Indizierung von Websites in Solr mit Python

Indizierung von Websites in Solr mit Python In diesem Beitrag zeige ich Ihnen eine einfache, aber effektive Methode zur Indizierung…

Indizierung von Websites in Solr mit Python

In diesem Beitrag zeige ich Ihnen eine einfache, aber effektive Methode zur Indizierung von Websites in einem Solr-Index mit Scrapy und Python.

Wir sehen viele fortgeschrittene Solr-basierte Anwendungen mit ausgefeilten, benutzerdefinierten Datenpipelines, die Daten aus verschiedenen Quellen kombinieren, oder die große Anforderungen haben. Außerdem sehen wir oft Leute, die die Suche auf eine minimal-invasive Weise implementieren möchten, indem sie bestehende Websites als Integrationspunkte nutzen, anstatt eine tiefe Integration mit bestimmten CMS oder Datenbanken zu implementieren, die möglicherweise von anderen Gruppen in einer Organisation gepflegt werden. Das Crawlen von Websites hört sich zwar recht einfach an, aber Sie werden bald feststellen, dass es Probleme mit der Mechanik des Crawlings, aber vor allem mit der Struktur von Websites gibt.
Wenn Sie einfach nur den HTML-Code analysieren und den Text indizieren, werden Sie eine Menge Text indizieren, der für die Seite eigentlich nicht relevant ist: Navigationsabschnitte, Kopf- und Fußzeilen, Werbung, Links zu verwandten Seiten. Der Versuch, dies im Nachhinein zu bereinigen, ist oft nicht effektiv. Es ist viel besser, wenn Sie verhindern, dass dieser Müll überhaupt in den Index gelangt. Dazu müssen Sie den Inhalt der Webseite analysieren und Informationen auf intelligente Weise extrahieren. Und dafür gibt es ein großartiges Tool: Scrapy. In diesem Beitrag werde ich ein einfaches Beispiel für seine Verwendung geben. Im Scrapy-Tutorial finden Sie eine Einführung und weitere Informationen.

Krabbelnd

Meine Beispielseite ist mein persönlicher Blog. Ich schreibe den Blog in Markdown, generiere HTML mit Jekyll, stelle ihn über Git bereit und hosten ihn auf Lighttpd und CloudFront. Aber all das ändert nichts daran, dass wir diese Inhalte konsumieren, wir werden die Website nur crawlen.

Zunächst bereiten Sie die Ausführung von Scrapy in einer Python-Virtualenv vor:

PROJECT_DIR=~/projects/scrapy
mkdir $PROJECT_DIR
cd $PROJECT_DIR
virtualenv scrapyenv
source scrapyenv/bin/activate
pip install scrapy

Dann erstellen Sie eine Scrapy-Anwendung mit dem Namen blog:

scrapy startproject blog
cd blog

Die Elemente, die wir indizieren möchten, sind die Blog-Einträge; ich verwende nur die Felder Titel, URL und Text:

cat > blog/items.py <<EOM
from scrapy.item import Item, Field

class BlogItem(Item):
    title = Field()
    url = Field()
    text = Field()
EOM

Als Nächstes erstelle ich einen einfachen Spider, der meine Website durchsucht, Blogbeiträge anhand der URL-Struktur identifiziert,
und den Text aus dem Blogbeitrag extrahiert. Das Tolle daran ist, dass wir bestimmte Teile der Seite extrahieren können.

cat > blog/spiders/blogspider.py <<EOM
from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from scrapy.http import Request
from blog.items import BlogItem
from scrapy.item import Item
from urlparse import urljoin
import re

