[PYTHON] Extrahieren Sie Seiten aus Wikipedia-Dumps

Wikipedia bietet einen Speicherauszug aller Seiten. Obwohl es sich um eine große Datenmenge handelt, wird ein Index so vorbereitet, dass er beim Komprimieren verarbeitet werden kann. Lassen Sie uns die Daten tatsächlich abrufen.

Vorbereitung

Eine Beschreibung der Dump-Daten finden Sie unten.

Achten Sie darauf, das entpackte XML aufgrund der großen Dateigröße nicht in einem normalen Editor oder Browser zu öffnen.

Die Daten für die japanische Version von Wikipedia sind unten.

Ab der Ausgabe zum 1. Mai 2020, die zum Zeitpunkt des Schreibens verfügbar war, werden wir die folgenden zwei Dateien verwenden.

  1. jawiki-20200501-pages-articles-multistream.xml.bz2 3.0 GB
  2. jawiki-20200501-pages-articles-multistream-index.txt.bz2 23.9 MB

Das erste XML sind die Körperdaten. Da es bereits komprimiert ist und diese Größe hat, wird es beim Erweitern eine lächerliche Größe sein, aber diesmal wird es nicht erweitert, da es so betrachtet wird, dass es beim Komprimieren behandelt werden kann.

Der zweite Index wird erweitert. Es wird ungefähr 107 MB sein.

Spezifikation

Der folgende Artikel untersucht die Struktur von gedumpten XML-Tags.

Die Struktur des Hauptteils ist wie folgt. Ein Element wird in einem Seiten-Tag gespeichert.

<mediawiki>
    <siteinfo> ⋯ </siteinfo>
    <page> ⋯ </page>
    <page> ⋯ </page>
           ⋮
    <page> ⋯ </page>
</mediawiki>

Die bz2-Datei komprimiert nicht einfach die gesamte XML-Datei, sondern besteht aus Blöcken mit 100 Elementen. Sie können den Block herausnehmen und punktgenau bereitstellen. Diese Struktur heißt ** Multistream **.

siteinfopage × 100page × 100

Der Index hat für jede Zeile die folgende Struktur.

bz2 Offset:id:title

Überprüfen Sie die tatsächlichen Daten.

$ head -n 5 jawiki-20200501-pages-articles-multistream-index.txt
690:1:Wikipedia:Protokoll hochladen April 2004
690:2:Wikipedia:Aufzeichnung löschen/Vergangenes Protokoll Dezember 2002
690:5:Ampasand
690:6:Wikipedia:Sandbox
690:10:Sprache

Um die Länge eines Blocks ab 690 zu ermitteln, müssen Sie wissen, wo der nächste Block beginnt.

$ head -n 101 jawiki-20200501-pages-articles-multistream-index.txt | tail -n 2
690:217:Liste der Musiker(Gruppe)
814164:219:Liste der Songtitel

Da es sich bei jedem Artikel um einen Artikel handelt, können Sie die Gesamtzahl der Artikel ermitteln, indem Sie die Anzahl der Zeilen zählen. Es gibt ungefähr 2,5 Millionen Artikel.

$ wc -l jawiki-20200501-pages-articles-multistream-index.txt
2495246 jawiki-20200501-pages-articles-multistream-index.txt

Mitnahme

Lassen Sie uns tatsächlich einen bestimmten Gegenstand herausnehmen. Das Ziel ist "Qiita".

Informationsbeschaffung

Suche nach "Qiita".

$ grep Qiita jawiki-20200501-pages-articles-multistream-index.txt
2919984762:3691277:Qiita
3081398799:3921935:Template:Qiita tag
3081398799:3921945:Template:Qiita tag/doc

Ignorieren Sie die Vorlage und zielen Sie auf die erste ID = 3691277.

Grundsätzlich gibt es 100 Elemente pro Block, aber es gibt Ausnahmen und sie scheinen nicht ausgerichtet zu sein. Überprüfen Sie daher manuell die Startposition des nächsten Blocks.

2919984762:3691305:Category:Gabuns bilaterale Beziehungen
2920110520:3691306:Category:Japan-Cameloon-Beziehungen

Sie haben alle Informationen, die Sie benötigen.

id Block 次のBlock
3691277 2919984762 2920110520

Python

Starten Sie Python.

$ python
Python 3.8.2 (default, Apr  8 2020, 14:31:25)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

Öffnen Sie die komprimierte Datei.

>>> f = open("jawiki-20200501-pages-articles-multistream.xml.bz2", "rb")

Geben Sie den Versatz an, um den Block mit dem Qiita-Element abzurufen.

>>> f.seek(2919984762)
2919984762
>>> block = f.read(2920110520 - 2919984762)

Erweitern Sie den Block, um die Zeichenfolge abzurufen.

>>> import bz2
>>> data = bz2.decompress(block)
>>> xml = data.decode(encoding="utf-8")

Und überprüfen Sie den Inhalt. Enthält 100 Seiten-Tags.

>>> print(xml)
  <page>
    <title>Category:Bürgermeister Eba</title>
    <ns>14</ns>
    <id>3691165</id>
(Weggelassen)

