Analizar Wikipedia, filtrado, para tareas de PNL en 44 líneas de código

En esta publicación, me gustaría complementar este artículo y decirle cómo puede usar el WikiExtractor de Wikipedia de manera flexible, filtrando artículos por categoría.



Todo comenzó con el hecho de que necesitaba definiciones para varios términos. Los términos y sus definiciones suelen ser la primera oración de cada página de Wikipedia. Siguiendo el camino más simple, extraje todos los artículos y rápidamente tomé todo lo que necesitaba con los clientes habituales. El problema es que el tamaño de las definiciones excedía los 500 MB y había demasiadas cosas innecesarias, por ejemplo, entidades nombradas, ciudades, años, etc. que no necesito.



Asumí correctamente que la herramienta WikiExtractor ( usaré una versión diferente, el enlace estará debajo) tiene algún tipo de filtro, y resultó ser un filtro por categorías. Las categorías son etiquetas para artículos que tienen una estructura jerárquica para organizar páginas. Me alegré de poner la categoría "Ciencias Exactas", creyendo muy ingenuamente que todos los artículos relacionados con las ciencias exactas se incluirán en la lista, pero no sucedió un milagro: cada página tiene su propio conjunto de categorías y no hay información en una sola página. sobre cómo se relacionan estas categorías. Esto significa que si necesito páginas sobre ciencias exactas, debo indicar todas las categorías que son descendientes de "Ciencias exactas".



Bueno, no importa, ahora encontraré un servicio, pensé, que me enviaría fácilmente todas las categorías desde un principio. Desafortunadamente, solo encontré esto donde puedes ver cómo se relacionan estas categorías. Un intento de iterar manualmente sobre las categorías tampoco tuvo éxito, pero estaba "contento" de que estas categorías no tuvieran una estructura de árbol, como pensé todo este tiempo, sino solo un gráfico dirigido con ciclos. Además, la jerarquía en sí flota mucho; diré de antemano que al establecer el punto de partida "Matemáticas", puede llegar fácilmente a Alexander I. Como resultado, solo tuve que restaurar este gráfico localmente y de alguna manera obtener una lista de categorías de interés para mí.



, : - , , , - .



Ubuntu 16.04, , , 18.04 .





, ,



  • ruwiki-latest-pages-articles.xml.bz2
  • ruwiki-latest-categorylinks.sql.gz
  • ruwiki-latest-category.sql.gz
  • ruwiki-latest-page.sql.gz


categorylinks , , [[Category:Title]] , . cl_from, id , cl_to, . , id , page () page_id page_title. , . , , , , , . category([](category table)) cat_title. pages-articles.xml .



mysql. ,



sudo apt-get install mysql-server  mysql-client


, mysql , .



$ mysql -u username -p
mysql> create database category;
mysql> create database categorylinks;
mysql> create database page;


, . .



$  mysql -u username -p category < ruwiki-latest-category.sql
$  mysql -u username -p categorylinks < ruwiki-latest-categorylinks.sql
$  mysql -u username -p page < ruwiki-latest-page.sql




, csv.



mysql> select page_title, cl_to from categorylinks.categorylinks join page.page
on cl_from = page_id  where page_title in (select cat_title from category) INTO outfile '/var/lib/mysql-files/category.csv' FIELDS terminated by ';' enclosed by '"' lines terminated by '\n';


. .





, , — , . , , , , 1,6 1,1. .



import pandas as pd
import networkx as nx
from tqdm.auto import tqdm, trange

#Filtering
df = pd.read_csv("category.csv", sep=";", error_bad_lines=False)
df = df.dropna()
df_filtered = df[df.parant.str.contains("[--]+:") != True] 
df_filtered = df_filtered[df_filtered.parant.str.contains(",_") != True]
df_filtered = df_filtered[df_filtered.parant.str.contains("__") != True] 
df_filtered = df_filtered[df_filtered.parant.str.contains("_") != True] 
df_filtered = df_filtered[df_filtered.parant.str.contains(",_") != True] 
df_filtered = df_filtered[df_filtered.parant.str.contains("__") != True]
df_filtered = df_filtered[df_filtered.parant.str.contains("__") != True]
df_filtered = df_filtered[df_filtered.parant.str.contains("_") != True] 
df_filtered = df_filtered[df_filtered.parant.str.contains("__") != True]
df_filtered = df_filtered[df_filtered.parant.str.contains("") != True] 

# Graph recovering
G = nx.DiGraph()
c = 0
for i, gr in tqdm(df_filtered.groupby('child')):

    vertex = set()
    edges = []
    for i, r in gr.iterrows():
        G.add_node(r.parant, color="white")
        G.add_node(r.child, color="white")
        G.add_edge(r.parant, r.child)




, , , , .



counter = 0
nodes = []

def dfs(G, node, max_depth):
    global nodes, counter
    G.nodes[node]['color'] = 'gray'
    nodes.append(node)
    counter += 1
    if counter == max_depth:
        counter -= 1
        return
    for v in G.successors(node):
        if G.nodes[v]['color'] == 'white':
            dfs(G, v, max_depth)
        elif G.nodes[v]['color'] == 'gray':
            continue
    counter -= 1


, nodes . " " 5 . 2500 . , , , , - , , , — , . , , .



, .



_

CAM
__
_
_
__
__


__
__
__
___
_

...

_
___
__
_____
_
_
____
_
_
_
_
__
_
_()

...


_

_
_

_
_
_
-_

_
_
_
_
_


Sin embargo, para aplicar estas categorías para el filtrado del idioma ruso, debe modificar algo en la fuente. Usé esta versión. Ahora hay algo nuevo, quizás las correcciones a continuación ya no sean relevantes. En el archivo WikiExtractor.py, debe reemplazar "Categoría" por "Categoría" en dos lugares. Las áreas con la versión ya corregida se presentan a continuación:




tagRE = re.compile(r'(.*?)<(/?\w+)[^>]*?>(?:([^<]*)(<.*?>)?)?')
#                    1     2               3      4
keyRE = re.compile(r'key="(\d*)"')
catRE = re.compile(r'\[\[:([^\|]+).*\]\].*')  # capture the category name [[Category:Category name|Sortkey]]"

def load_templates(file, output_file=None):
...


if inText:
    page.append(line)
    # extract categories
    if line.lstrip().startswith('[[:'):
        mCat = catRE.search(line)
        if mCat:
            catSet.add(mCat.group(1))


Después de eso, debes ejecutar el comando



python WikiExtractor.py --filter_category categories --output wiki_filtered ruwiki-latest-pages-articles.xml


donde categorías es el archivo con categorías. Los artículos filtrados estarán en wiki_filtered.

Eso es todo. Gracias por su atención.




All Articles