So crawlen Sie eine Webseite mit Scrapy und Python 3

Einführung

Web-Scraping, das häufig als Web-Crawlen oder Web-Spidering bezeichnet wird, oder das „programmgesteuerte Durchsuchen einer Sammlung von Webseiten und Extrahieren von Daten“ ist ein leistungsstarkes Tool für die Arbeit mit Daten im Web.

Mit einem Web-Scraper können Sie Daten zu einer Reihe von Produkten durchsuchen, eine große Anzahl von Texten oder quantitativen Daten zum Herumspielen abrufen, Daten von einer Site ohne offizielle API abrufen oder einfach nur Ihre persönliche Neugier befriedigen.

In diesem Tutorial lernen Sie die Grundlagen des Scraping- und Spidering-Prozesses kennen, während Sie einen spielerischen Datensatz untersuchen. Wir werden http://brickset.com [BrickSet] verwenden, eine von der Community betriebene Website, die Informationen zu LEGO-Sets enthält. Am Ende dieses Tutorials steht Ihnen ein voll funktionsfähiger Python-Web-Scraper zur Verfügung, der eine Reihe von Seiten in Brickset durchläuft und Daten zu LEGO-Sets von jeder Seite extrahiert und die Daten auf Ihrem Bildschirm anzeigt.

Der Scraper ist leicht erweiterbar, sodass Sie daran herumspielen und es als Grundlage für Ihre eigenen Projekte verwenden können, die Daten aus dem Web scrappen.

Voraussetzungen

Um dieses Tutorial abzuschließen, benötigen Sie eine lokale Entwicklungsumgebung für Python 3. Sie können How To Install and Set Up a Lokale Programmierumgebung für Python 3, um alles zu konfigurieren, was Sie benötigen.

Schritt 1 - Erstellen eines Grundschabers

Das Schaben erfolgt in zwei Schritten:

  1. Sie suchen Webseiten systematisch und laden sie herunter.

  2. Sie nehmen diese Webseiten und extrahieren Informationen aus ihnen.

Beide dieser Schritte können auf verschiedene Arten in vielen Sprachen implementiert werden.

Sie können einen Scraper von Grund auf neu erstellen, indem Sie modules oder Bibliotheken verwenden, die von Ihrer Programmiersprache bereitgestellt werden um mit möglichen Kopfschmerzen umzugehen, wenn Ihr Schaber komplexer wird. Beispielsweise müssen Sie die Parallelität behandeln, damit Sie mehr als eine Seite gleichzeitig crawlen können. Sie möchten wahrscheinlich herausfinden, wie Sie Ihre verschrotteten Daten in verschiedene Formate wie CSV, XML oder JSON umwandeln können. Und manchmal müssen Sie sich mit Sites befassen, für die bestimmte Einstellungen und Zugriffsmuster erforderlich sind.

Sie haben mehr Glück, wenn Sie Ihren Scraper auf einer vorhandenen Bibliothek aufbauen, die diese Probleme für Sie löst. In diesem Tutorial verwenden wir Python und Scrapy, um unseren Scraper zu erstellen.

Scrapy ist eine der beliebtesten und leistungsstärksten Python-Scraping-Bibliotheken. Das Schaben erfolgt mit dem Ansatz "Batterien inbegriffen". Dies bedeutet, dass viele der allgemeinen Funktionen, die alle Schaber benötigen, verarbeitet werden, damit Entwickler das Rad nicht jedes Mal neu erfinden müssen. Es macht das Schaben schnell und macht Spaß!

Scrapy ist, wie die meisten Python-Pakete, auf PyPI (auch bekannt als "+ pip +"). PyPI, der Python Package Index, ist ein Community-Repository aller veröffentlichten Python-Software.

Wenn Sie über eine Python-Installation wie die in der Voraussetzung für dieses Tutorial beschriebene verfügen, ist auf Ihrem Computer bereits "+ pip +" installiert, sodass Sie Scrapy mit dem folgenden Befehl installieren können:

pip install scrapy

Wenn bei der Installation Probleme auftreten oder Sie Scrapy ohne Verwendung von "+ pip +" installieren möchten, lesen Sie die official installation docs. .

