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.
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
J'essaierai ceci dans cet article.
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 ... ~~
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-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
À 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
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.)
L'ensemble de données de l'Encyclopédie Nico Nico est grossièrement divisé.
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
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.
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.
import pandas as pd
import json
from pathlib import Path
from pprint import pprint
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))
##################
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
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.
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)
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