Python-Web-Scraping - BeautifulSoup

Python-Web-Scraping bezeichnet den Prozess des automatischen Extrahierens von Informationen aus dem Internet durch das Schreiben von Python-Programmen.

Der grundlegende Web-Scraping-Prozess umfasst normalerweise das Senden von HTTP-Anfragen zum Abrufen von Webseiteninhalten, das Parsen der Webseiten, das Extrahieren von Daten und anschließend das Speichern der Daten.

Pythons reichhaltiges Ökosystem macht es zu einer beliebten Sprache für die Entwicklung von Web-Scrapern, insbesondere wegen seiner leistungsstarken Bibliotheksunterstützung.

Im Allgemeinen kann der Web-Scraping-Prozess in die folgenden Schritte unterteilt werden:

  • HTTP-Anfragen senden: Der Scraper ruft HTML-Seiten von der Zielwebsite über HTTP-Anfragen ab. Zu den häufig verwendeten Bibliotheken gehörenrequests。
  • HTML-Inhalt parsen: Nachdem die HTML-Seite abgerufen wurde, muss der Scraper den Inhalt parsen und Daten extrahieren. Gängige Bibliotheken sind unter anderemBeautifulSoup、lxml、Scrapy, usw.
  • Daten extrahieren: Extrahieren Sie die erforderlichen Daten, indem Sie HTML-Elemente lokalisieren (wie Tags, Attribute, Klassennamen usw.).
  • Daten speichern: Speichern Sie die extrahierten Daten in Formaten wie Datenbanken, CSV-Dateien und JSON-Dateien zur späteren Verwendung oder Analyse.

Dieses Kapitel stellt hauptsächlich BeautifulSoup vor, eine Python-Bibliothek zum Parsen von HTML- und XML-Dokumenten. Sie kann Daten aus Webseiten extrahieren und wird häufig für Web Scraping und Data Mining verwendet.


BeautifulSoup

BeautifulSoup ist eine Python-Bibliothek zum Extrahieren von Daten aus Webseiten, besonders geeignet zum Parsen von HTML- und XML-Dateien.

BeautifulSoup kann Webseiteninhalte extrahieren und manipulieren, indem es eine einfache API bereitstellt, was es sehr geeignet für Web-Scraping- und Datenextraktionsaufgaben macht.

BeautifulSoup installieren

Um BeautifulSoup zu verwenden, müssen Sie beautifulsoup4 und lxml oder html.parser (einen HTML-Parser) installieren.

Wir können pip verwenden, um diese Abhängigkeiten zu installieren:

pip install beautifulsoup4
pip install lxml  # 推荐使用 lxml 作为解析器(速度更快)

Wenn Sie lxml nicht haben, können Sie den in Python integrierten html.parser als Parser verwenden.

Grundlegende Verwendung

BeautifulSoup wird zum Parsen von HTML- oder XML-Daten verwendet und bietet Methoden zum Navigieren, Suchen und Ändern des Parse-Baums.

Zu den gängigen BeautifulSoup-Operationen gehören das Finden von Tags, das Abrufen von Tag-Attributen, das Extrahieren von Text usw.

Um BeautifulSoup zu verwenden, müssen Sie zuerst BeautifulSoup importieren und die HTML-Seite in ein BeautifulSoup-Objekt laden.

Normalerweise verwenden Sie zuerst eine Web-Scraping-Bibliothek (wierequests), um den Webseiteninhalt abzurufen:

Beispiel

from bs4 import BeautifulSoup
import requests

# Verwenden Sie requests, um den Webseiteninhalt abzurufen
url = 'https://cn.bing.com/' # Den Webseiteninhalt der Bing-Suchmaschine scrapen
response = requests.get(url)

# Verwenden Sie BeautifulSoup, um die Webseite zu parsen
soup = BeautifulSoup(response.text, 'lxml')  # Verwenden Sie den lxml-Parser
# Parsen Sie den Webseiteninhalt mit dem html.parser-Parser
# soup = BeautifulSoup(response.text, 'html.parser')

Webseitentitel abrufen:

Beispiel

from bs4 import BeautifulSoup
import requests

# Geben Sie die Website an, deren Titel Sie abrufen möchten
url = 'https://cn.bing.com/' # Den Webseiteninhalt der Bing-Suchmaschine scrapen

