[PYTHON] [Version 2020] Scraping und Verarbeitung des Textes von Aozora Bunko

Überblick

Ich habe den Text der in Aozora Bunko veröffentlichten Arbeit mit Python abgekratzt und zu einem schönen Gefühl verarbeitet. Zu dieser Zeit war ich hier und da süchtig danach, also dieses Memorandum.

Umgebung

Texterfassung

Holen Sie sich zuerst den Text der Arbeit von Aozora Bunko. Was zu tun ist, ist im Wesentlichen wie in diesem Artikel beschrieben (https://qiita.com/icy_mountain/items/011c9f56151b9832b54d), [Aozora Bunko API (https://qiita.com/ksato9700/items/626cc82c007ba8337034) Drücken Sie, um den HTML-Code des Körpers abzurufen. Zu diesem Zeitpunkt wird der Arbeits-ID-Teil der URL auf "book_id" und eine Variable gesetzt. In meiner eigenen Umgebung konnte ich dies jedoch nicht tun. Zuerst habe ich am Jupyter-Notizbuch anstatt am Terminal gearbeitet, daher kann ich den Befehl ! Wget nicht verwenden. Wenn Sie also den Befehl nachschlagen, der eine GET-Anforderung an die API in Python sendet, werden zwei angezeigt: "urllib2.urlopen ()" und "reqests.req ()". Von diesen ist "urllib2" eine Bibliothek für Python2. Kann ich nicht benutzen. Es scheint, dass es in Python3 in "urllib3" oder "urllib" umbenannt wurde, aber ich war mir nicht sicher, also habe ich beschlossen, die "Anfragen" -Bibliothek zu verwenden. Der API-Abruf mit der GET-Methode sieht also folgendermaßen aus:

import requests
res = requests.get('http://pubserver2.herokuapp.com/api/v0.1/books/{book_id}/content?format=html'.format(book_id))

Extraktion von Text

Konvertieren Sie anschließend die abgerufenen HTML-Daten in ein Format, das von BeautifulSoup4 verwendet werden kann.

from bs4 import BeautifulSoup
soup = BeautifulSoup(res.text, 'html.parser')

Um den Text des title -Tags von hier zu erhalten, schreiben Sie:

soup.find('title').get_text()
# ->Hisaku Yumeno Ao Suisen, Roter Suisen

Die Titel sind durch Leerzeichen mit halber Breite gut voneinander getrennt. Wenn Sie hier also "split ()" ausführen, können Sie sie in den Namen und den Titel des Autors unterteilen. In einigen Fällen, z. B. bei ausländischen Autoren, läuft es möglicherweise nicht gut, sodass das Vorhandensein oder Fehlen der verbleibenden Informationen auch in der Variablen festgelegt wird.

title_list = title.split(' ')
        book_author = title_list[0] #Autorenname
        book_title = title_list[1] #Titel
        book_title_info = len(title_list) > 2 #Ist der Titel gebrochen?

Auf der anderen Seite ist der Körper (im wahrsten Sinne des Wortes) das "div" -Tag der "main_text" -Klasse, also würde es so aussehen:

soup.find('div', {'class': 'main_text'}).get_text()
# -> \n\n\n\r\n\u3000 Utako wurde von einem Freund gelehrt, die Wurzeln von Narzissen zu schneiden, rote und blaue Farben in sie zu geben und sie in der Ecke des Gartens zu begraben.[...]

Dieses Mal möchte ich Sätze durch Interpunktion trennen, daher erstelle ich für jeden Satz ein Listenformat wie folgt. Wenn Sie den ersten Satz möchten, können Sie ihn als 0. Element erhalten.

text_list = soup.find('div', {'class': 'main_text'}).get_text().split('。')
text_first = text_list[0] + "。" #Der erste Satz

Reinigung von Text

Wenn dies so bleibt, wird der Text verschmutzt, sodass unnötige Elemente entfernt und der Text verfeinert werden. Da der Code, der dem Zeilenvorschubcode "\ n" und dem Raum halber Breite "\ u3000" entspricht, gemischt ist, lassen Sie ihn zunächst mit "strip ()" nach "get_text ()" fallen.

text_list = soup.find('div', {'class': 'main_text'}).get_text().strip('\r''\n''\u3000').split('。')

Um den in Text in Klammern eingeschlossenen Teil des Rubins zu entfernen, fügen Sie unmittelbar nach der Konvertierung den folgenden Code hinzu, um den Rubin zu entfernen.

    for tag in soup.find_all(["rt", "rp"]):
        tag.decompose() #Tags und deren Inhalt löschen

Manchmal wird es nicht durch Interpunktion getrennt, und der erste Satz kann endlos fortgesetzt werden. Wenn er also zu lang ist, werde ich ihn durch eine andere Zeichenfolge ersetzen. Der Längenstandard 100 ist angemessen.

text_first = text_list[0] + "。" if (len(text_list[0]) < 100) else "too long" #Anfang

Wenn beim Konvertieren des obigen Prozesses in eine Funktion die entsprechende Arbeits-ID nicht vorhanden ist und das Abrufen fehlschlägt, tritt zum Zeitpunkt der Extraktion ein NoneType-Fehler auf. Schließen Sie dies daher durch das Vorhandensein oder Fehlen von Tags und Klassen aus. (Ich denke, es gibt einen besseren Weg, es zu schreiben).

if (soup.find('title') is None) or (soup.find('div') is None) or (soup.find('div', {'class': 'main_text'}) is None):
        return [book_id, '', '', '', '', '' ]
else:
        title =  soup.find('title').get_text()
        [...]

bookInfo.py


def bookInfo(book_id):
    import requests
    from bs4 import BeautifulSoup

    res = requests.get(f'http://pubserver2.herokuapp.com/api/v0.1/books/{book_id}/content?format=html')
    
    soup = BeautifulSoup(res.text, 'html.parser')
    for tag in soup.find_all(["rt", "rp"]):
        tag.decompose() #Tags und deren Inhalt löschen
    
    if (soup.find('title') is None) or (soup.find('div') is None) or (soup.find('div', {'class': 'main_text'}) is None):
        return [book_id, '', '', '', '']
    else:
        title =  soup.find('title').get_text()
        title_list = title.split(' ')
        book_author = title_list[0] #Autorenname
        book_title = title_list[1] #Titel
        book_title_info = len(title_list) > 2 #Ist der Titel gebrochen?
        
        print(soup.find('div', {'class': 'main_text'}))
        text_list = soup.find('div', {'class': 'main_text'}).get_text().strip('\r''\n''\u3000').split('。')
        text_first = text_list[0] + "。" if (len(text_list[0]) < 100) else "too long" #Anfang
        else:
            text_last = ""
    
        list = [book_id, book_author, book_title, book_title_info, text_first]
        print(list)
        return list
bookInfo(930)
# -> [930,
# 'Hisaku Yumeno',
# 'Das Wunder von Oshie',
# False,
# 'Wenn ich die Schlaflücke der Krankenschwester sehe, habe ich eine arme weibliche Figur, daher denke ich, dass es schwierig ist zu lesen und zu verstehen, aber ich werde Ihnen viele Male vergeben, wenn ich mich beeile. Bitte.']

CSV-Ausgabe von verfeinerten Daten

Ich möchte die mit der obigen Funktion erhaltenen Listen hinzufügen, um eine zweidimensionale Liste zu erstellen und sie als CSV-Datei auszugeben. Importieren Sie zuerst csv und öffnen Sie die Datei. Übrigens, wenn die Datei bereits vorhanden ist und Sie sie nach dem vollständigen Text hinzufügen möchten, anstatt sie zu überschreiben, ändern Sie "w" in "a".

import csv
f = open('output.csv', 'w')
writer = csv.writer(f, lineterminator='\n')

Erstellen Sie eine leere Liste und drehen Sie die for-Schleife, um den Rückgabewert der Ausführung der Funktion zur Liste hinzuzufügen. Mit der Aozora Bunko-API dauerte es übrigens einige Sekunden, bis eine Arbeit fertig war. Ich bin der Meinung, dass wenn Sie zu viele Anfragen anfordern, diese unbrauchbar werden. Ich denke, es ist besser, sie in kleinen Einheiten wie 10 oder 100 auszuführen.

csvlist = []
for i in range(930, 940):
    csvlist.append(bookInfo(i))

Schließen Sie schließlich die Datei und Sie sind fertig.

writer.writerows(csvlist)
f.close()

Eine CSV-Datei wurde ausgegeben. Es ist bequem, es in eine Google-Tabelle zu laden.

930,Hisaku Yumeno,Das Wunder von Oshie,False,Wenn ich die Schlaflücke der Krankenschwester sehe, habe ich eine arme weibliche Figur, daher denke ich, dass es schwierig ist zu lesen und zu verstehen, aber ich werde Ihnen viele Male vergeben, wenn ich mich beeile. Bitte.

Beiseite

Recommended Posts

[Version 2020] Scraping und Verarbeitung des Textes von Aozora Bunko
Clustering von Büchern von Aozora Bunko mit Doc2Vec
Fügen Sie dem Bild Linien und Text hinzu
DJango Hinweis: Von Anfang an (Formularverarbeitung)
Holen Sie sich die Adresse von Längen- und Breitengrad
Holen Sie sich nur den Text aus dem Django-Formular.
Schaben Sie den Holojour ab und zeigen Sie ihn in der CLI an
Laden Sie Bilder aus einer Textdatei herunter, die die URL enthält
Macports easy_install löst die Version automatisch auf und führt sie aus
Übergeben Sie ein Array von PHP an PYTHON und führen Sie eine Numpy-Verarbeitung durch, um das Ergebnis zu erhalten