Le texte du travail publié dans Aozora Bunko a été gratté avec Python et transformé en une agréable sensation. À l'époque, j'y étais accro ici et là, donc ce mémorandum.
Tout d'abord, récupérez le texte de l'œuvre auprès d'Aozora Bunko.
Ce qu'il faut faire est essentiellement comme décrit dans cet article (https://qiita.com/icy_mountain/items/011c9f56151b9832b54d), [API Aozora Bunko (https://qiita.com/ksato9700/items/626cc82c007ba8337034) Appuyez sur pour récupérer le HTML du corps. À ce moment, la partie de l'ID de travail de l'URL sera définie sur book_id
et une variable.
Cependant, je ne pouvais pas faire cela dans mon propre environnement. Tout d'abord, je travaillais sur Jupyter Notebook plutôt que sur le terminal, donc je ne peux pas utiliser la commande ! Wget
.
Donc, si vous recherchez la commande qui envoie une requête GET à l'API en Python, vous verrez ʻurllib2.urlopen () ʻandreqests.req ()
, mais parmi ceux-ci, ʻurllib2 est une bibliothèque pour Python2. ne peut pas utiliser. Il semble qu'il ait été renommé en ʻurllib3
ou ʻurlliben Python3, mais je n'étais pas sûr, j'ai donc décidé d'utiliser la bibliothèque
requests`. Ainsi, la récupération de l'API par la méthode GET ressemble à ceci:
import requests
res = requests.get('http://pubserver2.herokuapp.com/api/v0.1/books/{book_id}/content?format=html'.format(book_id))
Ensuite, convertissez les données HTML récupérées dans un format qui peut être utilisé par BeautifulSoup4.
from bs4 import BeautifulSoup
soup = BeautifulSoup(res.text, 'html.parser')
Pour obtenir le corps de la balise title
à partir d'ici, écrivez:
soup.find('title').get_text()
# ->Hisaku Yumeno Narcisse Bleu, Narcisse Rouge
Les titres sont joliment séparés par des espaces demi-largeur, donc si vous faites split ()
ici, vous pouvez les diviser en nom et titre de l'auteur.
Dans certains cas, comme pour les auteurs étrangers, les choses peuvent ne pas bien se passer, de sorte que la présence ou l'absence des informations restantes est également définie dans la variable.
title_list = title.split(' ')
book_author = title_list[0] #Nom de l'auteur
book_title = title_list[1] #Titre
book_title_info = len(title_list) > 2 #Le titre est-il cassé?
D'un autre côté, le corps (dans le vrai sens du mot) est la balise div
de la classe main_text
, donc cela ressemblerait à ceci:
soup.find('div', {'class': 'main_text'}).get_text()
# -> \n\n\n\r\n\U3000 Utako a été enseigné par un ami, a coupé les racines des jonquilles, mis de la peinture rouge et de la peinture bleue, et les a enterrées dans le coin du jardin.[...]
Cette fois, je veux séparer les phrases par ponctuation, donc je vais créer un format de liste pour chaque phrase comme suit. Si vous voulez la première phrase, vous pouvez l'obtenir comme 0e élément.
text_list = soup.find('div', {'class': 'main_text'}).get_text().split('。')
text_first = text_list[0] + "。" #La première phrase
Si cela reste tel quel, le texte sera sale, nous allons donc supprimer les éléments inutiles et affiner le texte.
Tout d'abord, le code correspondant au code de saut de ligne \ n
et l'espace demi-largeur \ u3000
sont mélangés, alors déposez-le avecstrip ()
aprèsget_text ()
.
text_list = soup.find('div', {'class': 'main_text'}).get_text().strip('\r''\n''\u3000').split('。')
Afin de supprimer la partie du rubis entre parenthèses dans le texte, ajoutez le code suivant immédiatement après la conversion pour supprimer le rubis.
for tag in soup.find_all(["rt", "rp"]):
tag.decompose() #Supprimer les balises et leur contenu
Parfois, il n'est pas séparé par la ponctuation et la première phrase peut se poursuivre indéfiniment, donc si elle est trop longue, je la remplacerai par une autre chaîne de caractères. La longueur standard 100 est appropriée.
text_first = text_list[0] + "。" if (len(text_list[0]) < 100) else "too long" #début
Enfin, lors de la conversion du processus ci-dessus en une fonction, si l'ID de travail correspondant n'existe pas et que la récupération échoue, une erreur NoneType se produira au moment de l'extraction, excluez donc cela par la présence ou l'absence de balises et de classes. (Je pense qu'il y a une meilleure façon de l'écrire).
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() #Supprimer les balises et leur contenu
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] #Nom de l'auteur
book_title = title_list[1] #Titre
book_title_info = len(title_list) > 2 #Le titre est-il cassé?
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" #début
else:
text_last = ""
list = [book_id, book_author, book_title, book_title_info, text_first]
print(list)
return list
bookInfo(930)
# -> [930,
# 'Hisaku Yumeno',
# 'Le miracle d'Oshie',
# False,
# 'Quand je vois le trou de sommeil de l'infirmière, je dirige un pauvre personnage féminin, donc je pense que c'est difficile à lire et à comprendre, mais je vous pardonnerai plusieurs fois car je me dépêche. S'il vous plaît.']
Je voudrais ajouter les listes obtenues en utilisant la fonction ci-dessus afin de créer une liste bidimensionnelle et de la sortir sous forme de fichier CSV.
Importez d'abord csv
et ouvrez le fichier.
À propos, si le fichier existe déjà et que vous souhaitez l'ajouter après le texte intégral au lieu de l'écraser, remplacez w '' par
a ''.
import csv
f = open('output.csv', 'w')
writer = csv.writer(f, lineterminator='\n')
Créez une liste vide et tournez la boucle for pour ajouter la valeur de retour de l'exécution de la fonction à la liste. À propos, avec l'API Aozora Bunko, il a fallu quelques secondes pour obtenir un travail. Je pense que si vous demandez trop de requêtes, cela deviendra inutilisable, donc je pense qu'il vaut mieux l'exécuter par petites unités telles que 10 ou 100.
csvlist = []
for i in range(930, 940):
csvlist.append(bookInfo(i))
Fermez enfin le fichier et vous avez terminé.
writer.writerows(csvlist)
f.close()
Un fichier CSV a été généré. Il est pratique de le charger dans une feuille de calcul Google.
930,Hisaku Yumeno,Le miracle d'Oshie,False,Quand je vois le trou de sommeil de l'infirmière, je dirige un pauvre personnage féminin, donc je pense que c'est difficile à lire et à comprendre, mais je vous pardonnerai plusieurs fois car je me dépêche. S'il vous plaît.
Recommended Posts