Es ist umständlich, also analysieren Sie es als XML. Das Root-Element wird zum Parsen benötigt. Fügen Sie es daher entsprechend hinzu.

>>> import xml.etree.ElementTree as ET
>>> root = ET.fromstring("<root>" + xml + "</root>")

Überprüfen Sie den Inhalt. Unter dem Stamm befinden sich 100 Seiten-Tags.

>>> len(root)
100
>>> [child.tag for child in root]
['page', 'page',(Weggelassen), 'page']

Rufen Sie die Seite ab, indem Sie die ID angeben. Das Argument von "find" ist eine Notation namens XPath.

>>> page = root.find("page/[id='3691277']")

Und überprüfen Sie den Inhalt.

>>> page.find("title").text
'Qiita'
>>> page.find("revision/text").text[:50]
'{{Infobox Website\n|Site-Name=Qiita\n|Logo=\n|Bildschirmfoto=\n|Schädel'

Als Datei speichern.

>>> tree = ET.ElementTree(page)
>>> tree.write("Qiita.xml", encoding="utf-8")

Sie erhalten eine Datei, die folgendermaßen aussieht:

Qiita.xml


<page>
    <title>Qiita</title>
    <ns>0</ns>
    <id>3691277</id>
    <revision>
      <id>77245770</id>
      <parentid>75514051</parentid>
      <timestamp>2020-04-26T12:21:10Z</timestamp>
      <contributor>
        <username>Linuxmetel</username>
        <id>1613984</id>
      </contributor>
      <comment>Erklärung zu Qiitas Kontroverse und LGTM-Aktie hinzugefügt</comment>
      <model>wikitext</model>
      <format>text/x-wiki</format>
      <text bytes="4507" xml:space="preserve">{{Infobox Website
|Site-Name=Qiita
(Weggelassen)
[[Category:Japanische Website]]</text>
      <sha1>mtwuh9z42c7j6ku1irgizeww271k4dc</sha1>
    </revision>
  </page>

Skript

Eine Reihe von Abläufen wird in einem Skript zusammengefasst.

Speichern und verwenden Sie den Index in SQLite.

SQLite

Das Skript konvertiert den Index in TSV und generiert SQL zur Aufnahme.

python conv_index.py jawiki-20200501-pages-articles-multistream-index.txt

Es werden drei Dateien generiert.

In SQLite importieren.

sqlite3 jawiki.db ".read jawiki-20200501-pages-articles-multistream-index.sql"

Sie sind jetzt bereit.

Wie benutzt man

Die Datenbank enthält nur den Index, daher benötigen Sie die Datei xml.bz2 im selben Verzeichnis. Benennen Sie es nicht um, da die Datenbank den Dateinamen xml.bz2 enthält.

Wenn Sie die Datenbank und den Elementnamen angeben, wird das Ergebnis angezeigt. Standardmäßig wird nur der Inhalt des Text-Tags angegeben. Wenn Sie jedoch "-x" angeben, werden alle Tags im Seiten-Tag ausgegeben.

python mediawiki.py jawiki.db Qiita
python mediawiki.py -x jawiki.db Qiita

Sie können in eine Datei ausgeben.

python mediawiki.py -o Qiita.txt jawiki.db Qiita
python mediawiki.py -o Qiita.xml -x jawiki.db Qiita

mediawiki.py kann als Bibliothek verwendet werden.

import mediawiki
db = mediawiki.DB("jawiki.db")
print(db["Qiita"].text)

In Verbindung stehender Artikel

Artikel über Multistream- und bz2-Module.

Referenz

Ich habe auf die Indexspezifikationen von Wikipedia verwiesen.

Die ElementTree XML-API verwies auf die Dokumentation.

Ich habe untersucht, wie SQLite bei der Verarbeitung von Beispielsatzdaten verwendet wird.

Recommended Posts

Extrahieren Sie Seiten aus Wikipedia-Dumps
Tabelle aus Wikipedia extrahieren
Extrahieren Sie mit Python Daten von einer Webseite
Extrahieren Sie Weiterleitungen aus Wikipedia-Dumps
So erhalten Sie eine Liste mit Links von einer Seite aus Wikipedia
# 5 [python3] Extrahiert Zeichen aus einer Zeichenfolge
So extrahieren Sie den Koeffizienten aus der Minutenformel
Extrahieren Sie die Merkmalsmenge (Identität) aus dem Text.
Holen Sie sich ein Bild von einer Webseite und ändern Sie die Größe
Ich habe ein Tool erstellt, um eine Wortwolke aus Wikipedia zu erstellen
Extrahieren Sie den Wert, der einem Wert am nächsten kommt, aus einem Listenelement in Python
Extrahieren Sie eine bestimmte Sprache aus Wiktionary
Versuchen Sie, mit Python3 eine Zeichenfolge aus einem Bild zu extrahieren
So extrahieren Sie die gewünschte Zeichenfolge aus einem Befehl in Zeile 4
Ich habe ein Skript geschrieben, um Webseiten-Links in Python zu extrahieren
Finden Sie alle Muster, um eine bestimmte Zahl aus dem Satz zu extrahieren