Heim BlogWeb-Scraping Web Scraping in Python und Scrapy verstehen Web Scraping in Python verstehen

Web Scraping in Python und Scrapy verstehen Web Scraping in Python verstehen

von Kadek

Was ist Web Scraping?

Web Scraping ist eine automatisierte Methode, mit der große Mengen öffentlicher Daten von Websites extrahiert werden. Dabei werden Softwaretools verwendet, um durch Webseiten zu navigieren, die gewünschten Informationen abzurufen und sie zur weiteren Analyse oder Bearbeitung zu speichern.

Grundsätzlich ahmt Web Scraping die Aktionen eines menschlichen Benutzers beim Surfen auf einer Website nach, allerdings in einem viel schnelleren und effizienteren Tempo. Dieser Prozess umfasst typischerweise den Zugriff auf den HTML-Code einer Webseite, dessen Analyse, um die relevanten Daten zu finden, und das anschließende Extrahieren und Organisieren dieser Daten in einem strukturierten Format wie einer Tabelle oder einer Datenbank.

Web Scraping ist in verschiedenen Bereichen von unschätzbarem Wert geworden, darunter Datenwissenschaft, Marktforschung und Business Intelligence. Durch die Automatisierung des Prozesses der Datenerfassung aus Online-Quellen können Unternehmen schnell und effizient große Mengen an Informationen sammeln und so fundierte Entscheidungen treffen und Einblicke in die Wettbewerbsfähigkeit gewinnen.

Es ist jedoch wichtig zu beachten, dass die Rechtmäßigkeit und ethischen Überlegungen im Zusammenhang mit Web Scraping je nach den Nutzungsbedingungen der Website und der Art der erfassten Daten variieren – um nur einige zu nennen. Daher müssen Web-Scraping-Anwender Vorsicht walten lassen und sich an Best Practices halten, um die Einhaltung rechtlicher und ethischer Standards sicherzustellen.

Datenerfassung mit REST-APIs

Als Softwareentwickler sind wir es gewohnt, mit gut strukturierten oder zumindest halbstrukturierten Datenstrukturen umzugehen.

Wenn Daten zwischen Anwendungen ausgetauscht werden müssen, verwenden wir Serialisierungsformate wie XML, JSON oder ähnliche Formate. Dies ist besonders nützlich für den Datenaustausch über HTTP.

Eine ganze Reihe von Tools basiert auf APIs (Application Programming Interfaces), die auf HTTP basieren. Viele Unternehmen bieten ihren Kunden Zugriff auf ihre Systeme über REST-APIs (Representational State Transfer).

In Python können wir mit integrierten Modulen aus der Standardbibliothek auf REST-APIs zugreifen.

import urllib.request
import json

def get_weather_with_urllib(API_KEY, city):
   url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={API_KEY}"
   response = urllib.request.urlopen(url)
   return json.loads(response.read())

Der obige Code öffnet eine HTTP-Verbindung zu api.openweathermap.orgund führt dann einen GET-Vorgang für die API-Ressource unter aus /data/2.5/weather mit der urllib.request Modul. Das Ergebnis ist ein dateiähnliches Objekt, das mit dem JSON-Modul gelesen und analysiert werden kann.

Auch wenn dies ziemlich einfach aussieht, kann der Umgang mit komplexeren Anfragen, Statuscodes, verschiedenen HTTP-Verben, Sitzungsabwicklung und anderen Dingen zu langem Code führen.

Eine häufig verwendete Bibliothek eines Drittanbieters zum Verwalten von HTTP-Anfragen in Python ist Requests von Kenneth Reitz, einem Python-Programmierer, der in der Community für seine verschiedenen Beiträge und Softwarepakete bekannt ist.

Sie können Request installieren, indem Sie pip in Ihrer Befehlszeile verwenden:

python -m pip install requests

Mit Anfragen würde unser kleines Skript so aussehen:

import requests

def get_weather_with_requests(API_KEY, city):
   url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={API_KEY}"
   response = requests.get(url)
   return response.json()

Beachten Sie, dass der einzige Unterschied hier darin besteht, dass wir verwenden response.json anstatt json.loads(response.read()) um die Antwort zu analysieren. Hab Geduld mit mir. Wir werden weitere Beispiele sehen, bei denen das Anforderungsmodul glänzt.

REST-APIs

Als Softwareentwickler sind wir es gewohnt, mit gut strukturierten oder zumindest halbstrukturierten Datenstrukturen umzugehen. Wenn Daten zwischen Anwendungen ausgetauscht werden müssen, verwenden wir Serialisierungsformate wie XML, JSON oder ähnliche Formate.

Glücklicherweise sind viele APIs verfügbar, die eine große Auswahl an unterschiedlichen Datensätzen bieten.

Im Prinzip haben wir in der Einleitung bereits gesehen, wie man mit Python auf REST-APIs zugreift.

In diesem Mini-Guide liegt der Schwerpunkt auf Web Scraping, was bedeutet, dass wir größtenteils keinen Zugriff auf strukturierte Daten haben. Stattdessen müssen wir die Daten aus dem HTML-Code einer Website extrahieren.

Schöne Suppe

