[PYTHON] Début de l'analyse de l'encyclopédie Nico Nico ~ Appuyez sur les données fournies par JSON

Utiliser l'ensemble de données de l'Encyclopédie Nico Nico

L'ensemble de données de l'Encyclopédie Nico Nico est une collection d'articles 2008-2014 de l'Encyclopédie Nico Nico publiés sur IDR et des commentaires sur ces articles.

Il convient à la recherche sur les langages naturels tels que l'extraction de connaissances, mais ce n'est pas un ensemble de données silencieux comme Wikipedia, mais un ensemble de données plutôt excentrique.

Par exemple, près de la moitié des phrases de l'Encyclopédie Niko Niko n'ont pas de sujet, et le style d'écriture n'est pas toujours unifié, et AA est également inclus.

Cette fois, je présenterai le contenu des données avec un simple outil de prétraitement à la recherche de ** personnes intéressantes ** qui souhaiteraient analyser cet ensemble de données.

Prétraitez l'Encyclopédie Nico Nico fournie

Les données fournies sont un ** CSV légèrement spécial ** qui peut être transformé en un CSV standard avec un prétraitement approprié. En outre, HTML a des balises qui sont lourdes et un peu lourdes pour la commodité de l'analyse. Pour cette raison

  1. Pré-traiter CSV
  2. Transformez l'article de l'encyclopédie Nico Nico (HTML) en JSON
  3. Jetez un œil

J'essaierai ceci dans cet article.

Prétraitement

L'environnement important requis pour le prétraitement n'est pas la mémoire mais la capacité du disque. Si vous ne disposez que de 50 Go d'espace supplémentaire par inadvertance, le prétraitement échouera avec une erreur.

De plus, si vous utilisez Python, il est préférable d'avoir plus de CPU et de mémoire. ~~ Ou plutôt, les performances de Pandas ne sont pas si bonnes ... ~~

Demande d'utilisation des données

https://www.nii.ac.jp/dsc/idr/nico/nicopedia-apply.html

Postulez d'ici. Lorsque vous postulez, vous recevrez une URL à télécharger d'ici au moins quelques jours, alors conservez-la.

Téléchargez et décompressez le fichier compressé

Téléchargez-le à partir de l'URL et développez-le pour appliquer comme ça.

.
└── nico-dict
    └── zips
        ├── download.txt
        ├── head
        │   ├── head2008.csv
        │   ├── ...
        │   └── head2014.csv
        ├── head.zip
        ├── res
        │   ├── res2008.csv
        │   ├── ...
        │   └── res2014.csv
        ├── res.zip
        ├── rev2008.zip
        ├── rev2009
        │   ├── rev200901.csv
        │   ├── rev200902.csv
        │   ├── rev200903.csv
        │   ├── ...
        │   └── rev200912.csv
        ├── rev2009.zip
        ├──...
        ├── rev2013.zip
        ├── rev2014
        │   ├── rev201401.csv
        │   └── rev201402.csv
        └── rev2014.zip

Clone du référentiel

À l'origine, j'ai utilisé Clojure (Lisp) pour l'analyse en raison de l'évaluation des délais et de la facilité de prétraitement, mais j'ai créé un outil pour HTML-> JSON qui ne traite pas autant que possible afin qu'il puisse être analysé avec Python.

https://github.com/MokkeMeguru/niconico-parser

Veuillez cloner à partir de.

git clone https://github.com/MokkeMeguru/niconico-parser

Format CSV.

https://github.com/MokkeMeguru/niconico-parser/blob/master/resources/preprocess.sh

Pour zips / preprocess.sh

sh preprocess.sh

