Python Language
Web grattant avec Python
Recherche…
Introduction
Le Web scraping est un processus automatisé et programmé grâce auquel les données peuvent être constamment «grattées» sur les pages Web. Également connu sous le nom de récupération d'écran ou de collecte Web, le balayage Web peut fournir des données instantanées à partir de n'importe quelle page Web accessible au public. Sur certains sites Web, le raclage Web peut être illégal.
Remarques
Paquets Python utiles pour le web scraping (ordre alphabétique)
Faire des demandes et collecter des données
requests
Un package simple mais puissant pour faire des requêtes HTTP.
requests-cache
Mise en cache pour les requests
; la mise en cache des données est très utile. En développement, cela signifie que vous pouvez éviter de frapper un site inutilement. Lorsque vous exécutez une collection réelle, cela signifie que si votre racloir plante pour une raison quelconque (vous n'avez peut-être pas manipulé de contenu inhabituel sur le site ...? Peut-être que le site est tombé ...?) D'où tu t'es arrêté.
scrapy
Utile pour créer des robots d'indexation sur le Web, où vous avez besoin de quelque chose de plus puissant que l'utilisation de requests
et l'itération de pages.
selenium
Liaisons Python pour Selenium WebDriver, pour l'automatisation des navigateurs. L'utilisation de requests
pour effectuer directement des requêtes HTTP est souvent plus simple pour récupérer des pages Web. Cependant, cela reste un outil utile lorsqu'il n'est pas possible de reproduire le comportement souhaité d'un site à l'aide de requests
uniquement, en particulier lorsque JavaScript est requis pour rendre des éléments sur une page.
Analyse HTML
BeautifulSoup
Requête de documents HTML et XML à l'aide de plusieurs analyseurs (analyseur HTML intégré à Python, html5lib
, lxml
ou lxml.html
)
lxml
Traite HTML et XML. Peut être utilisé pour interroger et sélectionner du contenu à partir de documents HTML via des sélecteurs CSS et XPath.
Exemple de base d'utilisation de requêtes et de lxml pour récupérer des données
# For Python 2 compatibility.
from __future__ import print_function
import lxml.html
import requests
def main():
r = requests.get("https://httpbin.org")
html_source = r.text
root_element = lxml.html.fromstring(html_source)
# Note root_element.xpath() gives a *list* of results.
# XPath specifies a path to the element we want.
page_title = root_element.xpath('/html/head/title/text()')[0]
print(page_title)
if __name__ == '__main__':
main()
Maintenir la session Web-scraping avec les requêtes
Il est recommandé de conserver une session Web pour conserver les cookies et autres paramètres. En outre, cela peut entraîner une amélioration des performances, car requests.Session
réutilise la connexion TCP sous-jacente à un hôte:
import requests
with requests.Session() as session:
# all requests through session now have User-Agent header set
session.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'}
# set cookies
session.get('http://httpbin.org/cookies/set?key=value')
# get cookies
response = session.get('http://httpbin.org/cookies')
print(response.text)
Gratter en utilisant le cadre Scrapy
Vous devez d'abord créer un nouveau projet Scrapy. Entrez un répertoire dans lequel vous souhaitez stocker votre code et exécutez:
scrapy startproject projectName
Pour gratter, nous avons besoin d'une araignée. Les araignées définissent la manière dont un site donné sera raclé. Voici le code d'une araignée qui suit les liens vers les questions les plus votées sur StackOverflow et raconte certaines données de chaque page ( source ):
import scrapy
class StackOverflowSpider(scrapy.Spider):
name = 'stackoverflow' # each spider has a unique name
start_urls = ['http://stackoverflow.com/questions?sort=votes'] # the parsing starts from a specific set of urls
def parse(self, response): # for each request this generator yields, its response is sent to parse_question
for href in response.css('.question-summary h3 a::attr(href)'): # do some scraping stuff using css selectors to find question urls
full_url = response.urljoin(href.extract())
yield scrapy.Request(full_url, callback=self.parse_question)
def parse_question(self, response):
yield {
'title': response.css('h1 a::text').extract_first(),
'votes': response.css('.question .vote-count-post::text').extract_first(),
'body': response.css('.question .post-text').extract_first(),
'tags': response.css('.question .post-tag::text').extract(),
'link': response.url,
}
Enregistrez vos classes d'araignées dans le répertoire projectName\spiders
. Dans ce cas - nom du projectName\spiders\stackoverflow_spider.py
.
Vous pouvez maintenant utiliser votre araignée. Par exemple, essayez de courir (dans le répertoire du projet):
scrapy crawl stackoverflow
Modifier l'agent utilisateur Scrapy
Parfois, l'agent utilisateur Scrapy par défaut ( "Scrapy/VERSION (+http://scrapy.org)"
) est bloqué par l'hôte. Pour modifier l'agent utilisateur par défaut, ouvrez settings.py , décommentez et modifiez la ligne suivante selon vos souhaits.
#USER_AGENT = 'projectName (+http://www.yourdomain.com)'
Par exemple
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
Gratter à l'aide de BeautifulSoup4
from bs4 import BeautifulSoup
import requests
# Use the requests module to obtain a page
res = requests.get('https://www.codechef.com/problems/easy')
# Create a BeautifulSoup object
page = BeautifulSoup(res.text, 'lxml') # the text field contains the source of the page
# Now use a CSS selector in order to get the table containing the list of problems
datatable_tags = page.select('table.dataTable') # The problems are in the <table> tag,
# with class "dataTable"
# We extract the first tag from the list, since that's what we desire
datatable = datatable_tags[0]
# Now since we want problem names, they are contained in <b> tags, which are
# directly nested under <a> tags
prob_tags = datatable.select('a > b')
prob_names = [tag.getText().strip() for tag in prob_tags]
print prob_names
Scraping utilisant Selenium WebDriver
Certains sites Web n'aiment pas être effacés. Dans ces cas, vous devrez peut-être simuler un utilisateur réel travaillant avec un navigateur. Selenium lance et contrôle un navigateur Web.
from selenium import webdriver
browser = webdriver.Firefox() # launch firefox browser
browser.get('http://stackoverflow.com/questions?sort=votes') # load url
title = browser.find_element_by_css_selector('h1').text # page title (first h1 element)
questions = browser.find_elements_by_css_selector('.question-summary') # question list
for question in questions: # iterate over questions
question_title = question.find_element_by_css_selector('.summary h3 a').text
question_excerpt = question.find_element_by_css_selector('.summary .excerpt').text
question_vote = question.find_element_by_css_selector('.stats .vote .votes .vote-count-post').text
print "%s\n%s\n%s votes\n-----------\n" % (question_title, question_excerpt, question_vote)
Le sélénium peut faire beaucoup plus. Il peut modifier les cookies du navigateur, remplir des formulaires, simuler des clics de souris, réaliser des captures d'écran de pages Web et exécuter du code JavaScript personnalisé.
Téléchargement de contenu Web simple avec urllib.request
Le module de bibliothèque standard urllib.request
peut être utilisé pour télécharger du contenu Web:
from urllib.request import urlopen
response = urlopen('http://stackoverflow.com/questions?sort=votes')
data = response.read()
# The received bytes should usually be decoded according the response's character set
encoding = response.info().get_content_charset()
html = data.decode(encoding)
Un module similaire est également disponible dans Python 2 .
Grattage avec boucle
importations:
from subprocess import Popen, PIPE
from lxml import etree
from io import StringIO
Téléchargement:
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'
url = 'http://stackoverflow.com'
get = Popen(['curl', '-s', '-A', user_agent, url], stdout=PIPE)
result = get.stdout.read().decode('utf8')
-s
: téléchargement silencieux
-A
: drapeau de l'agent utilisateur
Analyse:
tree = etree.parse(StringIO(result), etree.HTMLParser())
divs = tree.xpath('//div')