[PYTHON] Lassen Sie uns 2ch Thread mit WordCloud-morphologische Analyse / WordCloud Edition- visualisieren

Einführung

2ch braucht Zeit, um jeden Threadless zu lesen Ich habe versucht, die Thread-Informationen mit WordCloud zu visualisieren und das gesamte Bild einfach zu erhalten. In der vorherigen Scraping Edition wurde der geringere Inhalt der gewünschten Thread-Gruppe extrahiert. Dieses Mal werden wir als zweiten Teil den Inhalt der zuletzt gesammelten Lektionen analysieren und in WordCloud ausgeben.

Gesamtdurchfluss

  1. Scraping "Protokollgeschwindigkeit", um die URL des Ziel-Threads zu extrahieren
  2. 2ch Faden abkratzen, um weniger zu extrahieren
  3. [Morphologische Analyse von mit Mecab extrahiertem weniger Inhalt](## Morphologische Analyse mit Mecab) ← Erklärung dieses Mal
  4. [Ausgabe mit WordCloud](## Ausgabe mit WordCloud) ← Erklärung dieses Mal

Umgebung

Verwenden Sie nach wie vor Google Colaboratory. Google Colaboratory ist eine Python-Ausführungsumgebung, die in einem Browser ausgeführt wird. Jeder mit einem Google-Konto kann es verwenden. Mecab benötigt eine zusätzliche Installation (später beschrieben), WordCloud ist jedoch standardmäßig in Google Colaboratory enthalten, sodass keine Installation erforderlich ist.

Vollständiger Code

Klicken Sie hier, um den vollständigen Text (einschließlich Scraping) anzuzeigen.
#Bibliothek importieren
import requests, bs4
import re
import time
import pandas as pd
from urllib.parse import urljoin

#Installieren Sie Schriftarten lokal in Colab
from google.colab import drive
drive.mount("/content/gdrive")
#Erstellen Sie vorab einen Ordner mit dem Namen "Schriftart" oben auf "Mein Laufwerk" auf Ihrem Google Drive und legen Sie die gewünschte Schriftartdatei darin ab.
#Kopieren Sie jeden Ordner lokal nach Colab
!cp -a "gdrive/My Drive/font/" "/usr/share/fonts/"

# ------------------------------------------------------------------------
#Vorbereitung
log_database = []  #Eine Liste, in der Thread-Informationen gespeichert sind
base_url = "https://www.logsoku.com/search?q=FFRK&p="

#Implementierung von Web Scraping
for i in range(1,4):  #Auf welche Seite Sie zurückkehren sollten (hier vorläufig bis zur 4. Seite)
  logs_url = base_url+str(i)

  #Schrottverarbeitungskörper
  res = requests.get(logs_url)
  soup = bs4.BeautifulSoup(res.text, "html.parser")

  #Was tun, wenn keine Suchergebnisse gefunden werden?
  if soup.find(class_="search_not_found"):break

  #Ruft die Tabelle / Zeile ab, in der die Thread-Informationen gespeichert sind
  thread_table = soup.find(id="search_result_threads")
  thread_rows = thread_table.find_all("tr")

  #Verarbeitung für jede Zeile
  for thread_row in thread_rows:
    tmp_dict = {}
    tags = thread_row.find_all(class_=["thread","date","length"])

    #Organisieren Sie den Inhalt
    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

    #Nur diejenigen mit mehr als 50 Lektionen werden der Datenbank hinzugefügt
    if tmp_dict["length"].isdecimal() and int(tmp_dict["length"]) > 50:
      log_database.append(tmp_dict)

  time.sleep(1)

#In DataFrame konvertieren
thread_df = pd.DataFrame(log_database)

# ------------------------------------------------------------------------
#Holen Sie weniger aus früheren Protokollen
log_url_base = "http://nozomi.2ch.sc/test/read.cgi/"
res_database = []

for thread in log_database:
  #Boardname und Bulletin Board-Nummer aus der Liste der letzten Protokolle.Und generieren Sie die URL des letzten Protokolls
  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)

  #Extrahieren Sie HTML von der letzten Protokollseite
  res = requests.get(thread_url)
  soup = bs4.BeautifulSoup(res.text, "html5lib")

  tmp_dict = {}
  #Informationen wie Datum im dt-Tag
  #Der Kommentar wird im dd-Tag gespeichert
  dddt = soup.find_all(["dd","dt"])

  for tag in dddt[::-1]:  #Auszug von hinten

    #Extrahieren Sie nur das Datum aus dem dt-Tag
    if "<dt>" in str(tag):
      date_result = re.search(r"\d*/\d*/\d*",tag.text)  #  "(←'"'Es ist mir egal (um Anomalien des Qiita zu vermeiden)
      if date_result:
        date_str = date_result.group()
        tmp_dict["date"] = date_str

    #Extrahieren Sie weniger Inhalt aus dem dd-Tag
    if "<dd>" in str(tag):
      tmp_dict["comment"] = re.sub("\n","",tag.text)

    # tmp_Die in dict gespeicherten Inhalte sind res_In Datenbank posten
    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)  #versprechen

