A autora do artigo, cuja tradução estamos publicando hoje, diz que seu objetivo é falar sobre o desenvolvimento de um raspador de web em Python usando Selenium, que busca preços de passagem aérea. Ao procurar por ingressos, são usadas datas flexíveis (+ - 3 dias em relação às datas especificadas). O raspador salva os resultados da pesquisa em um arquivo do Excel e envia para a pessoa que o lançou um email com informações gerais sobre o que ele conseguiu encontrar. O objetivo deste projeto é ajudar os viajantes a encontrar as melhores ofertas.

Se você, ao lidar com o material, sentir que está perdido - dê uma olhada
neste artigo.
O que estamos procurando?
Você é livre para usar o sistema descrito aqui da maneira que desejar. Por exemplo, usei-o para procurar passeios e ingressos de fim de semana para minha cidade natal. Se você é sério em encontrar tickets lucrativos, pode executar o script no servidor (um
servidor simples, por 130 rublos por mês, é bastante adequado para isso) e executá-lo uma ou duas vezes por dia. Os resultados da pesquisa serão enviados por e-mail para você. Além disso, recomendo que você configure tudo para que o script salve o arquivo do Excel com os resultados da pesquisa na pasta Dropbox, que permite exibir esses arquivos de qualquer lugar e a qualquer momento.
Ainda não encontrei tarifas com erros, mas acredito que isso seja possívelAo pesquisar, como já foi dito, uma "data flexível" é usada, o script encontra ofertas dentro de três dias a partir das datas especificadas. Embora, ao iniciar o script, ele procure ofertas em apenas uma direção, é fácil refiná-lo para que ele possa coletar dados em várias direções dos voos. Com sua ajuda, você pode até procurar tarifas erradas, tais achados podem ser muito interessantes.
Por que preciso de outro raspador da web?
Quando comecei a raspagem na web, para ser sincero, não era particularmente interessante. Eu queria fazer mais projetos no campo da modelagem preditiva, análise financeira e, possivelmente, no campo de análise da coloração emocional dos textos. Mas acabou sendo muito interessante - descobrir como criar um programa que coleta dados de sites. Ao me aprofundar neste tópico, percebi que a raspagem da Web é o "mecanismo" da Internet.
Você pode decidir que esta é uma declaração muito ousada. Mas pense em como o Google começou com um raspador da Web criado por Larry Page usando Java e Python. O Googlebots está pesquisando e explorando a Internet, tentando fornecer a seus usuários as melhores respostas possíveis para suas perguntas. A raspagem da Web possui um número infinito de aplicativos e, mesmo se você, no campo da Ciência de Dados, estiver interessado em outra coisa, para obter dados para análise, você precisará de algumas habilidades de raspagem.
Alguns dos truques usados aqui foram encontrados em um
livro maravilhoso sobre raspagem na web, que adquiri recentemente. Nele você pode encontrar muitos exemplos e idéias simples sobre a aplicação prática dos estudados. Além disso, há um capítulo muito interessante sobre o desvio de teste do reCaptcha. Para mim, isso era novidade, pois eu não sabia que havia ferramentas especiais e serviços completos para resolver esses problemas.
Você gosta de viajar ?!
À pergunta simples e bastante inofensiva colocada no cabeçalho desta seção, muitas vezes é possível ouvir uma resposta positiva, fornecida com algumas histórias de viagem da pessoa a quem ela foi solicitada. Muitos de nós concordam que viajar é uma ótima maneira de mergulhar em novos ambientes culturais e expandir nossos horizontes. No entanto, se você perguntar a alguém se ele gosta de procurar passagens aéreas, tenho certeza de que a resposta estará longe de ser tão positiva. De fato, aqui o Python vem em socorro.
A primeira tarefa que precisamos resolver no caminho de criar um sistema de busca de informações sobre passagens aéreas é selecionar uma plataforma adequada com a qual obteremos informações. A solução para esse problema não foi fácil para mim, mas, no final, escolhi o serviço Kayak. Tentei os serviços de Momondo, Skyscanner, Expedia e um pouco mais, mas os mecanismos de proteção contra robôs nesses recursos eram impenetráveis. Depois de várias tentativas, durante as quais, ao tentar convencer os sistemas de que eu era humano, tive que lidar com semáforos, passagens para pedestres e bicicletas, decidi que o caiaque me convinha melhor, mesmo aqui também, se carregar muitas páginas em pouco tempo, as verificações também começam. Consegui fazer o bot enviar solicitações para o site em intervalos de 4 a 6 horas, e tudo funcionou bem. As dificuldades também surgem periodicamente ao trabalhar com o Kayak, mas se você começar a ser incomodado por verificações, precisará lidar com elas manualmente, iniciar o bot ou esperar algumas horas, e as verificações devem parar. Se necessário, você pode adaptar o código para outra plataforma e, se fizer isso, poderá denunciá-lo nos comentários.
Se você está começando o scraping na Web e não sabe por que alguns sites estão tendo problemas, antes de iniciar seu primeiro projeto nessa área, faça um favor a si mesmo e pesquise no Google por palavras "Etiqueta de raspagem na web". Seus experimentos podem terminar mais cedo do que você imagina se estiver envolvido de maneira irracional na raspagem da Web.
Introdução
Aqui está uma visão geral do que acontecerá no código do nosso raspador da Web:
- Importe as bibliotecas necessárias.
- Abra a guia Google Chrome.
- Chamando a função que lança o bot, passando a cidade e a data, que serão usadas na procura de ingressos.
- Esta função recebe os primeiros resultados da pesquisa, classificados pelos critérios dos mais atraentes (melhores), e pressiona o botão para carregar resultados adicionais.
- Outra função coleta dados da página inteira e retorna um quadro de dados.
- As duas etapas anteriores são executadas usando tipos de classificação pelo preço do bilhete (barato) e pela velocidade do vôo (mais rápida).
- Um email é enviado ao usuário do script contendo um breve resumo dos preços dos ingressos (os mais baratos e o preço médio), e o quadro de dados com informações classificadas pelos três indicadores mencionados acima é salvo como um arquivo do Excel.
- Todas as ações acima são executadas em um ciclo após um período especificado.
Note-se que todo projeto Selenium começa com um driver da web. Uso o
Chromedriver , trabalho com o Google Chrome, mas existem outras opções. Também populares são o PhantomJS e o Firefox. Depois de carregar o driver, você precisa colocá-lo na pasta apropriada, isso completa a preparação para o seu uso. As primeiras linhas do nosso script abrem uma nova guia Chrome.
Lembre-se de que, na minha história, não estou tentando abrir novos horizontes para encontrar ofertas lucrativas em passagens aéreas. Existem técnicas muito mais avançadas para encontrar essas ofertas. Eu só quero oferecer aos leitores deste material uma maneira simples, mas prática, de resolver esse problema.
Aqui está o código que falamos acima.
from time import sleep, strftime from random import randint import pandas as pd from selenium import webdriver from selenium.webdriver.common.keys import Keys import smtplib from email.mime.multipart import MIMEMultipart
No início do código, você pode ver os comandos de importação de pacotes usados em todo o nosso projeto. Portanto, o
randint
é usado para que o bot "adormeça" por um número aleatório de segundos antes de iniciar uma nova operação de pesquisa. Normalmente, nenhum bot pode ficar sem ele. Se você executar o código acima, uma janela do Chrome será aberta, a qual o bot usará para trabalhar com sites.
Vamos fazer um pequeno experimento e abrir o site kayak.com em uma janela separada. Escolha a cidade a partir da qual vamos voar, a cidade para a qual queremos chegar e as datas dos voos. Ao escolher as datas, verificaremos se o intervalo é de + -3 dias. Eu escrevi o código levando em consideração o que o site produz em resposta a esses pedidos. Se, por exemplo, você precisar procurar tickets apenas para determinadas datas, é altamente provável que você precise modificar o código bot. Falando sobre o código, faço explicações apropriadas, mas se você sentir que está confuso, me avise.
Agora clique no botão iniciar da pesquisa e veja o link na barra de endereço. Ele deve se parecer com o link que eu uso no exemplo abaixo, onde a variável
kayak
que armazena a URL é declarada e o método
get
do driver da web é usado. Depois de clicar no botão de pesquisa, os resultados devem aparecer na página.
Quando usei o comando
get
mais de duas a três vezes em alguns minutos, fui solicitado a passar em um teste usando o reCaptcha. Você pode passar por essa verificação manualmente e continuar as experiências até que o sistema decida organizar uma nova verificação. Quando testei o script, tive a sensação de que a primeira sessão de pesquisa sempre fica sem problemas; portanto, se você quiser experimentar o código, basta checá-lo manualmente periodicamente e deixar que o código seja executado usando longos intervalos entre as sessões de pesquisa. Sim, e se você pensar bem, é improvável que uma pessoa precise de informações sobre os preços dos ingressos recebidos em intervalos de 10 minutos entre as operações de pesquisa.
Trabalhando com uma Página Usando XPath
Então, abrimos a janela e carregamos o site. Para obter preços e outras informações, precisamos usar a tecnologia XPath ou seletores CSS. Eu decidi me debruçar sobre o XPath e não senti a necessidade de usar seletores CSS, mas é bem possível trabalhar assim. Mover uma página usando o XPath pode ser uma tarefa assustadora e, mesmo que você use os métodos que descrevi
neste artigo, que usavam a cópia dos identificadores correspondentes do código da página, percebi que essa não é a melhor maneira de acessar elementos necessários. A propósito,
neste livro, você pode encontrar uma excelente descrição dos conceitos básicos sobre como trabalhar com páginas usando os seletores XPath e CSS. Aqui está a aparência do método correspondente do driver da web.
Então, continuamos a trabalhar no bot. Aproveite o programa para selecionar os bilhetes mais baratos. Na imagem a seguir, o código do seletor XPath é destacado em vermelho. Para visualizar o código, você precisa clicar com o botão direito do mouse no elemento da página em que está interessado e selecionar o comando Inspecionar no menu exibido. Este comando pode ser chamado para diferentes elementos da página, cujo código será exibido e destacado na janela de visualização de código.
Exibir código da páginaPara encontrar confirmação do meu raciocínio sobre as desvantagens de copiar seletores do código, preste atenção aos seguintes recursos.
Aqui está o que você obtém ao copiar código:
//*[@id="wtKI-price_aTab"]/div[1]/div/div/div[1]/div/span/span
Para copiar algo semelhante, é necessário clicar com o botão direito do mouse na parte do código que lhe interessa e selecionar Copiar> Copiar XPath no menu exibido.
Aqui está o que eu usei para definir o botão Mais Barato:
cheap_results = '//a[@data-code = "price"]'
Copiar> Copiar Comando XPathÉ bastante óbvio que a segunda opção parece muito mais simples. Ao usá-lo, ele procura o elemento a, que possui o atributo de
data-code
igual ao
price
. Utilizando a primeira opção, é pesquisado um elemento
id
que é
wtKI-price_aTab
, e o caminho XPath para o elemento se parece com
/div[1]/div/div/div[1]/div/span/span
. Uma solicitação XPath semelhante a uma página fará o truque, mas apenas uma vez. Posso dizer agora que o
id
será alterado na próxima vez que a página for carregada. A
wtKI
caracteres
wtKI
muda dinamicamente toda vez que a página é carregada; como resultado, o código no qual ela é usada será inútil após a próxima página ser recarregada. Portanto, dedique algum tempo para descobrir o XPath. Este conhecimento irá atendê-lo bem.
No entanto, deve-se observar que a cópia de seletores XPath pode ser útil ao trabalhar com sites bastante simples e, se isso lhe convém, não há nada de errado nisso.
Agora, vamos pensar no que fazer se precisar obter todos os resultados da pesquisa em várias linhas, dentro da lista. Muito simples Cada resultado está dentro de um objeto com a classe
resultWrapper
. O download de todos os resultados pode ser feito em um loop semelhante ao mostrado abaixo.
Deve-se notar que, se você entende o que foi dito acima, deve entender facilmente a maior parte do código que analisaremos. No decorrer do trabalho desse código, nos voltamos para o que precisamos (de fato, este é o elemento no qual o resultado é agrupado) usando algum mecanismo para indicar o caminho (XPath). Isso é feito para obter o texto do elemento e colocá-lo em um objeto a partir do qual os dados podem ser lidos (primeiro use
flight_containers
, em seguida,
flights_list
).
As três primeiras linhas são exibidas e podemos ver claramente tudo o que precisamos. No entanto, temos maneiras mais interessantes de obter informações. Precisamos coletar dados de cada elemento separadamente.
Trabalhar!
É mais fácil escrever uma função para carregar resultados adicionais, então vamos começar com ela. Gostaria de maximizar o número de vôos sobre os quais o programa recebe informações e, ao mesmo tempo, não causar suspeitas no serviço que levam à verificação, por isso clico no botão Carregar mais resultados uma vez toda vez que a página é exibida. Neste código, você deve prestar atenção ao bloco
try
, que eu adicionei devido ao fato de que às vezes o botão não carrega normalmente. Se você também encontrar isso, comente as chamadas para essa função no código da função
start_kayak
, que discutiremos abaixo.
Agora, depois de uma longa análise dessa função (às vezes eu posso me deixar levar), estamos prontos para declarar uma função que lidará com a raspagem de página.
Eu já coletei a maior parte do necessário na próxima função chamada
page_scrape
. Às vezes, os dados retornados sobre os estágios do caminho acabam sendo combinados; para a separação deles, uso um método simples. Por exemplo, na primeira vez que utilizo as variáveis
section_a_list
e
section_b_list
. Nossa função retorna o quadro de dados
flights_df
, isso nos permite separar os resultados obtidos usando diferentes métodos de classificação de dados e depois combiná-los.
def page_scrape(): """This function takes care of the scraping part""" xp_sections = '//*[@class="section duration"]' sections = driver.find_elements_by_xpath(xp_sections) sections_list = [value.text for value in sections] section_a_list = sections_list[::2]
Tentei nomear as variáveis para que o código ficasse claro. Lembre-se de que as variáveis que começam com
a
referem-se ao primeiro passo do caminho
b
ao segundo. Vá para a próxima função.
Mecanismos auxiliares
Agora, temos uma função que permite carregar resultados de pesquisa adicionais e uma função para processar esses resultados. Este artigo pode ser concluído, pois essas duas funções fornecem tudo o necessário para raspar páginas que podem ser abertas independentemente. Mas ainda não consideramos alguns dos mecanismos auxiliares discutidos acima. Por exemplo, este é um código para enviar e-mails e outras coisas. Tudo isso pode ser encontrado na função
start_kayak
, que agora consideramos.
Para usar esta função, você precisa de informações sobre cidades e datas. Usando essas informações, ela forma um link na variável
kayak
, que é usada para ir para uma página que conterá os resultados da pesquisa classificados pela melhor correspondência. Após a primeira sessão de raspagem, trabalharemos com os preços na tabela na parte superior da página. Ou seja, encontramos o preço mínimo do ingresso e o preço médio. Tudo isso, juntamente com a previsão emitida pelo site, serão enviados por e-mail. Na página, a tabela correspondente deve estar no canto superior esquerdo. Trabalhar com esta tabela, a propósito, pode causar um erro ao pesquisar usando datas exatas, pois nesse caso a tabela não é exibida na página.
def start_kayak(city_from, city_to, date_start, date_end): """City codes - it's the IATA codes! Date format - YYYY-MM-DD""" kayak = ('https://www.kayak.com/flights/' + city_from + '-' + city_to + '/' + date_start + '-flexible/' + date_end + '-flexible?sort=bestflight_a') driver.get(kayak) sleep(randint(8,10))
Testei esse script usando uma conta do Outlook (hotmail.com). Não verifiquei o funcionamento correto da conta do Gmail, esse sistema de e-mail é muito popular, mas existem muitas opções possíveis. Se você usa uma conta do Hotmail, para que tudo funcione, basta inserir seus dados no código.
Se você deseja entender exatamente o que é executado em seções separadas do código dessa função, você pode copiá-las e experimentar com elas. As experiências com código são a única maneira de entendê-lo.
Sistema pronto
Agora que tudo o que falamos está pronto, podemos criar um loop simples no qual nossas funções são chamadas. O script solicita ao usuário dados sobre cidades e datas. Ao testar com uma reinicialização constante do script, é improvável que você insira esses dados manualmente a cada vez, para que as linhas correspondentes, durante a duração do teste, possam ser comentadas descomentando aquelas abaixo delas nas quais os dados necessários para o script são codificados.
city_from = input('From which city? ') city_to = input('Where to? ') date_start = input('Search around which departure date? Please use YYYY-MM-DD format only ') date_end = input('Return when? Please use YYYY-MM-DD format only ')
Aqui está a execução de teste do script.
Script de execução de testeSumário
Se você chegar a esse ponto - parabéns! Agora você tem um raspador de web em funcionamento, embora eu já veja muitas maneiras de melhorá-lo. Por exemplo, ele pode ser integrado ao Twilio para que, em vez de emails, envie mensagens de texto. Você pode usar uma VPN ou outra coisa para receber simultaneamente resultados de vários servidores. Há também um problema recorrente ao verificar se o usuário do site é uma pessoa, mas esse problema também pode ser resolvido. De qualquer forma, agora você tem uma base que pode ser expandida, se desejar. Por exemplo, para garantir que o arquivo do Excel seja enviado ao usuário como um anexo de um email.