Denken Sie zum Beispiel an einen E-Commerce-Shop mit Hunderten von Produkten.

Die Daten sind oft nicht in maschinenlesbaren, strukturierten Formaten zugänglich* (* Das ist nur die halbe Wahrheit: HTML ist beispielsweise immer noch ein maschinenlesbares Format). Dies könnte daran liegen, dass der Website-Betreiber keinen Wert darin sieht, die Daten strukturiert bereitzustellen – oder daran, dass der Betreiber nicht möchte, dass die Daten von Robotern gecrawlt werden. Wir werden im letzten Kapitel sehen, wie man mit letzterem Fall umgeht.

BeautifulSoup ist eine Python-Bibliothek, die es einfach macht, Informationen aus Webseiten zu extrahieren. Es sitzt auf einem HTML- oder XML-Parser und stellt pythonische Redewendungen zum Iterieren, Durchsuchen und Ändern des Analysebaums bereit.

Es wird häufig zusammen mit der Anforderungsbibliothek verwendet, die zum Herunterladen des Webseiteninhalts verwendet wird. beautifulsoup wird dann zum Parsen des HTML-Inhalts verwendet.

Hier ist ein Beispiel dafür, wie Sie es verwenden können beautifulsoup Eine Website durchsuchen:

import requests
from bs4 import BeautifulSoup


url = "https://books.toscrape.com"


response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
book_titles = (a("title") for a in soup.select("h3 a"))

Scrapy

Scrapy ist ein leistungsstarkes und flexibles Web-Scraping-Framework, das in Python geschrieben ist. Betrachten Sie es als eine Kombination aus Requests und BeautifulSoup, aber mit viel mehr Funktionen.

Scrapy kann beispielsweise die Paginierung verarbeiten, indem es Links folgt und Daten aus JSON und XML extrahiert. Es bietet auch eine Möglichkeit, die extrahierten Daten in einer Datenbank zu speichern und Scraping-Jobs parallel auszuführen.

Mit Scrapy erstellen Sie eine „Spider“-Klasse, die definiert, wie eine Website gescrapt wird. Die Spider-Klasse enthält die Logik zum Extrahieren von Daten aus der Website und zum Verfolgen von Links zu anderen Seiten.

Bevor wir uns mit den Details befassen, finden Sie hier ein kurzes Beispiel einer Spider-Klasse für Scrapy:

import scrapy


class BooksSpider(scrapy.Spider):
   name = "books"
   start_urls = ("http://books.toscrape.com")


   def parse(self, response):
       for article in response.css('article.product_pod'):
           yield {
               'title': article.css("h3 > a::attr(title)").extract_first(),
               'price': article.css(".price_color::text").extract_first()
           }

In diesem Beispiel definieren wir eine Spider-Klasse namens BooksSpider, die die Website durchsucht http://books.toscrape.com. Die Parse-Methode wird mit der Antwort der Start-URL aufgerufen. Es extrahiert den Titel und den Preis jedes Buchs auf der Seite und erstellt ein Wörterbuch mit den extrahierten Daten.

Um den Spider auszuführen, können Sie den Code in einer Datei namens speichern Books_spider.py und führen Sie es mit dem aus scrapy runspider Befehl:

scrapy runspider books_spider.py

Im nächsten Eintrag dieses Mini-Guides werden wir tiefer in Scrapy eintauchen und seine Funktionen weiter erkunden.

Häufige Hindernisse beim Web Scraping

In diesem Abschnitt werden häufig auftretende Hindernisse beim Scraping von Websites behandelt. Die behandelten Themen sind:

  • Pagination
  • JavaScript / Clientseitiges Rendering
  • Bot-Erkennung
  • Sitzung und Anmeldung

1. Umgang mit Paginierungen

Die Paginierung ist ein häufiges Hindernis beim Scraping von Websites. Es unterteilt eine große Datenmenge in kleinere, besser verwaltbare Blöcke, indem es sie in Seiten aufteilt, die jeweils eine Teilmenge der Gesamtdaten enthalten. Paginierung wird häufig verwendet, um das Benutzererlebnis zu verbessern, indem die auf einer einzelnen Seite angezeigte Datenmenge reduziert und die Navigation durch den Inhalt erleichtert wird.

Beim Scrapen einer Website mit Paginierung müssen Sie überlegen, wie Sie durch die Seiten navigieren, um auf alle Daten zuzugreifen, die Sie scrapen möchten.

So könnte es mit aussehen beautifulsoup und Anfragen:

import requests
from bs4 import BeautifulSoup


url = "https://books.toscrape.com"


def get_entries(url):
   entries = ()
   response = requests.get(url)
   soup = BeautifulSoup(response.text, "html.parser")
   # Find all h3.a tags and extract the title attribute from the a tag
   entries += (a("title") for a in soup.select("h3 a"))
   # Find the next page link
   next_page = soup.select_one("li.next a")
   if next_page:
       next_page_url = requests.compat.urljoin(url, next_page("href"))
       entries += get_entries(next_page_url)
   return entries


get_entries(url)