s'il vous plaît faites-le. Ce fichier est le traitement requis pour modifier l'échappement CSV aux spécifications modernes. (Back story: j'ai testé ce processus pas mal, mais il y a peut-être un bogue. Si vous avez un bogue, veuillez commenter.)

Enregistrer les informations d'en-tête d'article dans la base de données

L'ensemble de données de l'Encyclopédie Nico Nico est grossièrement divisé.

  1. En-tête (ID d'article, titre, lecture du titre, catégorie, etc.)
  2. Corps de l'article
  3. Commentaires sur l'article

Il est devenu. Parmi ceux-ci, 1. est un montant qui peut être facilement créé dans une base de données, nous allons donc créer une base de données.

Les fichiers requis sont https://github.com/MokkeMeguru/niconico-parser/blob/master/resources/create-table.sql et https://github.com/MokkeMeguru/niconico-parser/blob/master/resources/ import-dir.sh. Disposez-les de manière à ce qu'ils soient zips / head / <file>

sh import-dir.sh

S'il vous plaît. Ensuite, vous obtiendrez une base de données de sqlite3 appelée header.db.

Accédons-y pour un essai.

sqlite3 headers.db
sqlite3 > select * from article_header limit 10
 ...> ;
 1|Encyclopédie Nico Nico|Nico Nico Daihakka|a|20080512173939
 4|curry|curry|a|20080512182423
 5|J'ai demandé à Hatsune Miku de chanter la chanson originale "Tu as des fleurs et je chante".|\N|v|20080719234213
 9|Go Go Curry|Go Go Curry|a|20080512183606
 13|Lutte authentique avec pantalon Gachimuchi|\N|v|20080513225239
 27|La tête est pan(P)┗(^o^ )┓3|\N|v|20080529215132
 33|[Hatsune Miku] "Un petit rapport de temps amusant" [Chanson arrangée]|\N|v|20080810020937
 37|【 SYNC.ART'S × U.N.Est-ce qu'Owen est elle? ] -Bonne le temps-|\N|v|20080616003242
 46|Groupe de météores vidéo Nico Nico|\N|v|20080513210124
 47|J'ai fait une potion élevée.|\N|v|20090102150209

Il a une encyclopédie smiley, et ça sent que vous pouvez obtenir des connaissances que Wikipédia n'a pas.

HTML->JSON! L'un des gros problèmes avec les articles de l'Encyclopédie Nico Nico est qu'il y a beaucoup de balises étranges. Contrairement à Wikipédia, il y a beaucoup de balises «
» et de balises «» pour le formatage, et c'était une réponse personnelle que j'ai eu beaucoup de mal à essayer de récupérer la phrase. (~~ De plus, AA est presque hors service. Créez une étiquette pour AA ... ~~)

Le moyen le plus simple d'analyser le HTML est d'utiliser DSL (langage spécifique au domaine). Un outil bien connu est Outil d'analyse HTML de Kotlin.

Cette fois, j'ai essayé de le traiter facilement en utilisant Lisp. Le code détaillé est ... eh bien () ...

lein preprocess-corpus -r /path/to/nico-dict/zips

Eh bien, veuillez l'exécuter comme ceci. (Cliquez ici pour l'exécution du Jar (rapport de bogue)) Il faut environ 10 à 15 minutes pour consommer environ 20 à 30 Go de disque.

Jetons un coup d'œil rapide au contenu.

head -n 1 rev2008-jsoned.csv 
1,"{""type"":""element"",""attrs"":null,""tag"":""body"",""content"":[{""type"":""element"",""attrs"":null,""tag"":""h2"",""content"":[""Aperçu""]},{""type"":""element"",""attrs"":null,""tag"":""p"",""content"":[""Qu'est-ce que l'Encyclopédie Nico Nico?(réduction)Est.""]}]}",200xxxxxxxx939,[],Encyclopédie Nico Nico,Nico Nico Daihakka,a

Pour expliquer un élément à la fois

  1. ID de l'article
  2. Conversion JSON + article prétraité
  3. Date de mise à jour de l'article
  4. Liste des liens (balises «») contenus dans la page
  5. Titre
  6. Lecture du titre
  7. Catégorie ("a" = mot "v" = vidéo "i" = produit "l" = diffusion en direct "c" = peut-être article de la communauté (catégorie non dans les spécifications))

Je ne peux pas vraiment présenter l'effet de la conversion JSON + prétraitement cette fois, mais par exemple, il est plus facile de gérer des choses comme <p> hoge <span /> hoge <br /> bar </ p>, et le graphique On peut mentionner qu'il est plus facile d'appliquer des outils tels que Snorkel.