#In DataFrame konvertieren
res_df = pd.DataFrame(res_database)

# ------------------------------------------------------------------------

#Morphologische Analysebibliothek MeCab und Wörterbuch(mecab-ipadic-NEologd)Installation von
!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

#Vermeiden von Fehlern mit symbolischen Links
!ln -s /etc/mecabrc /usr/local/etc/mecabrc


#Les n(=10000)Durch weniger trennen und mit Kommas kombinieren
#Der Zweck des Trennzeichens besteht darin, dass das spätere Mecab nicht zu viele Zeichen verarbeiten kann.
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-Geben Sie den Pfad an, in dem das neologd-Wörterbuch gespeichert ist
path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
#Über dem Pfad (/usr/~) Kann mit dem folgenden Befehl erhalten werden
# !echo `mecab-config --dicdir`"/mecab-ipadic-neologd"

#Erstellen eines Tagger-Objekts
mecab = MeCab.Tagger(path)

#Führen Sie für jede getrennte Gruppe eine morphologische Analyse durch
chasen_list = [mecab.parse(sentence) for sentence in sentences_sep]

word_list = []

# chasen_Zerlegen Sie die Liste in eine Zeile
# ex.Eisen Riesennomen,Proprietäre Nomenklatur,Allgemeines,*,*,*,Eisenriese,Tetsukyojin,Tetsukyojin)
for chasen in chasen_list:
  for line in chasen.splitlines():
    
    if len(line) <= 1: break

    speech = line.split()[-1]
    if "Substantiv" in speech:
      if  (not "Nicht unabhängig" in speech) and (not "Gleichbedeutend" in speech) and (not "Nummer" 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"  #Muss in den lokalen Schriftartenordner von Colab kopiert werden
stop_words = ["https","imgur","net","jpg","com","damit"]

#Instanzgenerierung (Parametereinstellung)
wordcloud = WordCloud(
    font_path=f_path, #Geben Sie die Schriftart an
    width=1024, height=640,   #Angeben der Größe des generierten Bildes
    background_color="white",   #Festlegen der Hintergrundfarbe
    stopwords=set(stop_words),   #Wörter, die nicht absichtlich angezeigt werden
    max_words=350,   #Maximale Anzahl von Wörtern
    max_font_size=200, min_font_size=5,   #Schriftgrößenbereich
    collocations = False    #Anzeige zusammengesetzter Wörter
    )

#Bilderzeugung
output_img = wordcloud.generate(word_line)

#zeigen
plt.figure(figsize=(18,15))  #Geben Sie die Größe an, die mit figsize angezeigt werden soll
plt.imshow(output_img)
plt.axis("off")  #Verstecke die Waage
plt.show()

Erläuterung

Morphologische Analyse von Mecab

Bei der morphologischen Analyse wird ein Satz in natürlicher Sprache in Wörter zerlegt (genauer gesagt Einheiten, die als morphologische Elemente bezeichnet werden und feiner als Wörter sind). Im Gegensatz zu Englisch fügt Japanisch keine Leerzeichen zwischen Wörtern ein, daher ist es erforderlich, eine morphologische Analyse durchzuführen, um Wörter zu trennen. Es gibt verschiedene Werkzeuge für die morphologische Analyse, aber dieses Mal werden wir "Mecab" verwenden, das eine hohe Verarbeitungsgeschwindigkeit und hohe Genauigkeit aufweist.

Installieren Sie Mecab

Mecab ist standardmäßig nicht in Google Colaboratory enthalten. Installieren Sie es daher, indem Sie jedes Mal Folgendes ausführen.

#Installieren Sie 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

#Vermeiden von Fehlern mit symbolischen Links
!ln -s /etc/mecabrc /usr/local/etc/mecabrc

Angeben eines Wörterbuchs (mecab-ipadic-NEologd)

Mecabs Standardwörterbuch "mecab-ipadic" ist für neue Wörter nicht sehr genau. Daher empfehlen wir die Angabe des Wörterbuchs ** "mecab-ipadic-NEologd" **. "Mecab-ipadic-NEologd" ist eines der Systemwörterbücher, die mit Mecab verwendet werden können. Da es häufig aktualisiert wird, zeichnet es sich dadurch aus, dass es gegen neue Wörter stark ist **. Zum Beispiel, wenn das Schlüsselwort "Aeris" morphologisch analysiert wird. Im Standardwörterbuch ist es in "Luft / Eichhörnchen" unterteilt, aber in "mecab-ipadic-NEologd" wird "airis" richtig als ein Wort beurteilt. In einer Umgebung, in der neue Wörter wie 2ch schlampig sind, sollte die Verwendung von "mecab-ipadic-NEologd" die Genauigkeit der Analyse verbessern. Die Installationsmethode ist wie folgt.

#Wörterbuch(mecab-ipadic-NEologd)Installation von
!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

Wenn Sie später mit Mecab aufrufen, müssen Sie den Pfad angeben, in dem das Wörterbuch mecab-ipadic-neologd gespeichert ist. Definieren Sie ihn daher.

path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
Wenn es nicht funktioniert (zum Anzeigen klicken)
Der obige Pfad (/ usr / ~) sollte grundsätzlich in Ordnung sein. Wenn dies jedoch nicht funktioniert, rufen Sie den Wörterbuchpfad mit dem folgenden Befehl ab.
!echo `mecab-config --dicdir`"/mecab-ipadic-neologd"

Datenvorverarbeitung für die morphologische Analyse

Es gibt zwei Punkte beim Übergeben von Textdaten an Mecab -Mecab übergibt Daten vom Typ str (in diesem Fall eine Zeichenfolge in Kombination mit einem Komma) -Wenn der oben genannte str-Typ zu viel ** Datenmenge enthält, schlägt die Analyse fehl. Daher müssen die Daten geteilt und an Mecab ** übergeben werden. Daher wird der zuvor weniger abgekratzte Inhalt (DataFrame-Typ: res_df) für jeweils 10000 weniger mit einem Str verbunden. Ich habe es nacheinander in der Liste gespeichert.

#Les n(=10000)Durch weniger trennen und mit Kommas kombinieren
#Der Zweck des Trennzeichens besteht darin, dass das spätere Mecab nicht zu viele Zeichen verarbeiten kann.
sentences_sep = []
n = 10000
for i in range(0, len(res_df["comment"]), n):
  sentences_sep.append(",".join(res_df["comment"][i: i + n]))

Morphologische Analyse durchführen

Mecab wird im Ablauf von "(1) Erstellung der Mecab.Tagger-Instanz" → "(2) Übergeben des Zieltextes an die Instanz und Analysieren (Analysieren)" ausgeführt. Geben Sie beim Erstellen der Instanz von ① die Analyseoption an. Ich möchte das oben erwähnte Systemwörterbuch "mecab-ipadic-NEologd" verwenden. Geben Sie daher den zuvor erhaltenen Pfad an. Das Analyseergebnis von ② wird von Tagger instance.parse (str type) erfasst. In diesem Fall wurde, wie oben erwähnt, die weniger große Gruppe in einen Listentyp unterteilt, daher habe ich versucht, sie mit der Einschlussnotation wie Python zu verarbeiten.

import MeCab

#Instanzgenerierung
mecab = MeCab.Tagger(path)

#Führen Sie für jede getrennte Gruppe eine morphologische Analyse durch
chasen_list = [mecab.parse(sentence) for sentence in sentences_sep]

Die Ausgabe ist ein str-Typ mit den folgenden Zeilenumbrüchen und Tabulatortrennzeichen.

Geräuschreduzierung

Von den Wörtern, die ausgeschnitten wurden, können Wörter, die für sich genommen keinen Sinn ergeben, wie "Hilfswörter", "Hilfsverben" und "Zusatzwörter", Rauschen sein, daher werden sie ausgeschlossen. Dieses Mal habe ich versucht, einfach nur "Substantive" zu extrahieren. In der Nomenklatur sind jedoch Nichtunabhängigkeit, Synonyme, Zahlen usw. ausgeschlossen, da sie wahrscheinlich Rauschen verursachen. Als Prozess wird der str-Typ des Mecab-Ausgabeergebnisses Zeile für Zeile mit .splitlines () → weiter zerlegt in Wort- und Teiltextinformationen mit .split () zerlegt → Wenn die Teilwortinformationen der Bedingung entsprechen, wird der Wortteil zur Wortliste hinzugefügt.

#Rauschunterdrückung (unnötige Teilwörter)
for chasen in chasen_list:
  for line in chasen.splitlines():
    
    if len(line) <= 1: break

    speech = line.split()[-1]  ##Informationen zum Teiltext extrahieren
    if "Substantiv" in speech:
      if  (not "Nicht unabhängig" in speech) and (not "Gleichbedeutend" in speech) and (not "Nummer" in speech):
        word_list.append(line.split()[0])

Wenn len (line) <= 1: break auf dem Weg ist ein Fehler (wahrscheinlich aufgrund von EOS) Gegenmaßnahme. Schließlich wird der Listentyp zu einem Str-Typ verkettet.

#Wortverkettung
word_line = ",".join(word_list)

Ausgabe mit WordCloud

(Vorbereitung) Installation japanischer Schriftarten

Wenn Sie Japanisch auf WordCloud anwenden, müssen Sie die Schriftart angeben, die mit Japanisch kompatibel ist. Wenn es lokal ist, müssen Sie nur den Pfad der gewünschten Schriftart angeben. Im Fall von Google Colaboratory ist dies etwas problematisch.    ↓ ** Kopieren Sie zunächst die gewünschte Schriftartdatei im Voraus auf Ihr Google Drive ** (nur TrueType-Schriftarten werden unterstützt). Der Speicherort ist beliebig, aber in Analogie zu dem Artikel, auf den ich verwiesen habe, habe ich in My Drive Top einen Ordner "font" erstellt und die Dateien darin gespeichert. Mounten Sie Google Drive im Labor.

#Installieren Sie Schriftarten lokal in Colab
from google.colab import drive
drive.mount("/content/gdrive")

Wenn Sie den obigen Vorgang ausführen, wird ein Link zum Mounten von Google Drive angezeigt. Klicken Sie darauf, um ein Konto auszuwählen. → Zulassen → Geben Sie den angezeigten Code in Google Colaboratory ein, um es zu mounten.

Verwenden Sie den Befehl, um die Schriftartdatei zusammen mit dem Ordner lokal in Colaboratory in den angegebenen Ordner zu kopieren.

!cp -a "gdrive/My Drive/font/" "/usr/share/fonts/"
Wenn es nicht funktioniert (zum Anzeigen klicken) Aus irgendeinem Grund ist beim Mounten des Laufwerks einmal ein Fehler aufgetreten und ich konnte die Schriftart nicht installieren. Laden Sie in diesem Fall die Datei direkt in den lokalen Schriftartenordner von Google Colaboratory hoch. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642673/74d79528-0f78-b5ce-8275-079f4e74f2ce.png)