class BlogSpider(BaseSpider):
    name = 'blog'
    allowed_domains = ['www.greenhills.co.uk']
    start_urls = ['http://www.greenhills.co.uk/']

    seen = set()

    def parse(self, response):
        if response.url in self.seen:
            self.log('already seen  %s' % response.url)
        else:
            self.log('parsing  %s' % response.url)
            self.seen.add(response.url)

        hxs = HtmlXPathSelector(response)
        if re.match(r'http://www.greenhills.co.uk/d{4}/d{2}/d{2}', response.url):
            item = BlogItem()
            item['title'] = hxs.select('//title/text()').extract()
            item['url'] = response.url
            item['text'] = hxs.select('//section[@id="main"]//child::node()/text()').extract()
            self.log("yielding item " + response.url)
            yield item

        for url in hxs.select('//a/@href').extract():
            url = urljoin(response.url, url)
            if not url in self.seen and not re.search(r'.(pdf|zip|jar)$', url):
                self.log("yielding request " + url)
                yield Request(url, callback=self.parse)
EOM

Der wichtigste Teil der Logik hier ist der Abgleich: Meine Blog-URLs beginnen alle mit einem Datum (/YYYY/MM/DD/), also verwende ich das, um Blogbeiträge zu identifizieren, die ich dann mit XPath analysiere. Der Haken an der Sache ist, dass Sie absolute URLs aus relativen Pfaden in HTML A-Tags (mit urljoin) erstellen müssen und dass ich Links zu binären Typen überspringe. Ich hätte den CrawlSpider verwenden und Regeln für das Extrahieren/Parsen definieren können, aber mit dem BaseCrawler ist es etwas klarer zu sehen, was passiert.

Um das Krabbeln zu starten:

scrapy crawl blog -o items.json -t json

die eine JSON-Datei items.json mit einer Liste von Elementen wie:

{"url": "http://www.greenhills.co.uk/2013/05/22/installing-distributed-solr-4-with-fabric.html",
"text": ["Installing Distributed Solr 4 with Fabric", "22 May 2013", "I wrote an article ", "u201cInstalling Distributed Solr 4 with Fabricu201d", "nabout deploying SolrCloud with ", "Fabric", ".nCode is on ", "github.com/Lucidworks/solr-fabric", ".", "My ", "VM strategy", "nand ", "server", " worked great for developing/testing this!", "u00a9 2011 Martijn Koster u2014 ", "terms", "n", "n"],
"title": ["Installing Distributed Solr 4 with Fabric"]},

Indizierung

Um diese Daten in Solr zu übertragen, könnten wir den JSON Request Handler verwenden und die JSON-Daten einfach in die entsprechende Form umwandeln. Aber da wir Python verwenden, benutzen wir einfach pysolr.

So installieren Sie pysolr:

pip install pysolr

und schreiben Sie den Python-Code:

cat > inject.py <<EOM
import pysolr,json,argparse
parser = argparse.ArgumentParser(description='load json into python.')
parser.add_argument('input_file', metavar='input', type=str, help='json input file')
parser.add_argument('solr_url', metavar='url', type=str, help='solr URL')

args = parser.parse_args()
solr = pysolr.Solr(args.solr_url, timeout=10)

items = json.load(open(args.input_file))
for item in items:
  item['id'] = item['url']

solr.add(items)
EOM

Das sieht zu einfach aus, oder? Der Trick ist, dass die Attributnamen title/url/body in der JSON-Datei mit den Felddefinitionen in der Default Solr schema.xml übereinstimmen. Beachten Sie, dass das Feld text so konfiguriert ist, dass es indiziert, aber nicht gespeichert wird. Das bedeutet, dass Sie den Inhalt der Seite nicht mit Ihrer Abfrage zurückbekommen und dass Sie keine Dinge wie Hervorhebungen vornehmen können.

Wir brauchen ein „id“-Feld, und dafür verwenden wir die URL. Ich hätte das auch im Crawler festlegen können, so dass es Teil der JSON-Datei geworden wäre, aber da es eine Solr-spezifische Anforderung ist (und ich so eine einfache Feldzuordnung veranschaulichen kann), habe ich mich entschieden, es hier zu tun.

