Open Source im professionellen Einsatz
Linux-Magazin 07/2016
772

Geburtshelfer

Mit dem erworbenen Wissen über Scrapy lässt sich eine Beispielanwendung bauen. Den Grundstein legt der Befehl

scrapy startproject mirror

der eine passende Verzeichnisstruktur erzeugt (Listing 1). Die Anwendung erreicht der User nach dem Wechsel in das Projektverzeichnis »mirror« . Die inhaltsleeren Dateien mit den Namen »__init__.py« sind rein technischer Natur [7]. Die Spider- und Pipeline-Klassen finden sich in den gleichnamigen Unterverzeichnissen. Die Ergebnisse speichert Scrapy im Verzeichnis »results« , die darauf basierenden Reports in »reports« .

Listing 1

Beispielprojekt mirror

01  |- scrapy.cfg
02  |- mirror:
03    |- __init__.py
04    |- items.py
05    |- pipelines
06      |- __init__.py
07      |- filter.py
08      |- normalize.py
09      |- store.py
10    |- reports
11      |- attr.py
12    |- results
13     |- 2016032210001458637243.sqlite3
14    |- settings.py
15    |- spiders
16     |- __init__.py
17     |- attr.py
18    |- utils.py

Zum reinen Skelett des Projekts kommen später ein paar Listings hinzu. Die Datei »mirror/utils.py« aus der letzten Zeile von Listing 1 speichert Hilfsfunktionen. Listing 2 zeigt den Inhalt dieser Datei. Die globalen Einstellungen des Projekts liegen ebenfalls im Python-Format vor und landen in »mirror/settings.py« (Listing 3). Die Variablen in den ersten drei Zeilen legt dabei Scrapy an, ihre Großschreibung erinnert an Konstanten unter C, die es in Python aber nicht gibt.

Listing 2

mirror/utils.py

01 from urlparse import urlparse
02
03 def optvalue(alist, key, default=[]):
04   if key in alist:
05     return alist[key]
06   return default
07
08 def domain(url):
09   return urlparse(url).netloc
10
11 def join(tags):
12   return "|".join(['//'+tag for tag in tags])
13
14 def relevance(kds, wds):
15   if len(kds) == 0 or len(wds) == 0:
16     return 0
17   return reduce(lambda acc, kw: float(wds.count(kw)) + acc, kds, 0)/len(kds + wds)
18
19 def is_absurl(url):
20   return reduce(lambda acc, p: url.startswith(p) or acc, [u'http://', u'https://', u'//'], False)

Listing 3

mirror/settings.py

01 BOT_NAME = 'mirror'
02 SPIDER_MODULES = ['mirror.spiders']
03 NEWSPIDER_MODULE = 'mirror.spiders'
04 ITEM_PIPELINES = {
05     'mirror.pipelines.normalize.Words': 300,
06     'mirror.pipelines.filter.Injections': 400,
07     'mirror.pipelines.store.Attributes': 500
08 }
09 RESULTS = 'mirror/results/'
10 MEDIA_TAGS = ['video', 'audio', 'img', 'canvas']
11 INJECT_TAGS = ['script/@src', 'img/@src', 'video/@src', 'audio/@src', 'iframe/@src', 'embed/@src', 'link/@href']
12 SEMANTIC_TAGS = ['html', 'head', 'title', 'meta', 'link', 'body', 'header', 'footer', 'nav', 'article', 'aside', 'section', 'h1', 'h2', 'h3', 'h4', 'p', 'a', 'ul', 'ol', 'li', 'dl', 'dt', 'figure', 'table', 'th', 'tr', 'td', 'video', 'audio', 'form', 'input',  'label', 'button']

Zeile 1 speichert den Namen, den Scrapy anstelle der Browserkennung im Kopf der HTTP-Anfragen an den abgefragten Webserver überträgt. Die Zeilen 2 und 3 sind aus Sicht von Scrapy systemimmanent und bedürfen keiner Änderung. Die dann folgenden Variablen speichern anwendungsspezifische Konstanten.

Transportarbeiter