Führen Sie Word Cloud aus

Importieren Sie die WordCloud-Bibliothek und erstellen Sie eine Instanz mit "WordCloud ()". Verschiedene Ausgabeparameter können durch Angabe eines Arguments in this () festgelegt werden.

from wordcloud import WordCloud

f_path = "BIZ-UDGothicB.ttc"  #Muss in den lokalen Schriftartenordner von Colab kopiert werden
stop_words = ["https","imgur","net","jpg","com","damit"]

#Instanzgenerierung (Parametereinstellung)
wordcloud = WordCloud(
    font_path=f_path, #Geben Sie die Schriftart an
    width=1024, height=640,   #Angeben der Größe des generierten Bildes
    background_color="white",   #Festlegen der Hintergrundfarbe
    stopwords=set(stop_words),   #Wörter, die nicht absichtlich angezeigt werden
    max_words=350,   #Maximale Anzahl von Wörtern
    max_font_size=200, min_font_size=5,   #Schriftgrößenbereich
    collocations = False    #Anzeige zusammengesetzter Wörter
    )

Der Inhalt jedes Parameters ist wie folgt.

Parameter Erläuterung Wert einstellen
font_path Geben Sie die Schriftart an Der oben erwähnte Schriftpfad (f_path)
colormap Schriftfarbe eingestellt
(Angegeben durch Matplotlib-Farbkarte)
Nicht festgelegt (Standard: viridis)
width Breite des erzeugten Bildes 1024
height Höhe des erzeugten Bildes 640
background_color Hintergrundfarbe white
stopwords Wörter, die nicht absichtlich angezeigt werden (gesetzt) ["https","imgur","net","jpg","com","damit"]
max_words Maximale Anzahl der anzuzeigenden Wörter 350
max_font_size Schriftgröße für die meisten Wörter 200
min_font_size Kleinste Wortschriftgröße 5
collocations Gibt an, ob verbundene Wörter angezeigt werden sollen False