Nachdem Sie Scrapy installiert haben, erstellen Sie einen neuen Ordner für unser Projekt. Sie können dies im Terminal tun, indem Sie Folgendes ausführen:

mkdir brickset-scraper

Navigieren Sie nun in das neu erstellte Verzeichnis:

cd brickset-scraper

Erstellen Sie dann eine neue Python-Datei für unseren Scraper mit dem Namen "+ scraper.py ". Wir werden den gesamten Code für dieses Tutorial in diese Datei einfügen. Sie können diese Datei im Terminal mit dem Befehl " touch +" wie folgt erstellen:

touch

Sie können die Datei auch mit Ihrem Texteditor oder dem grafischen Dateimanager erstellen.

Wir beginnen mit der Herstellung eines sehr einfachen Schabers, der Scrapy als Grundlage verwendet. Zu diesem Zweck erstellen wir eine Python class, die der Klasse `+ untergeordnet ist scrapy.Spider + `, eine grundlegende Spinnenklasse, die von Scrapy bereitgestellt wird. Diese Klasse hat zwei erforderliche Attribute:

  • + name + - nur ein Name für die Spinne.

  • + start_urls + - eine list von URLs, von denen Sie zu crawlen beginnen. Wir beginnen mit einer URL.

Öffnen Sie die Datei "+ scrapy.py +" in Ihrem Texteditor und fügen Sie diesen Code hinzu, um die Basisspinne zu erstellen:

scraper.py

import scrapy


class BrickSetSpider(scrapy.Spider):
   name = "brickset_spider"
   start_urls = ['']

Lassen Sie uns dies Zeile für Zeile aufteilen:

Zunächst import + scrapy +, damit wir die im Paket enthaltenen Klassen verwenden können.

Als nächstes nehmen wir die von Scrapy bereitgestellte Klasse "+ Spider " und machen daraus eine Unterklasse mit dem Namen " BrickSetSpider ". Stellen Sie sich eine Unterklasse als eine spezialisiertere Form ihrer Elternklasse vor. Die Unterklasse " Spider +" verfügt über Methoden und Verhaltensweisen, die festlegen, wie URLs befolgt und Daten aus den gefundenen Seiten extrahiert werden. Sie weiß jedoch nicht, wo oder nach welchen Daten gesucht werden soll. Indem wir es unterordnen, können wir es mit diesen Informationen versorgen.

Dann geben wir der Spinne den Namen "+ brickset_spider +".

Schließlich geben wir unserem Scraper eine einzelne URL, die von folgender Adresse ausgeht: http://brickset.com/sets/year-2016. Wenn Sie diese URL in Ihrem Browser öffnen, gelangen Sie zu einer Suchergebnisseite, auf der die erste von vielen Seiten mit LEGO-Sets angezeigt wird.

Testen wir nun den Schaber. In der Regel führen Sie Python-Dateien aus, indem Sie einen Befehl wie "+ Python-Pfad / to / file.py +" ausführen. Scrapy enthält jedoch its own command line interface, um den Prozess des Startens eines Scrapers zu optimieren. Starten Sie Ihren Scraper mit folgendem Befehl:

scrapy runspider

Sie sehen ungefähr Folgendes:

Output2016-09-22 23:37:45 [scrapy] INFO: Scrapy 1.1.2 started (bot: scrapybot)
2016-09-22 23:37:45 [scrapy] INFO: Overridden settings: {}
2016-09-22 23:37:45 [scrapy] INFO: Enabled extensions:
['scrapy.extensions.logstats.LogStats',
'scrapy.extensions.telnet.TelnetConsole',
'scrapy.extensions.corestats.CoreStats']
2016-09-22 23:37:45 [scrapy] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
...
'scrapy.downloadermiddlewares.stats.DownloaderStats']
2016-09-22 23:37:45 [scrapy] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
...
'scrapy.spidermiddlewares.depth.DepthMiddleware']
2016-09-22 23:37:45 [scrapy] INFO: Enabled item pipelines:
[]
2016-09-22 23:37:45 [scrapy] INFO: Spider opened
2016-09-22 23:37:45 [scrapy] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2016-09-22 23:37:45 [scrapy] DEBUG: Telnet console listening on 127.0.0.1:6023
2016-09-22 23:37:47 [scrapy] DEBUG: Crawled (200) <GET http://brickset.com/sets/year-2016> (referer: None)
2016-09-22 23:37:47 [scrapy] INFO: Closing spider (finished)
2016-09-22 23:37:47 [scrapy] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 224,
'downloader/request_count': 1,
...
'scheduler/enqueued/memory': 1,
'start_time': datetime.datetime(2016, 9, 23, 6, 37, 45, 995167)}
2016-09-22 23:37:47 [scrapy] INFO: Spider closed (finished)