Bevor Scrapy die abgefragten Daten in die Item-Pipeline schickt (Abbildung 4, links), überführt es sie in ein Item-Objekt. Das hilft beim Formatieren und Validieren der Anwendungsdaten. Die Item-Klasse der Beispielanwendung steckt in »mirror/items.py« (Listing 4).

Listing 4

mirror/items.py

01 from scrapy import Item, Field
02
03 class Attributes(Item):
04   url  = Field()
05   keywords = Field(input_processor=Split())
06   words = Field(input_processor=Split())
07   medias = Field()
08   links = Field()
09   tags = Field()
10   semantics = Field()
11   injections = Field()
12
13 class Split():
14   def __call__(self, values):
15     return [word for value in values for word in value.split()]

Zeile 1 importiert explizit die benötigten Basisklassen »Item« und »Field« aus dem Scrapy-Paket. Zeile 3 deklariert die »Item« -Klasse »Attributes« , die in den runden Klammern auf die Elternklasse »Item« verweist. Der abschließende Doppelpunkt leitet einen Block ein, dem alle folgenden, gleich eingerückten Zeilen angehören.

Die Anwendungsdaten legt Scrapy nicht direkt in den Attributen ab, sondern speichert sie in Objekten vom Typ »Field« (Zeilen 4 bis 11). Der Konstruktor von »Field« setzt sich wie üblich aus dem Klassennamen und einem Paar runder Klammern zusammen.

Dank des Aufrufparameters »input_processor« jagt das »Field« -Objekt die zu speichernden Daten zuvor durch die Methode »__call__()« , die zum übergebenen Objekt vom Typ »Split« gehört. Die Klasse instanziert der Code in den Zeilen 13 bis 15. Die Signatur von »__call__()« ist, wie bei allen Methoden, die Scrapy selbsttätig aufruft, vorgegeben. Die Methode nimmt im Aufrufparameter »values« eine Liste von Zeichenketten entgegen, die der etwas komplexere Listenausdruck in Zeile 15 in einzelne Wörter aufspaltet.

In ihm iteriert die »for« -Schleife in Gestalt der Variablen »value« über alle Elemente der Liste »values« . Die zweite Schleife knöpft sich die mit »split()« aufgespaltete Zeichenkette aus »value« vor. Bei jedem Durchlauf setzt das Skript über die Variable »word« (rechts neben der öffnenden, eckigen Klammer) ein Wort in die Ergebnisliste.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 6 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Portia

    Die Börsenkurse in maschinenlesbarer Form mal eben aus dem Internet holen? Kein Problem: Nach ein paar Mausklicks auf eine Börsen-Webseite webt Portia einen geeigneten Kommandozeilenbefehl und wickelt die gewünschten Daten in das passende Json-Format ein.

  • Muschelzucht im Ausland

    Microsoft veröffentlicht demnächst eine Admin-Shell für Windows, die diesen Namen auch verdient. Beim Pipelining verhält sich die Powershell unter Umständen sogar robuster als die Unix-Pendants, weil sie typisierte Objekte durchreicht.

  • E-Commerce-APIs

    Gutgehende Onlineshops sind selten und das Ergebnis langer Arbeit. Wer gerade erst beginnt Waren zu verticken, tut gut daran, bei einem großen Shoppingportal unterzuschlüpfen. Über APIs lassen sich eigene Warenwirtschafts- oder Buchhaltungsprogramme anbinden.

  • Appetithäppchen

    Newsticker, Web-Blogs und andere Informationssysteme verwenden gerne das RSS-Format, um kurze Nachrichten in standardisierter Form an die Interessenten zu verteilen. Diese News-Schnipsel lassen sich bestens mit Tcl und der objektorientierten Erweiterung CZRSS verarbeiten.

  • Tragendes Rahmenwerk

    Wer Web- oder SaaS-Anwendungen anbieten will, bekommt es mit Kodierungsrelikten der HTML- und Skriptsprachen-Frühzeit zu tun. Abhilfe schaffen moderne Frameworks wie Prado, die viele Elemente und Templates bereits als fertige Bausteine bereitstellen. Doch deren Struktur will zuerst verstanden sein.

comments powered by Disqus

Ausgabe 08/2017

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.