Raspagem da Web com o Scrapy: A maneira fácil
Mihai Maxim em Jan 30 2023

Raspagem da Web com o Scrapy
Scrapy é uma poderosa biblioteca Python para extrair dados de sites. É rápida, eficiente e fácil de usar - confie em mim, já passei por isso. Quer seja um cientista de dados, um programador ou alguém que adora brincar com dados, o Scrapy tem algo para lhe oferecer. E o melhor de tudo é que é gratuito e de código aberto.
Os projectos Scrapy vêm com uma estrutura de ficheiros que o ajuda a organizar o seu código e dados. Facilita a criação e manutenção de raspadores da Web, pelo que vale a pena considerar se estiver a planear fazer uma raspagem séria da Web. Web scraping com Scrapy É como ter um assistente útil (embora virtual) ao seu lado enquanto embarca na sua viagem de extração de dados.
O que vamos construir
Quando se está a aprender uma nova habilidade, uma coisa é ler sobre ela e outra coisa é realmente fazê-la. É por isso que decidimos construir um scraper juntos, à medida que avançamos neste guia. É a melhor maneira de obter uma compreensão prática de como funciona o web scraping com o Scrapy.
Então, o que é que vamos construir, exatamente? Vamos construir um raspador que recolhe as definições de palavras do sítio Web do Urban Dictionary. É um alvo divertido para a recolha de dados e ajudará a tornar o processo de aprendizagem mais agradável. O nosso scraper será simples - devolverá as definições de várias palavras encontradas no sítio Web do Urban Dictionary. Utilizaremos o suporte integrado do Scrapy para selecionar e extrair dados de documentos HTML para extrair as definições de que necessitamos.
Então, vamos começar! Na próxima secção, iremos rever os pré-requisitos necessários para seguir este tutorial. Até lá!
Pré-requisitos
Antes de mergulharmos na construção do nosso scraper, há algumas coisas que você precisará configurar. Nesta secção, iremos abordar como instalar o Scrapy e configurar um ambiente virtual para o nosso projeto. A documentação do Scrapy sugere a instalação do Scrapy em um ambiente virtual dedicado. Ao fazer isso, você evitará quaisquer conflitos com os pacotes do seu sistema.
Estou a executar o Scrapy no Ubuntu 22.04.1 WSL (Windows Subsystem for Linux), por isso vou configurar um ambiente virtual para a minha máquina.
Aconselho-o a ler o capítulo "Compreender a estrutura das pastas" para compreender totalmente as ferramentas com que estamos a trabalhar. Além disso, dê uma olhadela ao capítulo "Scrapy Shell", que tornará a sua experiência de desenvolvimento muito mais fácil.
Configurar um ambiente virtual Python
Para configurar um ambiente virtual para Python no Ubuntu, você pode usar o comando mkvirtualenv. Primeiro, certifique-se de que tem o virtualenv e o virtualenvwrapper instalados:
$ sudo apt-get install virtualenv virtualenvwrapper
Adicione estas linhas no final do seu ficheiro .bashrc:
export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/Deve
export VIRTUALENVWRAPPER_PYTHON='/usr/bin/python3'
source /usr/local/bin/virtualenvwrapper.sh
Utilizei o Vim para editar o ficheiro, mas pode escolher o editor que quiser:
vim ~/.bashrc
// Use ctr + i para entrar no modo de inserção, use a seta para baixo para ir até o final do arquivo.
// Cole as linhas no final do arquivo.
// Pressione escape para sair do modo de inserção, digite wq e pressione enter para salvar as alterações e sair do Vim.
Em seguida, crie um novo ambiente virtual com mkvirtualenv:
$ mkvirtualenv scrapy_env
Agora deve ver um (scrapy_env) anexado no início da sua linha de terminal.
Para sair do ambiente virtual, digite $ deactivate
Para voltar ao ambiente virtual scrappy_env, digite $ workon scrapy_env
Instalando o Scrapy
Pode instalar o Scrapy com o gestor de pacotes pip:
$ pip install scrapy
Isto irá instalar a versão mais recente do Scrapy.
É possível criar um novo projeto com o comando scrapy startproject:
$ scrapy startproject myproject
Isto irá inicializar um novo projeto Scrapy chamado "myproject". Ele deve conter a estrutura padrão do projeto.
Compreender a estrutura de pastas
Esta é a estrutura de projeto predefinida:
myproject
├── myproject
│ ├── __init__.py
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── settings.py
│ └── spiders
│ └── __init__.py
└── scrapy.cfg
items.py
items.py é um modelo para os dados extraídos. Este modelo será utilizado para armazenar os dados que extrai do sítio Web.
Exemplo:
import scrapy
class Product(scrapy.Item):
name = scrapy.Field()
price = scrapy.Field()
description = scrapy.Field()
Aqui definimos um Item chamado Produto. Este pode ser utilizado por uma Spider (ver /spiders) para armazenar informações sobre o nome, o preço e a descrição de um produto.
/aranhas
/spiders é uma pasta que contém as classes Spider. No Scrapy, as Spiders são classes que definem como um site deve ser raspado.
Exemplo:
import scrapy
from myproject.items import Product
class MySpider(scrapy.Spider):
name = 'myspider'
start_urls = ['<example_website_url>']
def parse(self, response):
# Extract the data for each product
for product_div in response.css('div.product'):
product = Product()
product['name'] = product_div.css('h3.name::text').get()
product['price'] = product_div.css('span.price::text').get()
product['description'] = product_div.css('p.description::text').get()
yield product
O "spider" percorre as start_urls, extrai o nome, o preço e a descrição de todos os produtos encontrados nas páginas (utilizando selectores css) e armazena os dados no Product Item (ver items.py). De seguida, "produz" estes itens, o que faz com que o Scrapy os passe para o componente seguinte no pipeline (ver pipelines.py).
Yield é uma palavra-chave em Python que permite que uma função devolva um valor sem terminar a função. Em vez disso, produz o valor e suspende a execução da função até que o próximo valor seja solicitado.
Por exemplo:
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
for number in count_up_to(5):
print(number)
// returns 1 2 3 4 5 (each on a new line)
pipelines.py
Os pipelines são responsáveis pelo processamento dos itens (ver items.py e /spiders) que são extraídos pelos spiders. Pode utilizá-los para limpar o HTML, validar os dados e exportá-los para um formato personalizado ou guardá-los numa base de dados.
Exemplo:
import pymongo
class MongoPipeline(object):
def __init__(self):
self.conn = pymongo.MongoClient('localhost', 27017)
self.db = self.conn['mydatabase']
self.product_collection = self.db['products']
self.other_collection = self.db['other']
def process_item(self, item, spider):
if spider.name == 'product_spider':
//insere o item na colecção_de_produtos
elif spider.name == 'other_spider':
//inserir item na coleção other_collection
return item
Criámos um Pipeline chamado MongoPipeline. Ele se conecta a duas coleções do MongoDB (product_collection e other_collection). O pipeline recebe itens (veja items.py) de spiders (veja /spiders) e os processa na função process_item. Neste exemplo, a função process_item adiciona os itens às suas coleções designadas.
settings.py
O settings.py armazena uma variedade de configurações que controlam o comportamento do projeto Scrapy, como os pipelines, middlewares e extensões que devem ser usados, bem como configurações relacionadas a como o projeto deve lidar com solicitações e respostas.
Por exemplo, pode utilizá-lo para definir a ordem de execução dos pipelines (ver pipelines.py):
ITEM_PIPELINES = {
'myproject.pipelines.MongoPipeline': 300,
'myproject.pipelines.JsonPipeline': 302,
}
// MongoPipeline will execute before JsonPipeline, because it has a lower order number(300)
Ou definir um contentor de exportação:
FEEDS = {
'items': {'uri': 'file:///tmp/items.json', 'format': 'json'},
}
// this will save the scraped data to a items.json
scrappy.cfg
scrapy.cfg é o ficheiro de configuração para as definições principais do projeto.
[definições]
predefinição = [nome do projeto].definições
[implantação]
#url = http://localhost:6800/
projeto = [nome do projeto]
middlewares.py
Existem dois tipos de middlewares no Scrapy: middlewares downloader e middlewares spider.
Os middlewares de download são componentes que podem ser utilizados para modificar solicitações e respostas, tratar erros e implementar lógica de download personalizada. Eles estão situados entre o spider e o downloader do Scrapy.
Os middlewares Spider são componentes que podem ser utilizados para implementar uma lógica de processamento personalizada. Eles estão situados entre o motor e a aranha.
A concha de sucata
Antes de embarcarmos na excitante jornada de implementação do nosso scraper do Urban Dictionary, devemos primeiro familiarizar-nos com o Scrapy Shell. Esta consola interactiva permite-nos testar a nossa lógica de scraping e ver os resultados em tempo real. É como uma caixa de areia virtual onde podemos brincar e afinar a nossa abordagem antes de soltar a nossa Aranha na web. Confie em mim, isso vai poupar muito tempo e dor de cabeça a longo prazo. Então vamos nos divertir e conhecer o Scrapy Shell.
Abrir a concha
Para abrir o Scrapy Shell, primeiro terá de navegar para o diretório do seu projeto Scrapy no seu terminal. Depois, basta executar o seguinte comando:
shell scrapy
Isto irá abrir o Scrapy Shell e ser-lhe-á apresentado um prompt onde pode introduzir e executar comandos Scrapy. Também pode passar um URL como argumento para o comando da shell para recolher diretamente uma página web, desta forma:
scrapy shell <url>
Por exemplo:
shell scrapy https://www.urbandictionary.com/define.php?term=YOLO
Devolverá (no objeto de resposta) o html da página Web que contém as definições da palavra YOLO (no Urban Dictionary).
Em alternativa, depois de entrar na shell, pode utilizar o comando fetch para ir buscar uma página Web.
fetch('https://www.urbandictionary.com/define.php?term=YOLO')
Também pode iniciar a shell com o parâmetro nolog para que não mostre os registos:
shell do scrapy --nolog
Trabalhar com o shell
Neste exemplo, fui buscar o URL "https://www.urbandictionary.com/define.php?term=YOLO" e guardei o html no ficheiro test_output.html.
(scrapy_env) mihai@DESKTOP-0RN92KH:~/myproject$ scrapy shell --nolog
[s] Available Scrapy objects:
[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s] crawler <scrapy.crawler.Crawler object at 0x7f1eef80f6a0>
[s] item {}
[s] settings <scrapy.settings.Settings object at 0x7f1eef80f4c0>
[s] Useful shortcuts:
[s] fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s] fetch(req) Fetch a scrapy.Request and update local objects
[s] shelp() Shell help (print this help)
[s] view(response) View response in a browser
>>> response // response is empty
>>> fetch('https://www.urbandictionary.com/define.php?term=YOLO')
>>> response
<200 https://www.urbandictionary.com/define.php?term=Yolo>
>>> with open('test_output.html', 'w') as f:
... f.write(response.text)
...
118260
Agora, vamos inspecionar o ficheiro test_output.html e identificar os selectores de que precisamos para extrair os dados para o nosso scraper do Urban Dictionary.