Faisons quelques statistiques

J'ai fait un outil de pré-traitement! Ce n'est pas très ennuyeux en soi, alors faisons quelque chose comme les statistiques. En parlant de traitement des données, il semble que ce soit Python + Pandas, donc je vais étudier en utilisant Python + Pandas. (Cependant, Pandas est très lourd ou lent, veuillez donc utiliser un autre outil pour une analyse à grande échelle.)

Nous allons procéder comme le Jupyter Notebook ci-dessous.

Importation de dépendance

import pandas as pd
import json
from pathlib import Path
from pprint import pprint

Déclaration des variables globales

Veuillez changer pour chaque environnement.

############################
#Variables globales(Changer le cas échéant) #
############################
#En-tête CSV
header_name = ('article_id', 'article', 'update-date',
               'links', 'title', 'title_yomi', 'category''')
dtypes = {'article_id': 'uint16',
          'article': 'object',
          'update-date': 'object',
          'links': 'object',
          'title': 'object',
          'title_yomi': 'object',
          'category': 'object'
}

#Exemple de CSV
sample_filepath = "/home/meguru/Documents/nico-dict/zips/rev2014/rev201402-jsoned.csv"
sample_filepath = Path(sample_filepath)

#Exemples de CSV
fileparent = Path("/home/meguru/Documents/nico-dict/zips")
filepaths = [
    "rev2014/rev201401-jsoned.csv",
    "rev2014/rev201402-jsoned.csv",
    "rev2013/rev201301-jsoned.csv",
    "rev2013/rev201302-jsoned.csv",
    "rev2013/rev201303-jsoned.csv",
    "rev2013/rev201304-jsoned.csv",
    "rev2013/rev201305-jsoned.csv",
    "rev2013/rev201306-jsoned.csv",
    "rev2013/rev201307-jsoned.csv",
    "rev2013/rev201308-jsoned.csv",
    "rev2013/rev201309-jsoned.csv",
    "rev2013/rev201310-jsoned.csv",
    "rev2013/rev201311-jsoned.csv",
    "rev2013/rev201312-jsoned.csv",
]
filepaths = filter(lambda path: path.exists(),  map(
    lambda fpath: fileparent / Path(fpath), filepaths))
##################

Définition de la fonction de lecture des CSV prétraités

def read_df(csvfile: Path, with_info: bool = False):
    """read jsoned.csv file
    args:
    - csvfile: Path
    a file path you want to read
    - with_info: bool
    with showing csv's information
    returns:
    - df
    readed data frame
    notes:
    if you call this function, you will got some log message
    """
    df = pd.read_csv(csvfile, names=header_name, dtype=dtypes)
    print('[Info] readed a file {}'.format(csvfile))
    if with_info:
        df.info()
    return df


def read_dfs(fileparent: Path, csvfiles: List[Path]):
    """read jsoned.csv files
    args:
    - fileparent: Path
    parent file path you want to read
    - csvfiles: List[Path]
    file paths you want to read
    returns:
    - dfl
    concated dataframe
    note:
    given.
        fileparent = \"/path/to\"
        csvfiles[0] = \"file\"
    then.
        search file <= \"/path/to/file\"
    """
    dfl = []
    for fpath in filepaths:
        dfi = pd.read_csv(fileparent / fpath,
                          index_col=None, names=header_name, dtype=dtypes)
        dfl.append(dfi)
    dfl = pd.concat(dfl, axis=0, ignore_index=True)
    return dfl

Chargez 1 fichier dans l'échantillon et visualisez

Cette fois, voyons comment les liens (balises <a>) dans le HTML montrent comment ils sont dispersés pour chaque type d'article.

df = read_df(sample_filepath, True)
# [Info] readed a file /home/meguru/Documents/nico-dict/zips/rev2014/rev201402-jsoned.csv
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 6499 entries, 0 to 6498
# Data columns (total 7 columns):
# article_id     6499 non-null int64
# article        6499 non-null object
# update-date    6499 non-null int64
# links          6499 non-null object
# title          6491 non-null object
# title_yomi     6491 non-null object
# category       6491 non-null object
# dtypes: int64(2), object(5)
# memory usage: 355.5+ KB

