Acesso direto ao conteúdo
Logotipo Dicas-L, por Ricardo Burile
Visite também: Ipok ·  Segurança Linux ·  UnderLinux ·  VivaOLinux ·  LinuxSecurity ·  NoticiasLinux ·  BR-Linux ·  SoftwareLivre.org ·  [mais]   
 

Você está aqui: Home  → Arquivo Dicas-L

 

Lan University

Assine a Lista Dicas-L

Receba diariamente por email as dicas
de informática publicadas neste site
Para se descadastrar, clique aqui.

Rastreando pedidos no site dos Correios com Perl

Colaboração: Fernando Henrique Giorgetti

Data de Publicação: 14 de junho de 2011

Escrevi um script perl para acompanhamento de códigos de rastreio junto ao site dos correios. Ele mantém uma lista dos tracking numbers buscados, até que eles tenham sido entregues.

Seu uso é bem simples, basicamente:

  ./correios.pl
  
  TRACKINGNUMBER1 TRACKINGNUMBER2 ... TRACKINGNUMBERN

Uma vez executado, os códigos solicitados via linha de comando ficam armazenados num arquivo para futuras consultas. O script buscará pelos códigos armazenados no histórico e por todos os demais, passado por parâmetro (caso existam).

Exemplos:

  [fernando@localhost correios]$ ./correios.pl
  
  ES720931075BR
  State for all tracking numbers
  
  TRACKING NUMBER    | DATE             | STATUS
  ES720931075BR      | 24/05/2011 20:27 | ACF TRES AVENIDAS - LIMEIRA /SP Encaminhado
                                        Em trânsito para CTE CAMPINAS - VALINHOS/SP

O código acima, continuará armazenado e será buscado automaticamente, até que tenha sido entregue.

Supondo que agora eu queira buscar um outro tracking number, só será necessário informar o novo código, exemplo:

  [fernando@localhost correios]$ ./correios.pl
  
  ES696088008BR
  Previous state for stored tracking numbers
  TRACKING NUMBER    | DATE             | STATUS
  ES720931075BR      | 24/05/2011 20:27 | ACF TRES AVENIDAS - LIMEIRA /SP Encaminhado
                                        Em trânsito para CTE CAMPINAS - VALINHOS/SP
  
  State for all tracking numbers
  TRACKING NUMBER    | DATE             | STATUS
  ES696088008BR      | 11/03/2011 18:03 | CEE LIMEIRA - LIMEIRA/SP        Entregue
  ES720931075BR      | 24/05/2011 20:27 | ACF TRES AVENIDAS - LIMEIRA /SP Encaminhado
                                        Em trânsito para CTE CAMPINAS - VALINHOS/SP

Note que ele buscou o anterior (pois ainda não está marcado como "Entregue") e buscou o novo ES696088008BR. Esse último já foi entregue, portanto não será armazenado para futuras consultas, exemplo:

  [fernando@localhost correios]$ ./correios.pl
  
  Previous state for stored tracking numbers
  TRACKING NUMBER    | DATE             | STATUS
  ES720931075BR      | 24/05/2011 20:27 | ACF TRES AVENIDAS - LIMEIRA /SP Encaminhado
                                        Em trânsito para CTE CAMPINAS - VALINHOS/SP
  
  State for all tracking numbers
  TRACKING NUMBER    | DATE             | STATUS
  ES720931075BR      | 24/05/2011 20:27 | ACF TRES AVENIDAS - LIMEIRA /SP Encaminhado
                                        Em trânsito para CTE CAMPINAS - VALINHOS/SP