Podemos observar isso:
- Cada contentor de definição de palavras tem a classe "definition".
- O significado da palavra encontra-se no interior da div com a classe "significado".
- Os exemplos da palavra encontram-se no interior da div com a classe "example".
- As informações sobre o autor e a data da publicação encontram-se na div com a classe "contributor".
Agora vamos testar alguns selectores no Scrapy Shell:
Para obter referências a todos os contentores de definição, podemos utilizar selectores CSS ou XPath:
Pode saber mais sobre os selectores XPath aqui: https://www.webscrapingapi.com/the-ultimate-xpath-cheat-sheet
definições = response.css('div.definition')
definições = response.xpath('//div[contains(@class, "definition")]')
Devemos extrair o significado, o exemplo e a informação de publicação de cada contentor de definição. Vamos testar alguns selectores com o primeiro contentor:
>>> first_def = definitions[0]
>>> meaning = first_def.css('div.meaning').xpath(".//text()").extract()
>>> meaning
['Yolo ', 'means', ', '', 'You Only Live Once', ''.']
>>> meaning = "".join(meaning)
>>> significado
'Yolo significa, 'Só se vive uma vez'.'
>>> exemplo = first_def.css('div.example').xpath(".//text()").extract()
>>> exemplo = "".join(example)
>>> exemplo
'"Põe o cinto de segurança." Jessica disse.\r "HAH, YOLO!" Responde a Anna.\r(Depois, têm um acidente de carro. Resumindo... Usa o cinto de segurança.)'
>>> post_data = first_def.css('div.contributor').xpath(".//text()").extract()
>>> post_data
['by ', 'Soy ugly', ' April 24, 2019']
Ao utilizar o shell Scrapy, conseguimos encontrar rapidamente um seletor geral que se adequa às nossas necessidades.
definition.css('div.<meaning|example|contributor>').xpath(".//text()").extract()
// returns an array with all the text found inside the <meaning|example|contributor>
ex: ['Yolo ', 'means', ', '', 'You Only Live Once', ''.']
Para saber mais sobre os selectores Scrapy, consulte a documentação. https://docs.scrapy.org/en/latest/topics/selectors.html
Implementar o scraper do Urban Dictionary
Bom trabalho! Agora que já apanhou o jeito de usar o Scrapy Shell e compreende o funcionamento interno de um projeto Scrapy, está na altura de mergulhar na implementação do nosso scraper Urban Dictionary. Por esta altura, já se deve sentir confiante e pronto para assumir a tarefa de extrair todas aquelas definições de palavras hilariantes (e por vezes questionáveis) da web. Então, sem mais delongas, vamos começar a construir nosso coletor de dados!
Definição de um item
Primeiro, vamos implementar um Item: (veja items.py)
class UrbanDictionaryItem(scrapy.Item):
meaning = scrapy.Field()
author = scrapy.Field()
date = scrapy.Field()
example = scrapy.Field()
Esta estrutura conterá os dados extraídos da Spider.
Definição de uma aranha
É assim que vamos definir a nossa Aranha (ver /spiders):
importar scrapy
from ..items import UrbanDictionaryItem
classe UrbanDictionarySpider(scrapy.Spider):
nome = "urban_dictionary" (dicionário urbano)
start_urls = ['https://www.urbandictionary.com/define.php?term=Yolo']
def parse(self, response):
definições = response.css('div.definition')
para definição em definições:
item = UrbanDictionaryItem()
item['meaning'] = definition.css('div.meaning').xpath(".//text()").extract()
item['example'] = definition.css('div.example').xpath(".//text()").extract()
author = definition.css('div.contributor').xpath(".//text()").extract()
item['data'] = autor[2]
item['autor'] = autor[1]
item de rendimento
Para executar o spider urban_dictionary, use o seguinte comando:
scrapy crawl urban_dictionary
// os resultados devem aparecer na consola (muito provavelmente no topo dos registos)
Criar um pipeline
Nesta altura, os dados não estão higienizados.
{'author': 'Soy ugly',
'date': ' April 24, 2019',
'example': ['“Put your ',
'seatbelt',
' on.” Jessica said.\n',
'“HAH, YOLO!” Replies Anna.\n',
'(They then proceed to have a ',
'car crash',
'. ',
'Long story short',
'...Wear a seatbelt.)'],
'meaning': ['Yolo ', 'means', ', ‘', 'You Only Live Once', '’.']}
Queremos modificar os campos "example" e "meaning" para conter strings, não arrays. Para o fazer, vamos escrever um Pipeline (ver pipelines.py) que transformará os arrays em strings concatenando as palavras.
class SanitizePipeline:
def process_item(self, item, spider):
# Sanitize o campo 'meaning'
item['meaning'] = "".join(item['meaning'])
# Sanitize o campo 'example'
item['example'] = "".join(item['example'])
# Sanitize the 'date' field
item['date'] = item['date'].strip()
return item
//ex: ['Yolo ', 'means', ', '', 'You Only Live Once', ''.'] turns to
'Yolo significa, 'You Only Live Once'.'
Ativar o Pipeline
Depois de definirmos o Pipeline, precisamos de o ativar. Se não o fizermos, então os nossos objectos UrbanDictionaryItem não serão higienizados. Para fazer isso, adicione-o ao seu arquivo settings.py (veja settings.py):
ITEM_PIPELINES = {
'myproject.pipelines.SanitizePipeline': 1,
}
Enquanto isso, pode também especificar um ficheiro de saída para os dados extraídos serem colocados.
FEEDS = {
'items': {'uri': 'file:///tmp/items.json', 'format': 'json'},
}
// this will put the scraped data in an items.json file.
Opcional: Implementação de um Middleware Proxy
A recolha de dados da Web pode ser um pouco complicada. Um dos principais problemas com que nos deparamos frequentemente é o facto de muitos sítios Web necessitarem de renderização de javascript para apresentarem totalmente o seu conteúdo. Isto pode causar enormes problemas para nós, enquanto web scrapers, uma vez que as nossas ferramentas muitas vezes não têm a capacidade de executar javascript como um navegador web normal faz. Isto pode levar a que sejam extraídos dados incompletos ou, pior ainda, que o nosso IP seja banido do sítio Web por fazer demasiados pedidos num curto período de tempo.
A nossa solução para este problema é o WebScrapingApi. Com o nosso serviço, pode simplesmente fazer pedidos à API e ela tratará de todo o trabalho pesado por si. Executará JavaScript, rodará proxies e até tratará de CAPTCHAs, assegurando que pode fazer scraping até dos sites mais teimosos com facilidade.
Um middleware proxy encaminhará cada pedido de busca feito pelo Scrapy para o servidor proxy. O servidor proxy então fará a requisição para nós e então retornará o resultado.
Primeiro, vamos definir uma classe ProxyMiddleware dentro do arquivo middlewares.py.
import base64
class ProxyMiddleware:
def process_request(self, request, spider):
# Set the proxy for the request
request.meta['proxy'] = "http://proxy.webscrapingapi.com:80"
request.meta['verify'] = False
# Set the proxy authentication for the request
proxy_user_pass = "webscrapingapi.proxy_type=residential.render_js=1:<API_KEY>"
encoded_user_pass = base64.b64encode(proxy_user_pass.encode()).decode()
request.headers['Proxy-Authorization'] = f'Basic {encoded_user_pass}'
Neste exemplo, utilizámos o servidor proxy WebScrapingApi.
webscrapingapi.proxy_type=residential.render_js=1 is the proxy authentication username, <API_KEY> the password.
Pode obter uma API_KEY gratuita criando uma nova conta em https://www.webscrapingapi.com/
Depois de definirmos o ProxyMiddleware, tudo o que precisamos de fazer é activá-lo como DOWNLOAD_MIDDLEWARE no ficheiro settings.py.
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.ProxyMiddleware': 1,
}
E é isso. Como pode ver, a recolha de dados da Web com o Scrapy pode simplificar muito do nosso trabalho.
Concluir
Conseguimos! Construímos um scraper que pode extrair definições do Urban Dictionary e aprendemos muito sobre o Scrapy ao longo do caminho. Desde a criação de itens personalizados até à utilização de middlewares e pipelines, provámos o quão poderoso e versátil pode ser o web scraping com o Scrapy. E a melhor parte? Ainda há muito mais para descobrir.
Parabéns por ter chegado ao fim desta viagem comigo. Agora, deve sentir-se confiante na sua capacidade de enfrentar qualquer projeto de Web scraping que surja no seu caminho. Lembre-se de que a raspagem da Web não precisa de ser assustadora ou esmagadora. Com as ferramentas e os conhecimentos certos, pode ser uma experiência divertida e gratificante. Se alguma vez precisar de ajuda, não hesite em contactar-nos em https://www.webscrapingapi.com/. Sabemos tudo sobre web scraping e teremos todo o gosto em ajudá-lo de todas as formas possíveis.
Notícias e actualizações
Mantenha-se atualizado com os mais recentes guias e notícias sobre raspagem da Web, subscrevendo a nossa newsletter.
We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

Artigos relacionados

Explore as complexidades da extração de dados de produtos da Amazon com nosso guia detalhado. De práticas recomendadas e ferramentas como a API Amazon Scraper a considerações legais, saiba como enfrentar desafios, contornar CAPTCHAs e extrair insights valiosos com eficiência.


Explore a comparação aprofundada entre o Scrapy e o Selenium para raspagem da Web. Desde a aquisição de dados em grande escala até o tratamento de conteúdo dinâmico, descubra os prós, os contras e os recursos exclusivos de cada um. Saiba como escolher a melhor estrutura com base nas necessidades e na escala do seu projeto.


Aprenda a extrair sites dinâmicos renderizados em JavaScript usando o Scrapy e o Splash. Desde a instalação até à escrita de um spider, à manipulação da paginação e à gestão das respostas do Splash, este guia abrangente oferece instruções passo a passo tanto para principiantes como para especialistas.
