Wikipedia fournit un vidage de toutes les pages. Bien qu'il s'agisse d'une énorme quantité de données, un index est préparé de manière à pouvoir être manipulé lors de sa compression. Récupérons réellement les données.
Une description des données de vidage est ci-dessous.
Veillez à ne pas ouvrir le fichier XML décompressé dans un éditeur ou un navigateur classique en raison de la taille énorme du fichier.
Les données pour la version japonaise de Wikipedia sont ci-dessous.
À partir de l'édition du 1er mai 2020 disponible au moment de la rédaction, nous utiliserons les deux fichiers suivants.
Le premier XML est les données du corps. Puisqu'il est déjà compressé et de cette taille, ce sera une taille ridicule lorsqu'il est agrandi, mais il ne sera pas agrandi cette fois car il est considéré comme pouvant être manipulé tout en étant compressé.
Le deuxième index se développe. Ce sera environ 107 Mo.
L'article suivant examine la structure des balises XML vidées.
La structure de la partie principale est la suivante. Un élément est stocké dans une balise de page.
<mediawiki>
<siteinfo> ⋯ </siteinfo>
<page> ⋯ </page>
<page> ⋯ </page>
⋮
<page> ⋯ </page>
</mediawiki>
Le fichier bz2 ne compresse pas simplement l'intégralité du fichier XML, mais se compose de blocs de 100 éléments. Vous pouvez retirer le bloc et le déployer précisément. Cette structure est appelée ** multi-flux **.
siteinfo | page × 100 | page × 100 | ⋯ |
L'index a la structure suivante pour chaque ligne.
décalage bz2:id:title
Vérifiez les données réelles.
$ head -n 5 jawiki-20200501-pages-articles-multistream-index.txt
690:1:Wikipedia:Téléchargement du journal avril 2004
690:2:Wikipedia:Supprimer l'enregistrement/Journal passé décembre 2002
690:5:Ampasand
690:6:Wikipedia:Sandbox
690:10:Langue
Pour connaître la longueur d'un bloc commençant à 690, vous devez savoir où commence le bloc suivant.
$ head -n 101 jawiki-20200501-pages-articles-multistream-index.txt | tail -n 2
690:217:Liste des musiciens(groupe)
814164:219:Liste des titres de chansons
Étant donné que chaque élément est un élément, vous pouvez trouver le nombre total d'éléments en comptant le nombre de lignes. Il y a environ 2,5 millions d'articles.
$ wc -l jawiki-20200501-pages-articles-multistream-index.txt
2495246 jawiki-20200501-pages-articles-multistream-index.txt
Supprimons en fait un élément spécifique. La cible est "Qiita".
Recherchez "Qiita".
$ grep Qiita jawiki-20200501-pages-articles-multistream-index.txt
2919984762:3691277:Qiita
3081398799:3921935:Template:Qiita tag
3081398799:3921945:Template:Qiita tag/doc
Ignorez le modèle et ciblez le premier id = 3691277.
Fondamentalement, il y a 100 éléments par bloc, mais il y a des exceptions et ils semblent ne pas être alignés, alors vérifiez manuellement la position de départ du bloc suivant.
2919984762:3691305:Category:Relations bilatérales du Gabon
2920110520:3691306:Category:Relations Japon-Cameloon
Vous disposez de toutes les informations dont vous avez besoin.
id | bloquer | 次のbloquer |
---|---|---|
3691277 | 2919984762 | 2920110520 |
Python
Démarrez 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.
Ouvrez le fichier compressé.
>>> f = open("jawiki-20200501-pages-articles-multistream.xml.bz2", "rb")
Spécifiez le décalage pour récupérer le bloc contenant l'élément Qiita.
>>> f.seek(2919984762)
2919984762
>>> block = f.read(2920110520 - 2919984762)
Développez le bloc pour obtenir la chaîne.
>>> import bz2
>>> data = bz2.decompress(block)
>>> xml = data.decode(encoding="utf-8")
Et vérifiez le contenu. Contient 100 balises de page.
>>> print(xml)
<page>
<title>Category:Maire Eba</title>
<ns>14</ns>
<id>3691165</id>
(Omis)
C'est gênant comme il est, alors analysez-le comme XML. L'élément racine est requis pour l'analyse, alors ajoutez-le de manière appropriée.
>>> import xml.etree.ElementTree as ET
>>> root = ET.fromstring("<root>" + xml + "</root>")
Vérifiez le contenu. Il y a 100 balises de page sous la racine.
>>> len(root)
100
>>> [child.tag for child in root]
['page', 'page',(Omis), 'page']
Obtenez la page en spécifiant l'identifiant. L'argument de find
est une notation appelée XPath.
>>> page = root.find("page/[id='3691277']")
Et vérifiez le contenu.
>>> page.find("title").text
'Qiita'
>>> page.find("revision/text").text[:50]
'{{Infobox Website\n|Nom du site=Qiita\n|logo=\n|capture d'écran=\n|Le crâne'
Enregistrez en tant que fichier.
>>> tree = ET.ElementTree(page)
>>> tree.write("Qiita.xml", encoding="utf-8")
Vous obtiendrez un fichier qui ressemble à ceci:
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>Ajout d'une explication sur la controverse de Qiita et le stock LGTM</comment>
<model>wikitext</model>
<format>text/x-wiki</format>
<text bytes="4507" xml:space="preserve">{{Infobox Website
|Nom du site=Qiita
(Omis)
[[Category:Site Web japonais]]</text>
<sha1>mtwuh9z42c7j6ku1irgizeww271k4dc</sha1>
</revision>
</page>
Une série de flux est résumée dans un script.
Stockez et utilisez l'index dans SQLite.
SQLite
Le script convertit l'index en TSV et génère du SQL pour l'ingestion.
python conv_index.py jawiki-20200501-pages-articles-multistream-index.txt
Trois fichiers seront générés.
Importez dans SQLite.
sqlite3 jawiki.db ".read jawiki-20200501-pages-articles-multistream-index.sql"
Vous êtes maintenant prêt.
La base de données ne contient que l'index, vous avez donc besoin du fichier xml.bz2 dans le même répertoire. Ne le renommez pas car la base de données contient le nom de fichier xml.bz2.
Si vous spécifiez le nom de la base de données et de l'élément, le résultat sera affiché. Par défaut, seul le contenu de la balise de texte est spécifié, mais si vous spécifiez -x
, toutes les balises à l'intérieur de la balise de page seront affichées.
python mediawiki.py jawiki.db Qiita
python mediawiki.py -x jawiki.db Qiita
Vous pouvez exporter vers un fichier.
python mediawiki.py -o Qiita.txt jawiki.db Qiita
python mediawiki.py -o Qiita.xml -x jawiki.db Qiita
mediawiki.py est conçu pour être utilisé comme bibliothèque.
import mediawiki
db = mediawiki.DB("jawiki.db")
print(db["Qiita"].text)
Articles sur les modules multiflux et bz2.
J'ai fait référence aux spécifications d'index de Wikipedia.
L'API XML ElementTree a référencé la documentation.
J'ai étudié comment utiliser SQLite lors du traitement de données d'exemple de phrase.
Recommended Posts