Pour le moment, j'ai pu confirmer que ce fichier lui-même contient un article de 6.5k.

Ensuite, analysez les informations de lien JSON pour calculer le nombre de liens.

#Confirmation des données brutes
df['links'][0]
# => '[{"type":"element","attrs":{"href":"http://wwwxxxxhtml"},"tag":"a","content":["Site de Kochi xxxx"]}]'
dfs= pd.DataFrame()
dfs['links']= df['links'].map(lambda x: len(json.loads(x)))
dfs['links'][0]
# => 1

Prenons une statistique rapide.

dfs['category']=df['category']
dfsg=dfs.groupby('category')
dfsg.describe()
#            links                                                      
#            count       mean         std  min  25%   50%    75%     max
# category                                                              
# a         5558.0  41.687298  209.005652  0.0  0.0   2.0  11.00  2064.0
# c           36.0  54.305556  109.339529  0.0  2.0   2.0  38.25   376.0
# i            4.0   7.500000    5.507571  2.0  3.5   7.0  11.00    14.0
# l          786.0  22.760814  106.608535  0.0  0.0   2.0   9.00  1309.0
# v          107.0  32.887850   46.052744  0.0  3.0  11.0  37.00   153.0

"a" = mot "v" = vidéo "i" = produit "l" = diffusion en direct "c" = article de la communauté, il existe donc en moyenne de nombreux ** liens vers des articles de la communauté **. Cependant, si vous regardez les valeurs médiane et maximale, vous pouvez observer qu'il semble nécessaire de regarder de plus près (classer) le mot articles.

Essayez d'augmenter les données d'exemple et de vérifier

6k articles ne suffisent pas, augmentons donc les données.

dfl = read_dfs(fileparent, filepaths)
# >>>         article_id                                            article  ...             title_yomi category
# 0             8576  {"type":"element","attrs":null,"tag":"body","c...  ...Kabekick un
# [223849 rows x 7 columns]
dfls = pd.DataFrame()
dfls['links'] = dfl['links'].map(lambda x: len(json.loads(x)))
dfls['category'] = dfl['category']
dflsg = dfls.groupby('category')
dflsg.describe()
#              links
#              count       mean         std  min  25%  50%   75%     max
# category
# a         193264.0  32.400566  153.923988  0.0  0.0  2.0  10.0  4986.0
# c           1019.0  34.667321   77.390967  0.0  1.0  2.0  34.0   449.0
# i            247.0   6.137652    6.675194  0.0  1.0  3.0  10.0    28.0
# l          24929.0  20.266477  100.640253  0.0  0.0  1.0   5.0  1309.0
# v           3414.0  14.620387   22.969974  0.0  1.0  6.0  16.0   176.0

Dans l'ensemble, vous pouvez voir que la valeur moyenne des liens en direct et vidéo est inversée à mesure que le nombre de liens vidéo diminue. De plus, le fait que la plage de fluctuation du nombre de liens dans le mot article est trop grande peut être confirmé comme dans le cas d'un échantillon. Il est également contre-intuitif que ** les articles de mots sont inférieurs à la moyenne du troisième quadrant **.

D'après les résultats ci-dessus, on peut voir qu'au moins le nombre de liens varie considérablement selon le type d'article, et je pense qu'il semble préférable d'étudier après avoir observé les propriétés de chaque article individuellement. (Expliquez au spectateur comment étudier et produire des résultats à partir d'ici)

Y a-t-il une corrélation entre le nombre de liens d'article et la taille de l'article?

D'après l'expérience précédente, vous pouvez voir que la dispersion est particulièrement importante pour les articles Word. La raison en est ** de mon expérience et de mon intuition lorsque je regarde habituellement l'Encyclopédie de Nico Nico **, j'ai trouvé la corrélation entre la taille de l'article et le nombre de liens. Alors, considérons le nombre de caractères dans les données converties JSON comme la taille de l'article et vérifions la corrélation.

