Mit Scrapy zum eigenen Webcrawler

Scrapy ist ein Framework mit dem Crawler und Scraper geschrieben werden können. So ist es möglich Daten von Webseiten automatisch auszulesen und zu verarbeiten. Im Folgenden wird kurz gezeigt, was mit Scrapy möglich ist.

Damit Scrapy ohne Probleme funktioniert musste in diesem Versuch unbedingt Python 2.7 verwendet werden. Eine Portierung auf Python 3.x ist jedoch gerade in Arbeit.

Zunächst muss scrapy installiert werden.

$ pip install scrapy

Anschießend kann eine Vorlage für das Projekt automatisch erzeugt werden.

$ scrapy startproject demo

Für den ersten Versuch kann auch gleich noch eine Vorlage für den ersten Spider erzeugt werden.

$ cd demo
$ scrapy genspider test dinotools.de
Created spider 'test' using template 'basic' in module:
  demo.spiders.test

Dabei werden folgende Dateien angelegt.

  • demo/__init__.py
  • demo/items.py
  • demo/pipelines.py
  • demo/settings.py
  • demo/spiders/__init__.py
  • demo/spiders/test.py

In einem weiteren Schritt wird die Vorlage des Spiders in der Datei demo/spiders/test.py angepasst. Im Folgenden ist die automatisch generierte Vorlage zu sehen.

# -*- coding: utf-8 -*-
import scrapy


class TestSpider(scrapy.Spider):
        name = "test"
        allowed_domains = ["dinotools.de"]
        start_urls = (
            'http://www.dinotools.de/',
        )

        def parse(self, response):
            pass

Diese wird nun wie folgt angepasst.

# -*- coding: utf-8 -*-
import scrapy
from scrapy.http.request import Request
from demo.items import BlogItem


class TestSpider(scrapy.Spider):
        name = "test"
        allowed_domains = ["dinotools.de"]
        start_urls = (
            'http://dinotools.de/blog.html',
        )

        def parse(self, response):
            s = scrapy.Selector(response)

            blog_index_pages = s.xpath("//ul[@class='pagination']/li/a/@href").extract()
            if blog_index_pages:
                for page in blog_index_pages:
                    yield Request(response.urljoin(page), self.parse)

            posts = s.xpath("//article")
            items = []
            for post in posts:
                item = BlogItem()
                item["title"] = post.xpath("header[@class='entry-header']/h2/a/text()").extract()[0]
                item["link"] = response.urljoin(post.xpath("header[@class='entry-header']/h2/a/@href").extract()[0])
                item["content"] = post.xpath("div[@class='entry-content']/p/text()").extract()[0]
                items.append(item)

            for item in items:
                yield item

Damit der Inhalt der empfangenen Seite durchsucht werden kann, wird dieser mit einem Selector() ausgewertet. Anschließend werden mit dem XPath Ausdruck //ul[@class='pagination']/li/a/@href alle Links für den Artikel-Index extrahiert. Die gefundenen Seiten werden durch die Zeile yield Request(...) in die Queue des Spiders eingefügt. Beim Crawling werden doppelte Einträge automatisch durch das Framework erkannt und die Seiten werden nicht erneut abgerufen.

Weiterhin werden von den Index-Seiten alle Informationen wie der Titel, der Link und die Zusammenfassung zu den einzelnen Artikeln gesammelt und abgespeichert. Diese Daten stehen nach dem Vorgang zur Verfügung.

Damit die Daten gespeichert werden können wird in der Datei demo/items.py die Klasse BlogItem() wie folgt angelegt.

# -*- coding: utf-8 -*-
import scrapy

class BlogItem(scrapy.Item):
        title = scrapy.Field()
        link = scrapy.Field()
        content = scrapy.Field()

Der Spider wird mit dem folgenden Befehl über die Kommandozeile gestartet.

$ scrapy crawl test

Es ist auch möglich den Inhalt für die Weiterverarbeitung als Datei im Json Format abzulegen. Dazu wird der Befehl wie folgt erweitert.

$ scrapy crawl test -o result.json -t json

Scrapy bietet noch wesentlich mehr Funktionen, die in diesem Artikel jedoch nicht alle vorgestellt werden konnten. Weiterführende Informationen können der Scrapy Webseite und der Scrapy Dokumentation entnommen werden.

Verwandte Artikel