Das ist eine Menge Output, also lasst es uns aufschlüsseln.

  • Der Scraper initialisierte und lud zusätzliche Komponenten und Erweiterungen, die zum Lesen von Daten aus URLs erforderlich waren.

  • Es verwendete die URL, die wir in der Liste "+ start_urls +" angegeben hatten, und griff nach dem HTML-Code, genau wie es Ihr Webbrowser tun würde.

  • Dieser HTML-Code wurde an die Methode "+ parse " übergeben, die standardmäßig keine Aktionen ausführt. Da wir nie unsere eigene " parse +" - Methode geschrieben haben, endet die Spinne ohne Arbeit.

Lassen Sie uns nun einige Daten von der Seite ziehen.

Schritt 2 - Extrahieren von Daten aus einer Seite

Wir haben ein sehr einfaches Programm erstellt, mit dem eine Seite heruntergezogen wird, das jedoch noch kein Scraping oder Spidering ausführt. Geben wir ihm einige Daten zum Extrahieren.

Wenn Sie sich http://brickset.com/sets/year-2016 anschauen, sehen Sie, dass die Seite, die wir durchsuchen möchten, die folgende Struktur aufweist:

  • Auf jeder Seite befindet sich eine Kopfzeile.

  • Es gibt einige Suchdaten auf oberster Ebene, einschließlich der Anzahl der Übereinstimmungen, der gesuchten Informationen und der Navigationspfade für die Website.

  • Dann gibt es die Sets selbst, die in Form einer Tabelle oder einer geordneten Liste angezeigt werden. Jedes Set hat ein ähnliches Format.

Wenn Sie einen Scraper schreiben, sollten Sie sich die Quelle der HTML-Datei ansehen und sich mit der Struktur vertraut machen. Hier ist es also, wobei einige Dinge der Lesbarkeit halber entfernt wurden:

brickset.com/sets/year-2016<body>
 <section class="setlist">

     <a href="https://images.brickset.com/sets/large/10251-1.jpg?201510121127"
     class="highslide plain mainimg" onclick="return hs.expand(this)"><img
     src="https://images.brickset.com/sets/small/10251-1.jpg?201510121127" title="10251-1:
     Brick Bank" onError="this.src='/assets/images/spacer.png'" /></a>
     <div class="highslide-caption">
       <h1>Brick Bank</h1><div class='tags floatleft'><a href='/sets/10251-1/Brick-
       Bank'>10251-1</a> <a href='/sets/theme-Creator-Expert'>Creator Expert</a> <a
       class='subtheme' href='/sets/theme-Creator-Expert/subtheme-Modular-
       Buildings'>Modular Buildings</a> <a class='year' href='/sets/theme-Creator-
       Expert/year-2016'>2016</a> </div><div class='floatright'>&copy;2016 LEGO
       Group</div>
         <div class="pn">
           <a href="#" onclick="return hs.previous(this)" title="Previous (left arrow
           key)">&#171; Previous</a>
           <a href="#" onclick="return hs.next(this)" title="Next (right arrow key)">Next
           &#187;</a>
         </div>
     </div>

...


 </section>
</body>

Das Scrappen dieser Seite erfolgt in zwei Schritten:

  1. Schnappen Sie sich zuerst jedes LEGO-Set, indem Sie nach den Teilen der Seite suchen, die die gewünschten Daten enthalten.

  2. Nehmen Sie dann für jeden Satz die gewünschten Daten auf, indem Sie sie aus den HTML-Tags ziehen.