# Senden Sie eine HTTP-Anfrage, um den Inhalt der Webseite abzurufen
response = requests.get(url)
# Problem mit chinesischem Zeichensalat
response.encoding = 'utf-8'
# Stellen Sie sicher, dass die Anfrage erfolgreich war
if response.status_code == 200:
    # Verwenden Sie BeautifulSoup, um den Inhalt der Webseite zu parsen
    soup = BeautifulSoup(response.text, 'lxml')
   
    # Finden Sie das <title>-Tag
    title_tag = soup.find('title')
   
    # Geben Sie den Titeltext aus
    if title_tag:
        print(title_tag.get_text())
    else:
        print("Das <title>-Tag wurde nicht gefunden")
else:
    print("Anfrage fehlgeschlagen, Statuscode:", response.status_code)

Nach Ausführen des obigen Codes lautet der ausgegebene Titel:

搜索 - Microsoft 必应

Problem mit chinesischem Zeichensalat

Bei der Verwendung der requests-Bibliothek zum Scrapen chinesischer Webseiten können Kodierungsprobleme auftreten, wodurch chinesische Inhalte nicht korrekt angezeigt werden. Um sicherzustellen, dass chinesische Webseiten korrekt gescrapt und angezeigt werden, müssen Sie sich normalerweise um die Zeichenkodierung der Webseite kümmern.

Automatische Kodierungserkennung: requests leitet die Kodierung der Webseite normalerweise automatisch aus dem Content-Type in den Antwort-Headern ab, aber dies kann manchmal ungenau sein. In solchen Fällen können Sie chardet verwenden, um die Kodierung automatisch zu erkennen.

Beispiel

import requests

url = 'https://cn.bing.com/'
response = requests.get(url)

# Verwende chardet, um die Kodierung automatisch zu erkennen
import chardet
encoding = chardet.detect(response.content)['encoding']
print(encoding)
response.encoding = encoding

Nach dem Ausführen des obigen Codes lautet die Ausgabe:

utf-8

Wenn Sie die Kodierung der Webseite kennen (z. B. utf-8 oder gbk), können Sie direktresponse.encoding festlegen:

response.encoding = 'utf-8'  # 或者 'gbk',根据实际情况选择

Tags finden

BeautifulSoup bietet mehrere Methoden zum Finden von Tags in einer Webseite. Zu den am häufigsten verwendeten gehörenfind()undfind_all()。

  • find()Gibt das erste passende Tag zurück
  • find_all()Gibt alle passenden Tags zurück

Beispiel

from bs4 import BeautifulSoup
import requests

# Geben Sie die Website an, deren Titel Sie abrufen möchten
url = 'https://www.baidu.com/' # Scrape den Webseiteninhalt der Bing-Suchmaschine

# Senden Sie eine HTTP-Anfrage, um den Inhalt der Webseite abzurufen
response = requests.get(url)
# Problem mit chinesischem Zeichensalat
response.encoding = 'utf-8'

soup = BeautifulSoup(response.text, 'lxml')

# Finde das erste <a>-Tag
first_link = soup.find('a')
print(first_link)
print("----------------------------")

# Hole das href-Attribut des ersten <a>-Tags
first_link_url = first_link.get('href')
print(first_link_url)
print("----------------------------")

# Alle <a>-Tags finden
all_links = soup.find_all('a')
print(all_links)

Das Ausgabeergebnis ist ähnlich wie das folgende:

<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
----------------------------
http://news.baidu.com
----------------------------
[<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>, <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123</a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图</a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频</a>,

Tag-Text abrufen

Mit derget_text()-Methode können Sie den Textinhalt innerhalb eines Tags extrahieren:

Beispiel

from bs4 import BeautifulSoup
import requests

# Geben Sie die Website an, deren Titel Sie abrufen möchten
url = 'https://www.baidu.com/' # Scrape den Webseiteninhalt der Bing-Suchmaschine

# Senden Sie eine HTTP-Anfrage, um den Inhalt der Webseite abzurufen
response = requests.get(url)
# Problem mit chinesischem Zeichensalat
response.encoding = 'utf-8'

soup = BeautifulSoup(response.text, 'lxml')

# Den Textinhalt des ersten <p>-Tags abrufen
paragraph_text = soup.find('p').get_text()

# Den gesamten Textinhalt auf der Seite abrufen
all_text = soup.get_text()
print(all_text)

Das Ausgabeergebnis ist ähnlich wie das folgende:

Baidu it, and you'll know.

Untergeordnete und übergeordnete Tags finden

Sie können dieparent- undchildren-Eigenschaften verwenden, um auf die übergeordneten und untergeordneten Tags eines Tags zuzugreifen:
# 获取当前标签的父标签
parent_tag = first_link.parent

# 获取当前标签的所有子标签
children = first_link.children

Beispiel

from bs4 import BeautifulSoup
import requests

# Geben Sie die Website an, deren Titel Sie abrufen möchten
url = 'https://www.baidu.com/' # Scrape den Webseiteninhalt der Bing-Suchmaschine

# Senden Sie eine HTTP-Anfrage, um den Inhalt der Webseite abzurufen
response = requests.get(url)
# Problem mit chinesischem Zeichensalat
response.encoding = 'utf-8'

soup = BeautifulSoup(response.text, 'lxml')

# Finde das erste <a>-Tag
first_link = soup.find('a')
print(first_link)
print("----------------------------")

# Eltern-Tag des aktuellen Tags abrufen
parent_tag = first_link.parent
print(parent_tag.get_text())

Das Ausgabeergebnis ist ähnlich wie das folgende:

<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
----------------------------
 新闻 hao123 地图 视频 贴吧  登录   更多产品 

Tags mit bestimmten Attributen finden

Sie können Tags mit bestimmten Attributen finden, indem Sie Attributparameter übergeben.

Zum Beispiel alle div-Tags mit dem Klassennamen example-class finden:

# 查找所有 class="example-class" 的 <div> 标签
divs_with_class = soup.find_all('div', class_='example-class')

# 查找具有 id="unique-id" 的 <p> 标签
unique_paragraph = soup.find('p', id='unique-id')

Rufen Sie den Such-Button mit der id su ab:

Beispiel

from bs4 import BeautifulSoup
import requests

# Geben Sie die Website an, deren Titel Sie abrufen möchten
url = 'https://www.baidu.com/' # Scrape den Webseiteninhalt der Bing-Suchmaschine

# Senden Sie eine HTTP-Anfrage, um den Inhalt der Webseite abzurufen
response = requests.get(url)
# Problem mit chinesischem Zeichensalat
response.encoding = 'utf-8'

soup = BeautifulSoup(response.text, 'lxml')

# Finde das <input>-Tag mit id="unique-id"
unique_input = soup.find('input', id='su')

input_value = unique_input['value'] # Wert des Eingabefelds abrufen

print(input_value)

Das Ausgabeergebnis ist:

Baidu it.

Erweiterte Nutzung

CSS-Selektoren

BeautifulSoup unterstützt auch das Finden von Tags mithilfe von CSS-Selektoren.

Die select()-Methode ermöglicht es Ihnen, eine jQuery-ähnliche Selektor-Syntax zu verwenden, um Tags zu finden:

# 使用 CSS 选择器查找所有 class 为 'example' 的 <div> 标签
example_divs = soup.select('div.example')

# 查找所有 <a> 标签中的 href 属性
links = soup.select('a[href]')

Umgang mit verschachtelten Tags

BeautifulSoup unterstützt tief verschachtelte HTML-Strukturen. Sie können diese Strukturen verarbeiten, indem Sie rekursiv untergeordnete Tags finden:

# 查找嵌套的 <div> 标签
nested_divs = soup.find_all('div', class_='nested')
for div in nested_divs:
    print(div.get_text())

Ändern von Webseiteninhalten

BeautifulSoup ermöglicht es Ihnen, HTML-Inhalte zu ändern.

Wir können Tag-Attribute, Text ändern oder Tags löschen:

Beispiel

# Das href-Attribut des ersten <a>-Tags ändern
first_link['href'] = 'http://new-url.com'

# Den Textinhalt des ersten <p>-Tags ändern
first_paragraph = soup.find('p')
first_paragraph.string = 'Updated content'

# Einen Tag löschen
first_paragraph.decompose()

Umwandlung in einen String

Das geparste BeautifulSoup-Objekt kann wieder in einen HTML-String umgewandelt werden:

# 转换为字符串
html_str = str(soup)

BeautifulSoup-Attribute und -Methoden

Im Folgenden sind häufig verwendete Attribute und Methoden in BeautifulSoup aufgeführt:

Methode/AttributBeschreibungBeispiel
BeautifulSoup()Wird verwendet, um HTML- oder XML-Dokumente zu parsen und ein BeautifulSoup-Objekt zurückzugeben.soup = BeautifulSoup(html_doc, 'html.parser')
.prettify()Formatiert und verschönert den Dokumentinhalt und erzeugt einen strukturierten String.print(soup.prettify())
.find()Findet das erste passende Tag.tag = soup.find('a')
.find_all()Findet alle passenden Tags und gibt eine Liste zurück.tags = soup.find_all('a')
.find_all_next()Findet alle Tags, die nach dem aktuellen Tag liegen und die Bedingungen erfüllen.tags = soup.find('div').find_all_next('p')
.find_all_previous()Findet alle Tags, die vor dem aktuellen Tag liegen und die Bedingungen erfüllen.tags = soup.find('div').find_all_previous('p')
.find_parent()Gibt das übergeordnete Tag des aktuellen Tags zurück.parent = tag.find_parent()
.find_all_parents()Finde alle übergeordneten Tags des aktuellen Tags.parents = tag.find_all_parents()
.find_next_sibling()Finde den nächsten Geschwister-Tag des aktuellen Tags.next_sibling = tag.find_next_sibling()
.find_previous_sibling()Finde den vorherigen Geschwister-Tag des aktuellen Tags.prev_sibling = tag.find_previous_sibling()
.parentRufe den übergeordneten Tag des aktuellen Tags ab.parent = tag.parent
.next_siblingRufe den nächsten Geschwister-Tag des aktuellen Tags ab.next_sibling = tag.next_sibling
.previous_siblingRufe den vorherigen Geschwister-Tag des aktuellen Tags ab.prev_sibling = tag.previous_sibling
.get_text()Extrahiere den Textinhalt innerhalb des Tags, wobei alle HTML-Tags ignoriert werden.text = tag.get_text()
.attrsGib alle Attribute des Tags zurück, dargestellt als Dictionary.href = tag.attrs['href']
.stringRufe den String-Inhalt innerhalb des Tags ab.string_content = tag.string
.nameGib den Namen des Tags zurück.tag_name = tag.name
.contentsGib alle untergeordneten Elemente des Tags als Liste zurück.children = tag.contents
.descendantsGib alle Nachfahren-Elemente des Tags in Generatorform zurück.for child in tag.descendants: print(child)
.parentRufe den übergeordneten Tag des aktuellen Tags ab.parent = tag.parent
.previous_elementRuft das vorherige Element des aktuellen Tags ab (Text ausgeschlossen).prev_elem = tag.previous_element
.next_elementRuft das nächste Element des aktuellen Tags ab (Text ausgeschlossen).next_elem = tag.next_element
.decompose()Entfernt den aktuellen Tag und seinen Inhalt aus dem Baum.tag.decompose()
.unwrap()Entfernt den Tag selbst und behält nur seinen Kindinhalt bei.tag.unwrap()
.insert()Fügt einen neuen Tag oder Text in den Tag ein.tag.insert(0, new_tag)
.insert_before()Fügt einen neuen Tag vor dem aktuellen Tag ein.tag.insert_before(new_tag)
.insert_after()Fügt einen neuen Tag nach dem aktuellen Tag ein.tag.insert_after(new_tag)
.extract()Löscht den Tag und gibt den Tag zurück.extracted_tag = tag.extract()
.replace_with()Ersetzt den aktuellen Tag und seinen Inhalt.tag.replace_with(new_tag)
.has_attr()Prüft, ob der Tag das angegebene Attribut besitzt.if tag.has_attr('href'):
.get()Ruft den Wert des angegebenen Attributs ab.href = tag.get('href')
.clear()Leert alle Inhalte des Tags.tag.clear()
.encode()Kodieren Sie den Tag-Inhalt als Byte-Stream.encoded = tag.encode()
.is_empty_elementPrüfen Sie, ob das Tag ein Void-Element ist (z. B.<br>、<img>usw.).if tag.is_empty_element:
.is_ancestor_of()Prüfen Sie, ob das aktuelle Tag ein Vorfahre des angegebenen Tags ist.if tag.is_ancestor_of(another_tag):
.is_descendant_of()Prüfen Sie, ob das aktuelle Tag ein Nachkomme des angegebenen Tags ist.if tag.is_descendant_of(another_tag):

Weitere Attribute

Methode/AttributBeschreibungBeispiel
.styleRufen Sie den Inline-Stil des Tags ab.style = tag['style']
.idRufen Sie die ... des Tags abidAttributs.id = tag['id']
.class_Rufen Sie die ... des Tags abclassAttributs.class_name = tag['class']
.stringRufen Sie den String-Inhalt innerhalb des Tags ab, wobei andere Tags ignoriert werden.content = tag.string
.parentRufen Sie das übergeordnete Element des Tags ab.parent = tag.parent

Sonstiges

Methode/AttributBeschreibungBeispiel
find_all(string)Verwenden Sie einen String, um passende Tags zu finden.tag = soup.find_all('div', class_='container')
find_all(id)Finden Sie das angegebene ...id-Tag anzeigen können.tag = soup.find_all(id='main')
find_all(attrs)Finden Sie Tags mit den angegebenen Attributen.tag = soup.find_all(attrs={"href": "http://example.com"})
Andere Erweiterungen