Beachten Sie, dass wir uns manuell um den URL-Join kümmern müssen. Dies liegt daran, dass die href Attribut der a Tag enthält nur den relativen Pfad zur nächsten Seite. Wir müssen es mit der Basis-URL verknüpfen, um die vollständige URL zu erhalten.

Mit Scrapy können wir das verwenden response.follow Methode, um Links zu folgen. Diese Methode benötigt eine URL und eine Rückruffunktion als Argumente. Die Callback-Funktion wird mit der Antwort der neuen URL aufgerufen.

So könnte eine Scrapy-Spinne aussehen:

import scrapy

class BooksSpider(scrapy.Spider):
   name = "books"
   allowed_domains = ("books.toscrape.com")
   start_urls = ("http://books.toscrape.com")


   def parse(self, response):
       self.log(f"I just visited {response.url}")


       for article in response.css('article.product_pod'):
           yield {
               'title': article.css("h3 > a::attr(title)").extract_first(),
               'price': article.css(".price_color::text").extract_first()
           }


       next_page_url = response.css("li.next > a::attr(href)").get()
       if next_page_url:
           yield response.follow(url=next_page_url, callback=self.parse)

2. Clientseitiges Rendering

Wenn eine Website JavaScript zum Rendern ihres Inhalts verwendet, kann es schwierig sein, die Daten zu extrahieren. Der Grund dafür ist, dass der Inhalt nicht im HTML-Quellcode vorhanden ist, der vom Server zurückgegeben wird. Stattdessen wird der Inhalt durch den JavaScript-Code generiert, der im Browser ausgeführt wird.

Da Ihre Python-Skripte normalerweise kein JavaScript ausführen, können Sie nicht einfach Anfragen und verwenden beautifulsoup um die Daten zu kratzen. Sie müssen ein Tool verwenden, das JavaScript ausführen kann, z. B. Playwright.

Playwright ist eine Node.js-Bibliothek, die eine High-Level-API zur Automatisierung von Browsern bereitstellt. Es ermöglicht Ihnen, mit Webseiten auf eine Weise zu interagieren, die die Interaktion eines echten Benutzers mit einem Browser simuliert. Dies macht es ideal zum Scrapen von Websites, die zum Rendern von Inhalten JavaScript verwenden.

Wir können Dramatiker in unseren Scrapy-Spinnen einsetzen. Hier ist ein Beispiel dafür, wie Sie Playwright zum Scrapen einer Website mit clientseitigem Rendering verwenden können:

import scrapy
from playwright.sync_api import sync_playwright


class QuotesSpider(scrapy.Spider):
   name = 'quotes'
   start_urls = ('http://quotes.toscrape.com/js')


   def parse(self, response):
       with sync_playwright() as p:
           browser = p.chromium.launch()
           page = browser.new_page()
           page.goto(response.url)
           quotes = page.query_selector_all('.quote')
           for quote in quotes:
               yield {
                   'text': quote.query_selector('.text').inner_text(),
                   'author': quote.query_selector('.author').inner_text(),
                   'tags': (tag.inner_text() for tag in quote.query_selector_all('.tag'))
               }
           browser.close()

3. Bot-Erkennung

Einige Websites schränken möglicherweise den Zugriff auf Bots ein. Dies kann durch Überprüfen des User-Agent-Headers der HTTP-Anfrage erfolgen. Der User-Agent-Header ist eine Zeichenfolge, die den Browser und das Betriebssystem des Clients identifiziert. Wenn der User-Agent-Header nicht oder auf einen Wert gesetzt ist, der vom Server nicht erkannt wird, blockiert der Server möglicherweise die Anfrage.

Es gibt jedoch ausgefeiltere Möglichkeiten, Bots zu erkennen. Beispielsweise kann der Server die Anforderungsrate eines Clients überprüfen. Wenn ein Client in kurzer Zeit zu viele Anfragen sendet, blockiert der Server möglicherweise den Client. Ihre IP-Adresse kann auch auf die schwarze Liste gesetzt werden, wenn Sie zu viele Anfragen senden.

Beim Surfen im Internet kann es vorkommen, dass Sie von Zeit zu Zeit auf ein CAPTCHA stoßen.

CAPTCHA-Bot-ErkennungCAPTCHA-Bot-Erkennung

Solche Herausforderungen sollen zwischen Menschen und Bots unterscheiden. Sie werden häufig verwendet, um zu verhindern, dass Bots Websites crawlen. Wenn Sie beim Scraping einer Website auf ein CAPTCHA stoßen, können Sie es mithilfe eines CAPTCHA-Lösungsdienstes umgehen.

Verwandt: So umgehen Sie CAPTCHAs beim Scraping von Amazon.

4. Sitzung und Anmeldung

Bei einigen Websites müssen sich Benutzer anmelden, bevor sie auf bestimmte Seiten zugreifen können. Dies ist ein häufiges Hindernis beim Scrapen von Websites. Um jedoch zu vermeiden, dass dieser erste Eintrag größer als nötig wird, erläutern wir im zweiten Teil unseres Mini-Leitfadens, wie mit Sitzungs- und Anmeldeanforderungen beim Scraping von Websites umgegangen wird.

Related Posts

Hinterlasse einen Kommentar