Segue o código fonte (download do código)

  #!/usr/bin/perl
  
  #
  # Author: Fernando H Giorgetti < fgiorgetti@gmail.com>
  # Date  : 08/27/2010
  #
  # Description:  Provides a friendly interface for tracking packages
  #               by keeping a list of all requested tracking numbers
  #              till they have been delivered
  #
  #               It only works with brazilian tracking numbers (thru the Correios website)
  #
  
  # Libraries
  use POSIX qw(strftime);
  use Env qw(HOME);
  
  #
  # General configuration
  #
  
  # Tracking numbers datafile
  $DATAFILE="$HOME/tracking_numbers.dat";
  
  # Flag that indicates whether to remove tracking numbers once delivered
  $REMOVE_COMPLETED=1;
  
  # Remove Tracking numbers that have no results (invalid not yet available)
  $REMOVE_NORESULTS=0;
  
  # State that indicates whether a package has been delivered
  $COMPLETED_STATE="Entregue";
  
  # URL for the Correios website
  $URL="http://websro.correios.com.br/sro_bin/txect01\$.QueryList?P_LINGUA=001&P_TIPO=001&P_COD_UNI=
  
  ";
  
  # Website output header (used to determine where relevant content starts)
  $HEADER="Data .*Local .*Situa";
  
  # Results header (Used when showing overall results)
  $RESULTSHEADER="TRACKING NUMBER    | DATE             | STATUS\n";
  
  # End of statuses string
  $ENDOFSTATUSES="____________________________________";
  
  #
  # Validate whether return code matches the expected code
  # and in case it does not match, show the error message and terminate
  #
  sub validateReturnCode {
  
        $code = $_;
        $expected = $_;
        $msg = $_;
  
        if ( $code != $expected ) {
                printf "%s\n", $msg;
                exit $code;
        }
  
  }
  
  #
  # Tries to create the DAT file
  # In case an error occurs, show an error message then exit
  #
  sub createDataFile {
  
        if ( ! -f $DATAFILE ) {
                system(touch, "$DATAFILE");
                validateReturnCode("$?", "0", "Error creating $DATAFILE");
        }
  
  }
  
  sub printTrackingNumberInfo {
  
        $trackingNumber = shift(@_);
        $date = shift(@_);
        $status = shift(@_);
        $status =~ s/< BR>/\n                                        /g;
  
        printf "%-18s | %s | %s\n", $trackingNumber, $date , $status;
  
  }
  
  #
  # Dumps the website and searches for the given tracking number's last status
  #
  sub dumpWebsite {
  
        # Reading given tracking number
        $TRACKINGNUMBER = shift(@_);
  
        # Dumping the website
        open(IN, "lynx -dump \"$URL$TRACKINGNUMBER\" |");
  
        # Reading content
        @data = < IN>;
  
        # Closing input
        close(IN);
  
        # Cleaning the status
        $date = strftime("%m/%d/%Y %H:%M", localtime);
        $STATUS = "";
  
        # Parsing response content
        $found = 0;
        if ( ! (grep {/$HEADER/} @data ) ) {
                $STATUS = "No data has been found";
        } else {
  
                # Found the header, proceeding
                foreach $line (@data) {
                        # Found the right line
                        if ($found == 1) {
                                chomp($line);
                                if ( $line =~ /([0-9]{2}\/[0-9]{2}\/[0-9]{4} [0-9]{2}:[0-9]{2})[ ]+(.*$)/ ) {
                                        # Found the 2nd latest status entry, time to skip
                                        if ($firstFound == 1) {
                                                last;
                                        }
                                        $date = $1;
                                        $STATUS = $2;
                                        $firstFound = 1;
                                } else {
                                        # Found the deadline
                                        if ( $line =~ /$ENDOFSTATUSES/ ) {
                                                last;
                                        }
  
                                        # Appending further lines to the status message
                                        $line =~ s/^\s+//;
                                        $STATUS .= sprintf("< BR>%s", $line);
                                }
                        }
  
                        # Found the header, mark found = 1 to read next line and skip
                        if ( $line =~ /$HEADER/ ) {
                                $found = 1;
                                $firstFound = 0;
                                next;
                        }
                }
  
        }
  
        # Displaying current status for given Tracking number
        printTrackingNumberInfo($TRACKINGNUMBER, $date , $STATUS);
        $LIST{$TRACKINGNUMBER}{status}="$STATUS";
        $LIST{$TRACKINGNUMBER}{date}="$date";
  
        # If STATUS means delivered and REMOVE_COMPLETED = 1, remove the tracking number from the list
        if (    ( $REMOVE_COMPLETED == 1 && $STATUS =~ /$COMPLETED_STATE$/ ) ||
                ( $REMOVE_NORESULTS && $found == 0) ) {
                delete $LIST{$TRACKINGNUMBER}{status};
                delete $LIST{$TRACKINGNUMBER}{date};
                delete $LIST{$TRACKINGNUMBER};
        }
  
  }
  
  #
  # Add all valid tracking numbers to the hash named LIST
  #
  sub pushTrackingNumbers {
  
        # Loop through all given tracking numbers
        foreach $trackingNumber (@_) {
  
                # Sanity check
                if ( $trackingNumber !~ /[A-Z0-9]+/ ) {
                        printf "Invalid tracking number: %s\n", $trackingNumber;
                        next;
                }
  
                # Add to the hash
                $LIST{$trackingNumber}{status} = "";
                $LIST{$trackingNumber}{date} = "";
  
        }
  
  }
  
  #
  # Serializes the active list of tracking numbers
  #
  sub serializeActiveList {
  
        # Opening output file
        open(OUT, ">$DATAFILE") or die "Could not open $DATAFILE";
  
        # Saving all tracking numbers and current status
        foreach $key (sort keys %LIST) {
                printf OUT "%s;%s;%s\n", $key, $LIST{$key}{date}, $LIST{$key}{status};
        }
  
        # Closing output file
        close(OUT);
  }
  
  #
  # Main Code
  #
  
  # Validating if lynx is installed
  open(LYNX, "lynx -version |") or die "Lynx must be installed! Exiting.";
  close(LYNX);
  
  # Hash of active tracking numbers
  %LIST = ();
  
  # Reading input tracking numbers
  pushTrackingNumbers(@ARGV);
  
  # Reading DAT file list and pushing to the LIST
  open(DATA, "<$DATAFILE");
  @LINES=< DATA>;
  close(DATA);
  
  # If there are stored tracking numbers, show a header
  if (scalar(@LINES) > 0) {
        printf "Previous state for stored tracking numbers\n";
        printf "%s", $RESULTSHEADER;
  }
  
  # Pushing stored tracking numbers to STORED array
  @STORED;
  foreach $line (@LINES) {
        if ( $line =~ /([A-Z0-9]+);(.*);(.*)/ ) {
                printTrackingNumberInfo($1, $2, $3);
                push(@STORED, "$1");
        }
  }
  
  pushTrackingNumbers(@STORED);
  printf "\n" if (scalar(@STORED) > 0);
  
  # Dumping the website for all valid tracking numbers
  if (scalar(keys %LIST) > 0) {
        printf "State for all tracking numbers\n";
        printf "%s", $RESULTSHEADER;
  
        foreach $trackingNumber (sort keys %LIST) {
                dumpWebsite($trackingNumber);
        }
  }
  
  # Saving the datafile
  serializeActiveList;