dfts.corr()
#                  links  article_size
# links         1.000000      0.713465
# article_size  0.713465      1.000000

Au moins, il semble y avoir une forte corrélation positive.

Si vous avancez un peu plus loin, cela ressemblera à ceci.

#À propos des articles Word
dfts[dfts['category'] == "a"].loc[:, ["links", "article_size"]].corr()
#                  links  article_size
# links         1.000000      0.724774
# article_size  0.724774      1.000000



#À propos des articles de la communauté
dfts[dfts['category'] == "c"].loc[:, ["links", "article_size"]].corr()
#                links  article_size
# links        1.00000       0.63424
# article_size 0.63424       1.00000

#À propos des articles produits
dfts[dfts['category'] == "i"].loc[:, ["links", "article_size"]].corr()
#                  links  article_size
# links         1.000000      0.254031
# article_size  0.254031      1.000000

#À propos des articles diffusés en direct
dfts[dfts['category'] == "l"].loc[:, ["links", "article_size"]].corr()
#                 links  article_size
# links         1.00000       0.58073
# article_size  0.58073       1.00000

#À propos des articles vidéo
dfts[dfts['category'] == "v"].loc[:, ["links", "article_size"]].corr()
#                  links  article_size
# links         1.000000      0.428443
# article_size  0.428443      1.000000

News Nous avons développé une CLI pour analyser les articles publiés sur le Web.

lein parse-from-web -u https://dic.nicovideo.jp/a/<contents-title>

Vous pouvez convertir les données d'article en JSON comme ceci. Voir Repository pour un exemple d'acquisition.

Cependant, cela ** met une charge sur le serveur de l'autre partie **, veuillez donc l'utiliser à des fins telles que tester un outil pendant un certain temps. Même si vous faites une erreur, veuillez ne pas imiter le raclage du tapis à la bombe de l'IP de l'université.

Recommended Posts

Début de l'analyse de l'encyclopédie Nico Nico ~ Appuyez sur les données fournies par JSON
L'analyse d'image a été facile à l'aide des données et de l'API fournies par Microsoft COCO
Le début de cif2cell
Analyse des données financières par pandas et leur visualisation (2)
Analyse des données financières par pandas et leur visualisation (1)
Compréhension mathématique de l'analyse en composantes principales depuis le début
Histoire de l'analyse d'image du fichier PDF et de l'extraction de données
Analyse des données de mesure (2) -Hydrobacter et raccord, recommandation lmfit-
Remarque DJango: depuis le début (Simplification et fractionnement d'URLConf)
Faisons l'analyse des données de naufrage du Titanic comme ça
Analyse des données basée sur les résultats des élections du gouverneur de Tokyo (2020)
Touchez la maquette et le talon
Un débutant en Python a d'abord essayé une analyse rapide et facile des données météorologiques des 10 dernières années.
Livres et sources recommandés de programmation d'analyse de données (Python ou R)
Une analyse simple des données de Bitcoin fournie par CoinMetrics en Python
À propos de Boxplot et Violinplot qui visualisent la variation des données indépendantes
Pratique de l'analyse de données par Python et pandas (Tokyo COVID-19 data edition)
L'histoire de Python et l'histoire de NaN
First Python 3 ~ Le début de la répétition ~
Touchez l'objet du réseau neuronal
Recommandation d'analyse des données à l'aide de MessagePack
Analyse des séries chronologiques 3 Prétraitement des données des séries chronologiques
Traitement des données 2 Analyse de divers formats de données
Résumer les principaux points de croissance hack des services web et les points d'analyse
Envoyer et recevoir des données d'image au format JSON en Python sur le réseau
Rechercher le nom et les données d'une variable libre dans un objet fonction
Extraire et tracer les dernières données démographiques à partir des données PDF fournies par la ville
L'histoire de la création d'une caméra sonore avec Touch Designer et ReSpeaker
Résumé des distributions de probabilité qui apparaissent souvent dans les statistiques et l'analyse des données
Nettoyage des données des données ouvertes de la situation d'occurrence du ministère de la Santé, du Travail et des Affaires sociales
Obtenez la clé pour la migration de la deuxième couche de données JSON avec python