Python Language
Web-Scraping mit Python
Suche…
Einführung
Web-Scraping ist ein automatisierter, programmatischer Prozess, durch den Daten ständig von Webseiten "abgeschabt" werden können. Web Scraping, auch als Screen Scraping oder Web Harvesting bekannt, kann sofortige Daten von jeder öffentlich zugänglichen Webseite bereitstellen. Auf einigen Websites ist das Scraping von Websites möglicherweise illegal.
Bemerkungen
Nützliche Python-Pakete für das Web-Scraping (alphabetische Reihenfolge)
Anfragen stellen und Daten sammeln
requests
Ein einfaches, aber leistungsfähiges Paket für HTTP-Anfragen.
requests-cache
Caching für requests
; Das Zwischenspeichern von Daten ist sehr nützlich. In der Entwicklung bedeutet dies, dass Sie vermeiden müssen, eine Website unnötig zu treffen. Wenn Sie eine echte Sammlung ausführen, bedeutet dies, dass wenn Ihr Scraper aus irgendeinem Grund abstürzt (möglicherweise haben Sie nicht mit ungewöhnlichen Inhalten auf der Website umgegangen ...? Vielleicht ist die Website ausgefallen ...?), Können Sie die Sammlung sehr schnell wiederholen von wo du aufgehört hast.
scrapy
Nützlich für das Erstellen von Webcrawlern, bei denen Sie etwas Stärkeres benötigen, als requests
und Seiten zu durchlaufen.
selenium
Python-Bindungen für Selenium WebDriver zur Browser-Automatisierung. Mit requests
an HTTP - Anfragen direkt ist oft einfacher , für das Abrufen von Webseiten zu machen. Dies ist jedoch ein nützliches Werkzeug, wenn es nicht möglich ist, das gewünschte Verhalten einer Website nur mit requests
zu replizieren, insbesondere wenn JavaScript zum Rendern von Elementen auf einer Seite erforderlich ist.
HTML-Analyse
BeautifulSoup
Fragen Sie HTML- und XML-Dokumente mit einer Reihe verschiedener Parser ab (in Python integrierter HTML-Parser, html5lib
, lxml
oder lxml.html
).
lxml
Verarbeitet HTML und XML. Kann verwendet werden, um Inhalte aus HTML-Dokumenten über CSS-Selektoren und XPath abzufragen und auszuwählen.
Ein einfaches Beispiel für die Verwendung von Anforderungen und lxml zum Abwischen einiger Daten
# 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()
Web-Scraping-Sitzung mit Anforderungen verwalten
Es ist eine gute Idee, eine Web-Scraping-Sitzung durchzuführen, um die Cookies und andere Parameter beizubehalten. Zusätzlich kann es zu einer Leistungssteigerung führen , da requests.Session
die zugrunde liegende TCP - Verbindung zu einem Host wieder verwendet:
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)
Scraping mit dem Scrapy-Framework
Zuerst müssen Sie ein neues Scrapy-Projekt einrichten. Geben Sie ein Verzeichnis ein, in dem Sie Ihren Code speichern möchten, und führen Sie Folgendes aus:
scrapy startproject projectName
Zum Kratzen brauchen wir eine Spinne. Spider definieren, wie eine bestimmte Site abgestreift wird. Hier ist der Code für eine Spinne, die den Links zu den am häufigsten gestellten Fragen zu StackOverflow folgt und einige Daten von jeder Seite ( Quelle ) kratzt:
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,
}
Speichern Sie Ihre Spider-Klassen im Verzeichnis projectName\spiders
. In diesem Fall - projectName\spiders\stackoverflow_spider.py
.
Jetzt kannst du deine Spinne benutzen. Versuchen Sie beispielsweise (im Verzeichnis des Projekts) auszuführen:
scrapy crawl stackoverflow
Ändern Sie den Scrapy-Benutzeragenten
Manchmal wird der standardmäßige Scrapy-Benutzeragent ( "Scrapy/VERSION (+http://scrapy.org)"
) vom Host blockiert. Um den Standardbenutzeragenten zu ändern, öffnen Sie die Datei settings.py , entfernen Sie das Kommentarzeichen und bearbeiten Sie die folgende Zeile in die gewünschte Zeile.
#USER_AGENT = 'projectName (+http://www.yourdomain.com)'
Zum Beispiel
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'
Kratzen mit 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
Kratzen mit Selenium WebDriver
Einige Websites mögen es nicht, abgeschabt zu werden. In diesen Fällen müssen Sie möglicherweise einen echten Benutzer simulieren, der mit einem Browser arbeitet. Selen startet und steuert einen Webbrowser.
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)
Selen kann viel mehr. Es kann Browser-Cookies ändern, Formulare ausfüllen, Mausklicks simulieren, Screenshots von Webseiten erstellen und benutzerdefiniertes JavaScript ausführen.
Einfacher Download von Webinhalten mit urllib.request
Das Standardbibliotheksmodul urllib.request
kann zum Herunterladen von Webinhalten verwendet werden:
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)
Ein ähnliches Modul ist auch in Python 2 verfügbar.
Kratzen mit Locken
Importe:
from subprocess import Popen, PIPE
from lxml import etree
from io import StringIO
Wird heruntergeladen:
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
: stummer Download
-A
: Benutzeragentenflag
Parsing:
tree = etree.parse(StringIO(result), etree.HTMLParser())
divs = tree.xpath('//div')