Personnellement, je préfère utiliser la scrapy et le sélénium et docker les deux dans des conteneurs séparés. De cette façon, vous pouvez installer les deux avec un minimum de tracas et explorer des sites Web modernes qui contiennent presque tous du javascript sous une forme ou une autre. Voici un exemple:
Utilisez le scrapy startproject
pour créer votre grattoir et écrire votre araignée, le squelette peut être aussi simple que ceci:
import scrapy
class MySpider(scrapy.Spider):
name = 'my_spider'
start_urls = ['https://somewhere.com']
def start_requests(self):
yield scrapy.Request(url=self.start_urls[0])
def parse(self, response):
# do stuff with results, scrape items etc.
# now were just checking everything worked
print(response.body)
La vraie magie se produit dans le middlewares.py. Remplacez deux méthodes dans le middleware du téléchargeur __init__
et process_request
, de la manière suivante:
# import some additional modules that we need
import os
from copy import deepcopy
from time import sleep
from scrapy import signals
from scrapy.http import HtmlResponse
from selenium import webdriver
class SampleProjectDownloaderMiddleware(object):
def __init__(self):
SELENIUM_LOCATION = os.environ.get('SELENIUM_LOCATION', 'NOT_HERE')
SELENIUM_URL = f'http://{SELENIUM_LOCATION}:4444/wd/hub'
chrome_options = webdriver.ChromeOptions()
# chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
self.driver = webdriver.Remote(command_executor=SELENIUM_URL,
desired_capabilities=chrome_options.to_capabilities())
def process_request(self, request, spider):
self.driver.get(request.url)
# sleep a bit so the page has time to load
# or monitor items on page to continue as soon as page ready
sleep(4)
# if you need to manipulate the page content like clicking and scrolling, you do it here
# self.driver.find_element_by_css_selector('.my-class').click()
# you only need the now properly and completely rendered html from your page to get results
body = deepcopy(self.driver.page_source)
# copy the current url in case of redirects
url = deepcopy(self.driver.current_url)
return HtmlResponse(url, body=body, encoding='utf-8', request=request)
N'oubliez pas d'activer cet intermédiaire en décommentant les lignes suivantes dans le fichier settings.py:
DOWNLOADER_MIDDLEWARES = {
'sample_project.middlewares.SampleProjectDownloaderMiddleware': 543,}
Ensuite pour l'ancrage. Créez votre à Dockerfile
partir d'une image légère (j'utilise python Alpine ici), copiez-y le répertoire de votre projet, installez les exigences:
# Use an official Python runtime as a parent image
FROM python:3.6-alpine
# install some packages necessary to scrapy and then curl because it's handy for debugging
RUN apk --update add linux-headers libffi-dev openssl-dev build-base libxslt-dev libxml2-dev curl python-dev
WORKDIR /my_scraper
ADD requirements.txt /my_scraper/
RUN pip install -r requirements.txt
ADD . /scrapers
Et enfin, rassemblez tout cela dans docker-compose.yaml
:
version: '2'
services:
selenium:
image: selenium/standalone-chrome
ports:
- "4444:4444"
shm_size: 1G
my_scraper:
build: .
depends_on:
- "selenium"
environment:
- SELENIUM_LOCATION=samplecrawler_selenium_1
volumes:
- .:/my_scraper
# use this command to keep the container running
command: tail -f /dev/null
Courez docker-compose up -d
. Si vous faites cela la première fois, cela prendra un certain temps pour récupérer le dernier sélénium / chrome autonome et créer votre image de grattoir.
Une fois que c'est fait, vous pouvez vérifier que vos conteneurs fonctionnent avec docker ps
et également vérifier que le nom du conteneur de sélénium correspond à celui de la variable d'environnement que nous avons passée à notre conteneur de racleur (ici, c'était le cas SELENIUM_LOCATION=samplecrawler_selenium_1
).
Entrez votre conteneur de grattoir avec docker exec -ti YOUR_CONTAINER_NAME sh
, la commande pour moi était docker exec -ti samplecrawler_my_scraper_1 sh
, cd dans le bon répertoire et exécutez votre grattoir avec scrapy crawl my_spider
.
Le tout est sur ma page github et vous pouvez l'obtenir d' ici