+ scrapy + erfasst Daten basierend auf selectors, die Sie bereitstellen. Selektoren sind Muster, mit denen wir ein oder mehrere Elemente auf einer Seite finden können, um dann mit den Daten innerhalb des Elements zu arbeiten. + scrapy + unterstützt entweder CSS-Selektoren oder XPath -Selektoren.

Wir werden vorerst CSS-Selektoren verwenden, da CSS die einfachere Option und die perfekte Lösung ist, um alle Mengen auf der Seite zu finden. Wenn Sie sich den HTML-Code für die Seite ansehen, werden Sie feststellen, dass jeder Satz mit der Klasse "+ Satz " angegeben ist. Da wir nach einer Klasse suchen, verwenden wir " .set " für unseren CSS-Selektor. Alles, was wir tun müssen, ist, diesen Selektor wie folgt in das Objekt " response" zu übergeben:

scraper.py

class BrickSetSpider(scrapy.Spider):
   name = "brickset_spider"
   start_urls = ['http://brickset.com/sets/year-2016']

   def parse(self, response):

Dieser Code erfasst alle Sätze auf der Seite und durchläuft sie, um die Daten zu extrahieren. Extrahieren wir nun die Daten aus diesen Sets, damit wir sie anzeigen können.

Ein weiterer Blick auf die source der Seite, die wir analysieren, zeigt, dass der Name jedes Sets in einem + h1 + - Tag für jedes Set gespeichert ist:

brickset.com/sets/year-2016<h1>Brick Bank</h1><div class='tags floatleft'><a href='/sets/10251-1/Brick-Bank'>10251-1</a>

Das "+ brickset " - Objekt, über das wir eine Schleife durchführen, verfügt über eine eigene " css +" - Methode, sodass wir einen Selektor übergeben können, um untergeordnete Elemente zu lokalisieren. Ändern Sie Ihren Code wie folgt, um den Namen des Sets zu finden und anzuzeigen:

scraper.py

class BrickSetSpider(scrapy.Spider):
   name = "brickset_spider"
   start_urls = ['http://brickset.com/sets/year-2016']

   def parse(self, response):
       SET_SELECTOR = '.set'
       for brickset in response.css(SET_SELECTOR):

In diesem Code werden Sie zwei Dinge bemerken:

  • Wir hängen "+ :: text" an Ihren Selektor für den Namen an. Dies ist ein CSS-Pseudoselektor, der den Text in des Tags + a + und nicht das Tag selbst abruft.

  • Wir rufen "+ extract_first () " für das von " brickset.css (NAME_SELECTOR) +" zurückgegebene Objekt auf, weil wir nur das erste Element wollen, das dem Selektor entspricht. Dies gibt uns eine string anstelle einer Liste von Elementen.

Speichern Sie die Datei und führen Sie den Scraper erneut aus:

scrapy runspider

Diesmal werden die Namen der Sets in der Ausgabe angezeigt:

Output...
[scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

[scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

[scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

[scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

...

Lassen Sie uns dies weiter ausbauen, indem wir neue Selektoren für Bilder, Teile und Miniaturfiguren oder Minifigs hinzufügen, die mit einem Set geliefert werden.

Sehen Sie sich den HTML-Code für ein bestimmtes Set noch einmal an:

brickset.com/sets/year-2016<article class="set">
 <a class="highslide plain mainimg" href="http://images.brickset.com/sets/images/10251-1.jpg?201510121127" onclick="return hs.expand(this)">
   ></a>
 ...
 <div class="meta">
   <h1><a href="/sets/10251-1/Brick-Bank"><span>10251:</span> Brick Bank</a> </h1>
   ...
   <div class="col">
     <dl>




       ...
     </dl>
   </div>
   ...
 </div>
</article>

Wir können ein paar Dinge sehen, wenn wir diesen Code untersuchen:

  • Das Bild für die Menge wird im Attribut "+ src " eines " img " - Tags in einem " a +" - Tag am Anfang der Menge gespeichert. Wir können einen anderen CSS-Selektor verwenden, um diesen Wert abzurufen, so wie wir es getan haben, als wir den Namen jedes Sets abgerufen haben.

  • Die Stückzahl zu ermitteln ist etwas schwieriger. Es gibt ein "+ dt " - Tag, das den Text " Pieces " enthält, und anschließend ein " dd +" - Tag, das die tatsächliche Stückzahl enthält. Wir verwenden XPath, eine Abfragesprache zum Durchlaufen von XML, um dies zu erfassen, da es zu komplex ist, um mit CSS-Selektoren dargestellt zu werden.

  • Das Abrufen der Anzahl der Minifiguren in einem Satz entspricht dem Abrufen der Stückzahl. Es gibt ein "+ dt " - Tag, das den Text " Minifigs " enthält, gefolgt von einem " dd +" - Tag direkt danach mit der Nummer.

Ändern wir also den Scraper, um diese neuen Informationen zu erhalten:

scraper.py

class BrickSetSpider(scrapy.Spider):
   name = 'brick_spider'
   start_urls = ['http://brickset.com/sets/year-2016']

   def parse(self, response):
       SET_SELECTOR = '.set'
       for brickset in response.css(SET_SELECTOR):

           NAME_SELECTOR = 'h1 ::text'



           yield {
               'name': brickset.css(NAME_SELECTOR).extract_first(),



           }

Speichern Sie Ihre Änderungen und führen Sie den Scraper erneut aus:

scrapy runspider

Jetzt sehen Sie die neuen Daten in der Programmausgabe:

Output2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

2016-09-22 23:52:37 [scrapy] DEBUG: Scraped from <200 http://brickset.com/sets/year-2016>

Verwandeln wir diesen Schaber nun in eine Spinne, die Links folgt.

Schritt 3 - Durchforsten mehrerer Seiten

Wir haben erfolgreich Daten von dieser ersten Seite extrahiert, kommen jedoch nicht weiter, um den Rest der Ergebnisse anzuzeigen. Der springende Punkt einer Spinne ist es, Links zu anderen Seiten zu erkennen und zu überqueren und auch Daten von diesen Seiten zu erfassen.

Sie werden feststellen, dass oben und unten auf jeder Seite ein kleines Karat ("+> +") angezeigt wird, das auf die nächste Ergebnisseite verweist. Hier ist der HTML-Code dafür:

brickset.com/sets/year-2016<ul class="pagelength">

 ...




 <li class="last">
   <a href="http://brickset.com/sets/year-2016/page-32">&#187;</a>
 </li>
</ul>

Wie Sie sehen, gibt es ein "+ li " - Tag mit der Klasse " next " und innerhalb dieses Tags ein " a +" - Tag mit einem Link zur nächsten Seite. Alles was wir tun müssen, ist dem Scraper zu sagen, dass er diesem Link folgen soll, falls er existiert.

Ändern Sie Ihren Code wie folgt:

scraper.py

class BrickSetSpider(scrapy.Spider):
   name = 'brick_spider'
   start_urls = ['http://brickset.com/sets/year-2016']

   def parse(self, response):
       SET_SELECTOR = '.set'
       for brickset in response.css(SET_SELECTOR):

           NAME_SELECTOR = 'h1 ::text'
           PIECES_SELECTOR = './/dl[dt/text() = "Pieces"]/dd/a/text()'
           MINIFIGS_SELECTOR = './/dl[dt/text() = "Minifigs"]/dd[2]/a/text()'
           IMAGE_SELECTOR = 'img ::attr(src)'
           yield {
               'name': brickset.css(NAME_SELECTOR).extract_first(),
               'pieces': brickset.xpath(PIECES_SELECTOR).extract_first(),
               'minifigs': brickset.xpath(MINIFIGS_SELECTOR).extract_first(),
               'image': brickset.css(IMAGE_SELECTOR).extract_first(),
           }

Zuerst definieren wir einen Selektor für den Link "Nächste Seite", extrahieren die erste Übereinstimmung und prüfen, ob sie existiert. "+ Scrapy.Request " ist ein Wert, den wir zurückgeben und "Hey, crawle diese Seite" sagen, und " callback = self.parse +" sagt: "Wenn Sie den HTML-Code von dieser Seite erhalten haben, geben Sie ihn an diese Methode zurück." So können wir es analysieren, die Daten extrahieren und die nächste Seite finden. “

Dies bedeutet, dass wir auf der nächsten Seite nach einem Link zur nächsten Seite suchen und auf dieser Seite nach einem Link zur nächsten Seite suchen usw., bis wir nichts mehr finden ein Link zur nächsten Seite. Dies ist das Schlüsselelement des Web Scraping: Suchen und Folgen von Links. In diesem Beispiel ist es sehr linear. Auf einer Seite befindet sich ein Link zur nächsten Seite, bis die letzte Seite angezeigt wird. Sie können jedoch Links zu Tags, anderen Suchergebnissen oder einer beliebigen anderen URL folgen.

Wenn Sie nun Ihren Code speichern und den Spider erneut ausführen, werden Sie feststellen, dass er nicht einfach stoppt, sobald er die erste Seite der Mengen durchläuft. Es werden alle 779 Übereinstimmungen auf 23 Seiten durchgespielt! Im Großen und Ganzen handelt es sich nicht um einen großen Datenblock, aber jetzt kennen Sie den Prozess, mit dem Sie automatisch neue Seiten zum Scrappen finden.

Hier ist unser vollständiger Code für dieses Tutorial mit Python-spezifischer Hervorhebung:

scraper.py

import scrapy


class BrickSetSpider(scrapy.Spider):
   name = 'brick_spider'
   start_urls = ['http://brickset.com/sets/year-2016']

   def parse(self, response):
       SET_SELECTOR = '.set'
       for brickset in response.css(SET_SELECTOR):

           NAME_SELECTOR = 'h1 ::text'
           PIECES_SELECTOR = './/dl[dt/text() = "Pieces"]/dd/a/text()'
           MINIFIGS_SELECTOR = './/dl[dt/text() = "Minifigs"]/dd[2]/a/text()'
           IMAGE_SELECTOR = 'img ::attr(src)'
           yield {
               'name': brickset.css(NAME_SELECTOR).extract_first(),
               'pieces': brickset.xpath(PIECES_SELECTOR).extract_first(),
               'minifigs': brickset.xpath(MINIFIGS_SELECTOR).extract_first(),
               'image': brickset.css(IMAGE_SELECTOR).extract_first(),
           }

       NEXT_PAGE_SELECTOR = '.next a ::attr(href)'
       next_page = response.css(NEXT_PAGE_SELECTOR).extract_first()
       if next_page:
           yield scrapy.Request(
               response.urljoin(next_page),
               callback=self.parse
           )

Fazit

In diesem Tutorial haben Sie einen voll funktionsfähigen Spider erstellt, der Daten aus Webseiten in weniger als 30 Codezeilen extrahiert. Das ist ein guter Anfang, aber es gibt eine Menge lustiger Dinge, die Sie mit dieser Spinne machen können. Hier einige Möglichkeiten, wie Sie den von Ihnen geschriebenen Code erweitern können. Sie üben das Scraping von Daten.

  1. Im Moment analysieren wir nur die Ergebnisse von 2016, wie Sie vielleicht aus dem Teil "+ 2016 " von " http: // brickset.com / sets / year-2016 +" erraten haben - wie würden Sie die Ergebnisse von anderen crawlen? Jahre?

  2. Bei den meisten Geräten ist ein Verkaufspreis enthalten. Wie extrahieren Sie die Daten aus dieser Zelle? Wie würden Sie eine rohe Zahl daraus bekommen? * Hinweis *: Sie finden die Daten in einem "+ dt +" genau wie die Anzahl der Teile und Minifiguren.

  3. Die meisten Ergebnisse haben Tags, die semantische Daten zu den Mengen oder ihrem Kontext angeben. Wie können wir diese crawlen, vorausgesetzt, es gibt mehrere Tags für einen Satz?

Das sollte ausreichen, um Sie zum Nachdenken und Experimentieren zu bewegen. Weitere Informationen zu Scrapy finden Sie in den offiziellen Dokumenten von Scrapy. Weitere Informationen zum Arbeiten mit Daten aus dem Web finden Sie in unserem Tutorial unter https://www.digitalocean.com/community/tutorials/how-to-scrape-web-pages-with-beautiful-soup-and-python-3 ["Wie man Webseiten mit schöner Suppe und Python 3 kratzt"].