2ch prend du temps pour lire chaque threadless, donc J'ai essayé de visualiser les informations du fil avec WordCloud et d'obtenir facilement une image complète. Dans la précédente Scraping Edition, le moins de contenu du groupe de threads souhaité était extrait. Cette fois, dans la deuxième partie, nous analyserons le contenu des leçons collectées la dernière fois et les publierons dans WordCloud.
Comme auparavant, utilisez Google Colaboratory. Google Colaboratory est un environnement d'exécution Python qui s'exécute sur un navigateur. Toute personne disposant d'un compte Google peut l'utiliser. Mecab nécessite une installation supplémentaire (décrite plus loin), mais WordCloud est inclus dans Google Colaboratory par défaut, l'installation n'est donc pas requise.
#Importer la bibliothèque
import requests, bs4
import re
import time
import pandas as pd
from urllib.parse import urljoin
#Installer les polices localement dans Colab
from google.colab import drive
drive.mount("/content/gdrive")
#Créez à l'avance un dossier appelé police en haut de Mon Drive sur votre Google Drive et placez-y le fichier de police souhaité.
#Copiez chaque dossier localement dans Colab
!cp -a "gdrive/My Drive/font/" "/usr/share/fonts/"
# ------------------------------------------------------------------------
#Préparation
log_database = [] #Une liste qui stocke les informations de fil
base_url = "https://www.logsoku.com/search?q=FFRK&p="
#Mise en place du web scraping
for i in range(1,4): #À quelle page revenir (ici, provisoirement jusqu'à la 4e page)
logs_url = base_url+str(i)
#Corps de traitement de grattage
res = requests.get(logs_url)
soup = bs4.BeautifulSoup(res.text, "html.parser")
#Que faire lorsqu'aucun résultat de recherche n'est trouvé
if soup.find(class_="search_not_found"):break
#Récupère la table / ligne où les informations sur les threads sont stockées
thread_table = soup.find(id="search_result_threads")
thread_rows = thread_table.find_all("tr")
#Traitement pour chaque ligne
for thread_row in thread_rows:
tmp_dict = {}
tags = thread_row.find_all(class_=["thread","date","length"])
#Organisez le contenu
for tag in tags:
if "thread" in str(tag):
tmp_dict["title"] = tag.get("title")
tmp_dict["link"] = tag.get("href")
elif "date" in str(tag):
tmp_dict["date"] = tag.text
elif "length" in str(tag):
tmp_dict["length"] = tag.text
#Seuls ceux qui ont plus de 50 leçons seront ajoutés à la base de données
if tmp_dict["length"].isdecimal() and int(tmp_dict["length"]) > 50:
log_database.append(tmp_dict)
time.sleep(1)
#Convertir en DataFrame
thread_df = pd.DataFrame(log_database)
# ------------------------------------------------------------------------
#Obtenez moins des journaux passés
log_url_base = "http://nozomi.2ch.sc/test/read.cgi/"
res_database = []
for thread in log_database:
#Nom du tableau et numéro du tableau d'affichage de la liste des journaux précédents.Et générer l'URL du journal passé
board_and_code_match = re.search("[a-zA-Z0-9_]*?/[0-9]*?/$",thread["link"])
board_and_code = board_and_code_match.group()
thread_url = urljoin(log_url_base, board_and_code)
#Extraire le code HTML de la page de journal précédente
res = requests.get(thread_url)
soup = bs4.BeautifulSoup(res.text, "html5lib")
tmp_dict = {}
#Informations telles que la date dans la balise dt
#Le commentaire est stocké dans la balise dd
dddt = soup.find_all(["dd","dt"])
for tag in dddt[::-1]: #Extrait par derrière
#Extraire uniquement la date de la balise dt
if "<dt>" in str(tag):
date_result = re.search(r"\d*/\d*/\d*",tag.text) # "(←'"'Pour éviter les anomalies d'affichage de qiita)
if date_result:
date_str = date_result.group()
tmp_dict["date"] = date_str
#Extraire moins de contenu de la balise dd
if "<dd>" in str(tag):
tmp_dict["comment"] = re.sub("\n","",tag.text)
# tmp_Le contenu stocké dans dict est res_Publier dans la base de données
if "date" in tmp_dict and "comment" in tmp_dict:
tmp_dict["thread_title"] = thread["title"]
res_database.append(tmp_dict)
tmp_dict = {}
time.sleep(1) #promettre
#Convertir en DataFrame
res_df = pd.DataFrame(res_database)
# ------------------------------------------------------------------------
#Bibliothèque d'analyse morphologique MeCab et dictionnaire(mecab-ipadic-NEologd)Installation de
!apt-get -q -y install sudo file mecab libmecab-dev mecab-ipadic-utf8 git curl python-mecab > /dev/null
!git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git > /dev/null
!echo yes | mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n > /dev/null 2>&1
!pip install mecab-python3 > /dev/null
#Éviter les erreurs avec les liens symboliques
!ln -s /etc/mecabrc /usr/local/etc/mecabrc
#Les n(=10000)Séparer par moins et combiner par des virgules
#Le but du délimiteur est que le dernier mécab ne peut pas gérer trop de caractères.
sentences_sep = []
n = 10000
for i in range(0, len(res_df["comment"]), n):
sentences_sep.append(",".join(res_df["comment"][i: i + n]))
# ------------------------------------------------------------------------
import MeCab
# mecab-ipadic-Spécifiez le chemin où le dictionnaire neologd est stocké
path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
#Au-dessus du chemin (/usr/~) Peut être obtenu avec la commande suivante
# !echo `mecab-config --dicdir`"/mecab-ipadic-neologd"
#Créer un objet Tagger
mecab = MeCab.Tagger(path)
#Effectuer une analyse morphologique pour chaque groupe séparé
chasen_list = [mecab.parse(sentence) for sentence in sentences_sep]
word_list = []
# chasen_Décomposer la liste en une seule ligne
# ex.Géant de fer,Nomenclature propriétaire,Général,*,*,*,Géant de fer,Tetsukyojin,Tetsukyojin)
for chasen in chasen_list:
for line in chasen.splitlines():
if len(line) <= 1: break
speech = line.split()[-1]
if "nom" in speech:
if (not "Non indépendant" in speech) and (not "Synonyme" in speech) and (not "nombre" in speech):
word_list.append(line.split()[0])
word_line = ",".join(word_list)
# ------------------------------------------------------------------------
from wordcloud import WordCloud
import matplotlib.pyplot as plt
f_path = "BIZ-UDGothicB.ttc" #Doit être copié dans le dossier local des polices de Colab
stop_words = ["https","imgur","net","jpg","com","alors"]
#Génération d'instance (paramétrage)
wordcloud = WordCloud(
font_path=f_path, #Spécifiez la police
width=1024, height=640, #Spécifier la taille de l'image générée
background_color="white", #Spécifier la couleur d'arrière-plan
stopwords=set(stop_words), #Mots qui ne sont pas affichés intentionnellement
max_words=350, #Nombre maximum de mots
max_font_size=200, min_font_size=5, #Plage de tailles de police
collocations = False #Affichage des mots composés
)
#Génération d'images
output_img = wordcloud.generate(word_line)
#indiquer
plt.figure(figsize=(18,15)) #Spécifiez la taille à afficher avec figsize
plt.imshow(output_img)
plt.axis("off") #Cacher l'échelle
plt.show()
L'analyse morphologique est le processus de décomposition d'une phrase en langage naturel en mots (plus précisément, des unités appelées éléments morphologiques qui sont plus fins que des mots). Contrairement à l'anglais, le japonais n'insère pas d'espaces entre les mots, il est donc nécessaire d'effectuer ** une analyse morphologique pour séparer les mots **. Il existe plusieurs outils d'analyse morphologique, mais cette fois nous utiliserons "Mecab", qui a une vitesse de traitement élevée et une grande précision.
Mecab n'est pas inclus dans Google Colaboratory par défaut, alors installez-le en exécutant ce qui suit à chaque fois.
#Installez Mecab
!apt-get -q -y install sudo file mecab libmecab-dev mecab-ipadic-utf8 git curl python-mecab > /dev/null
!pip install mecab-python3 > /dev/null
#Éviter les erreurs avec les liens symboliques
!ln -s /etc/mecabrc /usr/local/etc/mecabrc
Le dictionnaire par défaut de Mecab "mecab-ipadic" n'est pas très précis pour les nouveaux mots. Par conséquent, nous recommandons la spécification du dictionnaire ** "mecab-ipadic-NEologd" **. "Mecab-ipadic-NEologd" est l'un des dictionnaires système qui peuvent être utilisés avec Mecab, et comme il est fréquemment mis à jour, il se caractérise par sa résistance aux nouveaux mots **. Par exemple, lorsque le mot-clé "Aeris" est analysé morphologiquement. Dans le dictionnaire par défaut, il est divisé en "air / écureuil", mais dans "mecab-ipadic-NEologd", "airis" est correctement jugé comme un mot. Dans un environnement où les nouveaux mots tels que 2ch sont bâclés, l'utilisation de "mecab-ipadic-NEologd" devrait améliorer la précision de l'analyse. La méthode d'installation est la suivante.
#dictionnaire(mecab-ipadic-NEologd)Installation de
!git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git > /dev/null
!echo yes | mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n > /dev/null 2>&1
Lors d'un appel ultérieur avec Mecab, il est nécessaire de spécifier le chemin où le dictionnaire mecab-ipadic-neologd est stocké, définissez-le donc.
path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
!echo `mecab-config --dicdir`"/mecab-ipadic-neologd"
Il y a deux points lors de la transmission de données texte à Mecab -Mecab transmet une donnée de type str (dans ce cas, une chaîne de caractères combinée avec une virgule) -Si le type de chaîne ci-dessus contient trop de données ** , l'analyse échouera, il est donc nécessaire de diviser et de transmettre les données à Mecab **. Par conséquent, le contenu moins gratté précédemment (type DataFrame: res_df) est connecté à une chaîne pour 10000 moins. Je l'ai stocké dans la liste l'un après l'autre.
#Les n(=10000)Séparer par moins et combiner par des virgules
#Le but du délimiteur est que le dernier mécab ne peut pas gérer trop de caractères.
sentences_sep = []
n = 10000
for i in range(0, len(res_df["comment"]), n):
sentences_sep.append(",".join(res_df["comment"][i: i + n]))
Mecab est exécuté dans le flux de (1) Création de l'instance Mecab.Tagger
→(2) Passer le texte cible à l'instance et analyser (analyser)
.
Lors de la création de l'instance de ①, spécifiez l'option d'analyse.
Je souhaite utiliser le dictionnaire système "mecab-ipadic-NEologd" mentionné ci-dessus, spécifiez donc le chemin obtenu à l'avance.
Le résultat de l'analyse de ② est acquis par Tagger instance.parse (str type)
.
Dans ce cas, comme mentionné ci-dessus, le moins de groupe était divisé en un type de liste, j'ai donc essayé de le traiter en utilisant la notation d'inclusion comme python.
import MeCab
#Génération d'instance
mecab = MeCab.Tagger(path)
#Effectuer une analyse morphologique pour chaque groupe séparé
chasen_list = [mecab.parse(sentence) for sentence in sentences_sep]
La sortie sera de type str avec les sauts de ligne et les délimiteurs de tabulation suivants.
Parmi les mots découpés, les mots qui n'ont pas de sens en eux-mêmes, tels que «mots auxiliaires», «verbes auxiliaires» et «adjoints», peuvent être du bruit, ils sont donc exclus.
Cette fois, j'ai essayé d'extraire simplement les "noms". Cependant, parmi la nomenclature, la non-indépendance, les synonymes, les nombres, etc. sont exclus car ils sont susceptibles de provoquer du bruit.
En tant que processus, le type str du résultat de sortie Mecab est décomposé ligne par ligne avec .splitlines ()
→ ensuite décomposé en informations de mots et de parties de paroles avec .split ()
→ Lorsque les informations de mot de partie correspondent à la condition, la partie de mot est ajoutée à word_list.
#Suppression du bruit (mots de partie inutiles)
for chasen in chasen_list:
for line in chasen.splitlines():
if len(line) <= 1: break
speech = line.split()[-1] ##Extraire les informations des paroles de la partie
if "nom" in speech:
if (not "Non indépendant" in speech) and (not "Synonyme" in speech) and (not "nombre" in speech):
word_list.append(line.split()[0])
ʻSi len (line) <= 1: break` sur le chemin est une contre-mesure d'erreur (probablement due à EOS). Enfin, le type de liste est concaténé en un type str.
#Concaténation de mots
word_line = ",".join(word_list)
Lors de l'application du japonais à WordCloud, il est nécessaire de spécifier la police pour être compatible avec le japonais. S'il est local, il suffit de spécifier le chemin de la police souhaitée, Dans le cas de Google Colaboratory, c'est un peu gênant. ↓ Tout d'abord, ** copiez à l'avance le fichier de police souhaité sur votre Google Drive ** (seules les polices TrueType sont prises en charge). L'emplacement est arbitraire, mais par analogie avec l'article auquel j'ai fait référence, j'ai créé un dossier «font» dans My Drive Top et y ai stocké les fichiers. Montez Google Drive sur le colaboratoire.
#Installer les polices localement dans Colab
from google.colab import drive
drive.mount("/content/gdrive")
Lorsque vous exécutez ce qui précède, un lien pour monter Google Drive s'affiche. Cliquez dessus pour sélectionner un compte → Autoriser → Entrez le code affiché sur Google Colaboratory pour le monter.
Utilisez la commande pour copier le fichier de police avec le dossier dans le dossier spécifié localement dans Colaboratory.
!cp -a "gdrive/My Drive/font/" "/usr/share/fonts/"
Importez la bibliothèque WordCloud et créez une instance avec WordCloud ()
.
Divers paramètres de sortie peuvent être définis en donnant un argument dans this ().
from wordcloud import WordCloud
f_path = "BIZ-UDGothicB.ttc" #Doit être copié dans le dossier local des polices de Colab
stop_words = ["https","imgur","net","jpg","com","alors"]
#Génération d'instance (paramétrage)
wordcloud = WordCloud(
font_path=f_path, #Spécifiez la police
width=1024, height=640, #Spécifier la taille de l'image générée
background_color="white", #Spécifier la couleur d'arrière-plan
stopwords=set(stop_words), #Mots qui ne sont pas affichés intentionnellement
max_words=350, #Nombre maximum de mots
max_font_size=200, min_font_size=5, #Plage de tailles de police
collocations = False #Affichage des mots composés
)
Le contenu de chaque paramètre est le suivant.
Paramètres | La description | Définir la valeur |
---|---|---|
font_path | Spécifiez la police | Le chemin de police mentionné ci-dessus (f_path) |
colormap | Jeu de couleurs de police (Spécifié par la carte de couleurs matplotlib) |
Non défini (par défaut: viridis) |
width | Largeur de l'image générée | 1024 |
height | Hauteur de l'image générée | 640 |
background_color | Couleur de l'arrière plan | white |
stopwords | Mots qui ne sont pas affichés intentionnellement (définis) | ["https","imgur","net","jpg","com","alors"] |
max_words | Nombre maximum de mots à afficher | 350 |
max_font_size | Taille de police pour le plus de mots | 200 |
min_font_size | La plus petite taille de police de mots | 5 |
collocations | Afficher ou non les mots connectés | False |
Pour les paramètres autres que ceux ci-dessus, reportez-vous à l'article de l'article ci-dessous.
Générez une figure à partir de la chaîne de caractères cible avec la méthode .generate (concatenated word group: str type)
de l'instance wordcloud générée ci-dessus.
#Générer une image WordCloud en donnant une chaîne
output_img = wordcloud.generate(word_line)
import matplotlib.pyplot as plt
plt.figure(figsize=(18,15)) #Spécifiez la taille à afficher avec figsize
plt.imshow(output_img)
plt.axis("off") #Cacher l'échelle
plt.show()
J'ai pu l'afficher en toute sécurité.
Pour le moment, j'ai réussi à le visualiser, mais j'ai l'impression que c'est devenu flou. Je pense qu'une des raisons est que «l'axe du temps» et la «corrélation entre les mots» ont disparu. Alors quand tu as le temps ・ Affichage de la corrélation avec l'axe du temps (graphique) ・ Je veux jouer avec le réseau de cooccurrence. ~~ Je suis fatigué d'écrire un long article ~~ Je ne sais pas s'il faut écrire un article.
Résumé de l'utilisation de Google Colab Installez MeCab et ipadic-NEologd sur Google Colab Comment mettre votre police préférée dans Google Colaboratory et l'utiliser avec matplotlib J'ai essayé de créer Word Cloud avec Python ← Il y a une explication des paramètres wordcloud non mentionnés cette fois
Recommended Posts