Die url zeigt auf einen Solr 4-Server auf dem Host „vm116.lan“ in meinem LAN. Passen Sie den Hostnamen und die Portnummer an Ihren an.
Weitere Informationen zur Ausführung von Solr finden Sie im Solr 4.3.0-Tutorial.

Zur Ausführung (ändern Sie die URL so, dass sie auf Ihre Solr-Instanz verweist):

python inject.py items.json http://vm116.lan:8983/solr/collection1

und um eine Abfrage zu machen, gehen Sie mit Ihrem Browser auf http://vm116.lan:8983/solr/collection1/browse und suchen Sie nach Fabric. Dort sollten Sie den Beitrag Installing Distributed Solr 4 with Fabric finden. Oder verwenden Sie die untergeordnete Solr-Abfrageseite http://vm116.lan:8983/solr/#/collection1/query und führen Sie eine Abfrage nach text:Fabric durch.

In diesem Beispiel werden Crawling und Indizierung in getrennten Phasen durchgeführt. Sie können auch direkt vom Crawler aus injizieren.

Lizenz und Haftungsausschluss

Die obigen Codeschnipsel werden von abgedeckt:

Die MIT-Lizenz (MIT)

Copyright (c) 2013 Martijn Koster

Hiermit wird jeder Person, die eine Kopie
dieser Software und der zugehörigen Dokumentationsdateien (die „Software“) erwirbt, die Erlaubnis erteilt,
mit der Software uneingeschränkt zu handeln, einschließlich und ohne Einschränkung der Rechte
die Software zu nutzen, zu kopieren, zu modifizieren, zusammenzuführen, zu veröffentlichen, zu vertreiben, Unterlizenzen zu vergeben und/oder
Kopien der Software zu verkaufen, und Personen, denen die Software
zur Verfügung gestellt wird, dies zu gestatten, vorbehaltlich der folgenden Bedingungen:

Der obige Copyright-Hinweis und dieser Genehmigungshinweis sind in
in alle Kopien oder wesentlichen Teile der Software aufzunehmen.

DIE SOFTWARE WIRD OHNE MÄNGELGEWÄHR UND OHNE JEGLICHE AUSDRÜCKLICHE ODER
STILLSCHWEIGENDE GARANTIE ZUR VERFÜGUNG GESTELLT, EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF DIE GARANTIE DER MARKTGÄNGIGKEIT,
EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND NICHTVERLETZUNG VON RECHTEN. IN KEINEM FALL SIND DIE
AUTOREN ODER URHEBERRECHTSINHABER HAFTBAR FÜR JEGLICHE ANSPRÜCHE, SCHÄDEN ODER ANDERE
HAFTUNG, SEI ES AUS VERTRAG, UNERLAUBTER HANDLUNG ODER ANDERWEITIG, DIE SICH AUS,
ODER IN VERBINDUNG MIT DER SOFTWARE ODER DER NUTZUNG ODER DEM SONSTIGEN UMGANG MIT
DER SOFTWARE ERGEBEN.

You Might Also Like

Analytics Studio: Verwandeln Sie Ihre E-Commerce-Daten in verwertbare Einblicke

Entdecken Sie, wie Analytics Studio Teams in die Lage versetzt, datengestützte Entscheidungen...

Read More

Wenn KI schief geht: Fehlschläge in der realen Welt und wie man sie vermeidet

Lassen Sie nicht zu, dass Ihr KI-Chatbot einen 50.000 Dollar teuren Tahoe...

Read More

Lucidworks Kernpakete: Branchenoptimierte KI-Such- und Personalisierungslösungen

Entdecken Sie unsere umfassenden Core Packages, die Analytics Studio, Commerce Studio und...

Read More

Quick Links

Diese Site ist auf wpml.org als Entwicklungssite registriert. Wechseln Sie zu einer Produktionssite mit dem Schlüssel remove this banner.