Acredito que possa ser útil pra mais gente, pois pra mim é muito útil :)

 

 

Veja a relação completa dos artigos de Fernando Henrique Giorgetti

Formato PDF
Newsfeed RSS
Formato para impressão
PDF RSS Imprimir

Referências Adicionais

Referências adicionais sobre os assuntos abordados neste site podem ser encontradas em nossa Bibliografia.

Avalie esta dica

  • Currently 2.97/5
  • 1
  • 2
  • 3
  • 4
  • 5

Avaliação: 3.0 /5 (1641 votos)

Opinião dos Leitores

Cláudio
06 Jul 2011, 09:24
Evandro,

Também tem a opção no site: http://www.irtrader.com.br/

Tem um sistema chamado Post Office Tracker. Nele basta cadastrar o código dos correios e a cada mudança de status é enviado um email para o usuário.

Cláudio
Evandro
06 Jul 2011, 09:20
Gostei de seu script,

Tentei aplica-lo, so que da erro.
nao consigo retorno.
lynx: Can't access startfile http://websro.correios.com.br

Fernando
15 Jun 2011, 13:22
A idéia foi mesmo automatizar (como um script shell) fazendo uso da poderosa engine de regexp do Perl apenas. Como é um script pra uso pessoal, não me preocupei, de fato, com segurança e com o uso de APIs para comunição HTTP, mesmo sabendo que elas já existem.

Mas obrigado pela avaliação. Vou dar uma olhada nos módulos e assim que possível faço um update.

Abraços.
Blabos
14 Jun 2011, 15:44
Cara,

Boa a intenção, mas o seu código está cheio de problemas e infringindo várias regras de boas práticas de programação em Perl.

Não tem nem um 'use strict', sem falar que você usa o lynx pra acessar uma URL, quando se tem o LWP, o WWW::Mechanize entre outros módulos.

Dê uma olhada em:

http://search.cpan.org/search?query=correios&mode=all

Eu aproveito pra te convidar a conhecer a comunidade Perl mais de perto. Acesse nossas listas e venha tomar umas cervejas com a gente:

http://rio.pm.org/lista.pl
http://sao-paulo.pm.org/lista

Que tal trocar uma ideia com a gente e atualizar o seu artigo com uma abordagem mais moderna? É sempre bom ter pessoas com essa disposição para escrever novos artigos!
Cláudio
14 Jun 2011, 09:01
Legal este seu script, parabéns.
Já que somos uma comunidade, também gostaria de compartilhar um software dentre outros: Post Tracker. Nele basta cadastrar o código dos correios e a cada mudança de status é enviado um email para o usuário.

http://www.irtrader.com.br/
*Nome:
Email:
Me notifique sobre novos comentários nessa página
Oculte meu email
*Texto:
 
  Para publicar seu comentário, digite o código contido na imagem acima
 


Powered by Scriptsmill Comments Script
3ª geração do Under Servidor Cloud




 

As Palavras Mais Comuns da Língua Inglesa - 2ª edição