Weitere Parameter als die oben genannten finden Sie im Artikel im folgenden Artikel. Generieren Sie eine Zahl aus der Zielzeichenfolge mit der Methode ".generate (verkettete Wortgruppe: str-Typ)" der oben generierten Wordcloud-Instanz.

#Generieren Sie ein WordCloud-Bild, indem Sie eine Zeichenfolge angeben
output_img = wordcloud.generate(word_line)

Wird mit matplotlib angezeigt

import matplotlib.pyplot as plt

plt.figure(figsize=(18,15))  #Geben Sie die Größe an, die mit figsize angezeigt werden soll
plt.imshow(output_img)
plt.axis("off")  #Verstecke die Waage
plt.show()
Ich konnte es sicher anzeigen.

Eindrücke / Zukunft

Vorerst habe ich es geschafft, es zu visualisieren, aber ich habe das Gefühl, dass es verschwommen ist. Ich denke, einer der Gründe ist, dass die "Zeitachse" und die "Korrelation zwischen Wörtern" verschwunden sind. Also wenn du Zeit hast ・ Korrelationsanzeige mit Zeitachse (Grafik) ・ Ich möchte mit dem Koexistenznetzwerk spielen. ~~ Ich bin es leid, einen langen Artikel zu schreiben ~~ Es ist unentschlossen, ob ich einen Artikel schreiben soll.

Referenzartikel

Zusammenfassung der Verwendung von Google Colab Installieren Sie MeCab und ipadic-NEologd auf Google Colab So fügen Sie Ihre Lieblingsschriftart in Google Colaboratory ein und verwenden sie mit matplotlib Ich habe versucht, Word Cloud mit Python zu erstellen ← Es gibt eine Erklärung der Wordcloud-Parameter, die diesmal nicht erwähnt werden

Recommended Posts