Neste tutorial, você aprenderá como o conteúdo que vê no navegador realmente é renderizado e como raspá-lo quando necessário. Em particular, você aprenderá como raspar comentários dinâmicos. Nossas ferramentas serão Python e pacotes incríveis como requests, BeautifulSoup e Selenium.
Quando você deve usar o Web Scraping?
A raspagem da Web é a prática de buscar automaticamente o conteúdo de páginas da Web projetadas para interação com usuários humanos, analisando-as e extraindo algumas informações (possivelmente links de navegação para outras páginas). Às vezes é necessário se não houver outra maneira de extrair as informações necessárias. Idealmente, o aplicativo fornece uma API dedicada para acessar seus dados programaticamente. Existem várias razões pelas quais a raspagem da web deve ser seu último recurso:
- É frágil (as páginas da web que você está copiando podem mudar com frequência).
- Pode ser proibido (alguns aplicativos da web têm políticas contra raspagem).
- Pode ser lento e expansivo (se você precisar buscar e percorrer muito barulho).
Compreendendo páginas da Web do mundo real
Vamos entender o que estamos enfrentando observando a saída de algum código de aplicativo da web comum. No artigo Introdução ao Vagrant,
Para extrair qualquer conteúdo desta página, primeiro precisamos encontrar os elementos HTML que contêm o conteúdo da página.
Ver fonte da página
Todos os navegadores desde o início dos tempos (década de 1990) suportam a capacidade de visualizar o HTML da página atual. Aqui está um trecho da fonte de visualização de Introdução ao Vagrant que começa com um grande pedaço de JavaScript minificado e feio não relacionado ao artigo em si. Aqui está um pequena parte dela:
Aqui está um HTML real da página:
Raspagem Estática vs. Raspagem Dinâmica
A raspagem estática ignora o JavaScript. Ele busca páginas da web do servidor sem a ajuda de um navegador. Você obtém exatamente o que vê em “visualizar fonte da página” e, em seguida, corta e corta. Se o conteúdo que você procura estiver disponível, você não precisa ir mais longe. No entanto, se o conteúdo estiver em um src
URL, você precisa de raspagem dinâmica.
A raspagem dinâmica usa um navegador real (ou um navegador sem cabeça) e permite que o JavaScript faça seu trabalho. Em seguida, ele consulta o DOM para extrair o conteúdo que está procurando. Às vezes, você precisa automatizar o navegador simulando um usuário para obter o conteúdo de que precisa.
Raspagem estática com solicitações e BeautifulSoup
Vamos ver como a raspagem estática funciona usando dois pacotes impressionantes do Python: solicitações para buscar páginas da Web e BeautifulSoup para analisar páginas HTML.
Instalando Requests e BeautifulSoup
Instale o pipenv primeiro e depois: pipenv install requests beautifulsoup4
Isso criará um ambiente virtual para você também. Se você estiver usando o código do gitlab, basta pipenv install
.
Buscando páginas
Buscar uma página com solicitações é uma linha: r = requests.get(url)
O objeto de resposta tem muitos atributos. Os mais importantes são ok
e content
. Se a solicitação falhar, então r.ok
será falso e r.content
conterá o erro. O conteúdo é um fluxo de bytes. Geralmente é melhor decodificá-lo para utf-8 ao lidar com texto:
1 |
>>> r = requests.get('https://www.c2.com/no-such-page') |
2 |
>>> r.ok |
3 |
False |
4 |
>>> print(r.content.decode('utf-8')) |
5 |
|
6 |
|
7 |
|
8 |
|
9 |
Not Found
|
10 |
The requested URL /ggg was not found on this server. |
11 |
|
12 |
|
13 |
Apache/2.0.52 (CentOS) Server at www.c2.com Port 80 |
14 |
|
15 |
|
Se estiver tudo bem então r.content
conterá a página da Web solicitada (igual à origem da página de exibição).
Encontrando elementos com BeautifulSoup
o get_page()
A função abaixo busca uma página da Web por URL, decodifica-a para UTF-8 e a analisa em um objeto BeautifulSoup usando o analisador HTML.
1 |
def get_page(url): |
2 |
r = requests.get(url) |
3 |
content = r.content.decode('utf-8') |
4 |
return BeautifulSoup(content, 'html.parser') |
Assim que tivermos um objeto BeautifulSoup, podemos começar a extrair informações da página. BeautifulSoup fornece muitas funções de localização para localizar elementos dentro da página e detalhar elementos aninhados profundamente.
As páginas de autor do Envato Tuts+ contêm vários tutoriais. Aqui está minha página de autor. Em cada página, há até 12 tutoriais. Se você tiver mais de 12 tutoriais, poderá navegar para a próxima página. O HTML para cada artigo está incluído em um
1 |
def get_page_articles(page): |
2 |
elements = page.findAll('article') |
3 |
articles = [e.a.attrs['href'] for e in elements] |
4 |
return articles |
O código a seguir pega todos os artigos da minha página e os imprime (sem o prefixo comum):
1 |
page = get_page('https://tutsplus.com/authors/gigi-sayfan') |
2 |
articles = get_page_articles(page) |
3 |
prefix = 'https://code.tutsplus.com/tutorials' |
4 |
for a in articles: |
5 |
print(a[len(prefix):]) |
6 |
|
7 |
Output: |
8 |
|
9 |
docker-from-the-ground-up-building-images--cms-28166 |
10 |
how-to-implement-your-own-data-structure-in-python--cms-28723 |
11 |
professional-error-handling-with-python--cms-25950 |
12 |
write-professional-unit-tests-in-python--cms-25835 |
13 |
how-to-write-package-and-distribute-a-library-in-python--cms-28693 |
14 |
serialization-and-deserialization-of-python-objects-part-1--cms-26183 |
15 |
understand-how-much-memory-your-python-objects-use--cms-25609 |
16 |
fetching-data-in-your-react-application--cms-30670 |
17 |
rest-vs-grpc-battle-of-the-apis--cms-30711 |
18 |
regular-expressions-with-go-part-2--cms-30406 |
19 |
regular-expressions-with-go-part-1--cms-30403 |
20 |
8-things-that-make-jest-the-best-react-testing-framework--cms-30534 |
Raspagem dinâmica com selênio
A raspagem estática foi boa o suficiente para obter a lista de artigos, mas se precisarmos automatizar o navegador e interagir com o DOM de forma interativa, uma das melhores ferramentas para o trabalho é Selênio.
O Selenium é voltado principalmente para testes automatizados de aplicativos da Web, mas é ótimo como uma ferramenta de automação de navegador de uso geral.
Instalando o Selenium
Digite este comando para instalar o Selenium: pipenv install selenium
Escolha seu driver da Web
O Selenium precisa de um driver da web (o navegador que ele automatiza). Para web scraping, geralmente não importa qual driver você escolhe. Eu prefiro o driver Chrome. Siga as instruções neste guia do Selenium.
Chrome vs. PhantomJS
Em alguns casos, você pode preferir usar um navegador headless, o que significa que nenhuma interface do usuário é exibida. Teoricamente, o PhantomJS é apenas outro driver da web. Mas, na prática, as pessoas relataram problemas de incompatibilidade em que o Selenium funciona corretamente com o Chrome ou o Firefox e às vezes falha com o PhantomJS. Prefiro remover essa variável da equação e usar um driver da web de navegador real.
Vamos fazer uma raspagem dinâmica e usar o Selenium para raspar os comentários de um plug-in Javascript codecanyon localizado ga-analytics#sendMarketClickEvent”>aqui. Aqui estão as importações necessárias.
1 |
from selenium import webdriver |
O próximo passo é criar um webdriver
instância e obtenha o URL de comentários.
1 |
driver = webdriver.Chrome() |
2 |
driver.get('https://codecanyon.net/item/whatshelp-whatsapp-help-and-support-plugin-for-javascript/42202303/comments') |
Depois de obter o URL, temos que encontrar o elemento onde os comentários estão localizados. Para fazer isso, clique com o botão direito do mouse na página da Web e clique em inspecionar, conforme mostrado abaixo.
Os comentários estão incluídos no commentList
Eu iria. Clique com o botão direito do mouse no elemento e copie o XPath conforme mostrado abaixo.
Em seguida, use o selênio para extrair o conteúdo do elemento que contém os comentários.
1 |
driver = webdriver.Chrome() |
2 |
driver.get('https://codecanyon.net/item/whatshelp-whatsapp-help-and-support-plugin-for-javascript/42202303/comments') |
3 |
modules = driver.find_elements('xpath','//*[@id="content"]/div/div[1]/div[4]') |
4 |
for comment in comments: |
5 |
print(comment.text) |
Aqui está a saída:
1 |
sunsuk |
2 |
20 days ago |
3 |
How to integrate to CI scripts? |
4 |
3 other replies |
5 |
ThemeAtelier AUTHOR |
6 |
20 days ago |
7 |
Yes. You can add 5 staffs. We have proper documentation how can you add it in your website. Please follow the instruction. You have to call usual js and CSS files then just need to put actual markup in the footer of your site. |
8 |
sunsuk |
9 |
20 days ago |
10 |
How to add wa number? Any admin dashboard ? |
11 |
ThemeAtelier AUTHOR |
12 |
20 days ago |
13 |
No admin. It just a script. So everything is code. You just need to change demo values to your own value. |
14 |
HTML knowledge is require for installing it.
|
15 |
Deezia12 |
16 |
29 days ago |
17 |
Hi Author, |
18 |
Does it work for a php website?
|
19 |
ThemeAtelier AUTHOR |
20 |
24 days ago |
21 |
Yes. As It will work in php websites.
|
22 |
gigantium |
23 |
about 1 month ago |
24 |
This is support for multiuser or for SAAS function? |
25 |
ThemeAtelier AUTHOR |
26 |
about 1 month ago |
27 |
It’s not a SAAS product to use for multiple users. You can use this in your single website with for giving chat support to your customers with single and multi user agents. |
28 |
gigantium |
29 |
about 1 month ago |
30 |
Thanks for your kind response. Can you provide a demo to access the admin dashboard?
|
31 |
ThemeAtelier AUTHOR |
32 |
about 1 month ago |
Existem alguns cenários em que o navegador precisa carregar algum conteúdo dinâmico; isso pode tornar o processo de raspagem um pouco mais complicado. Felizmente, o driver de selênio fornece wait()
objetos que esperam por um determinado período de tempo antes de localizar o elemento programaticamente.
Para usar a funcionalidade de espera, primeiro você precisa das seguintes importações:
1 |
from selenium import webdriver |
2 |
from selenium.webdriver.common.by import By |
3 |
from selenium.webdriver.support.wait import WebDriverWait |
4 |
from selenium.webdriver.support import expected_conditions as EC |
Em seguida, obtenha o url e aplique o wait()
objeto ao elemento.
1 |
driver = webdriver.Chrome() |
2 |
url = 'http://www.c2.com/loading-page' |
3 |
driver.get(url) |
4 |
|
5 |
element = WebDriverWait(driver, 5).until( |
6 |
EC.presence_of_element_located((By.ID, "loaded_element")) |
7 |
)
|
Conclusão
A raspagem da Web é uma prática útil quando as informações necessárias estão acessíveis por meio de um aplicativo da Web que não fornece uma API apropriada. É preciso algum trabalho não trivial para extrair dados de aplicativos da Web modernos, mas ferramentas maduras e bem projetadas, como solicitações, BeautifulSoup e Selenium, valem a pena.
Este post foi atualizado com contribuições de Esther Vaati. Esther é desenvolvedora de software e escritora da Envato Tuts+.