LAPRAS Output Relay Day 1 article!
salut! Voici @Chanmoro, un ingénieur de robot d'exploration LAPRAS! Cette fois-ci, sous le titre LAPRAS Output Relay, les membres du LAPRAS publieront des articles quotidiennement jusqu'à fin mars! Les sessions d'étude et les conférences ont été annulées en raison du récent choc corona, mais j'espère que ce relais de sortie LAPRAS sera d'une certaine aide pour la motivation d'entrée et de sortie des ingénieurs.
Au fait, je travaille généralement en tant que développeur de robots, mais j'aimerais écrire cet article sur le flux de développement lors du développement d'un nouveau robot.
Ici, à titre d'exemple, les informations de l'article publié dans LAPRAS NOTE, qui est le média de l'entreprise exploité par LAPRAS, sont acquises et sorties dans un fichier au format JSON. Je voudrais présenter un exemple d'implémentation de robot.
Lors du montage d'un robot d'exploration, nous suivrons à peu près les étapes ci-dessous pour étudier, concevoir et mettre en œuvre.
Je vais vous expliquer chacun en détail.
Si vous jetez un coup d'œil à la page LAPRAS NOTE, vous verrez une liste d'articles sur la première page, qui vous mènera à la page de chaque article à partir du lien vers l'article de la liste.
Vous pouvez voir qu'il est à peu près composé de deux types de pages.
--Page de liste d'articles
Regardons de plus près la création de ces pages.
Sur la page de liste d'articles, vous pouvez voir que le titre de l'article, la catégorie, la date de publication, les informations de résumé du texte et les liens vers la page de détail de chaque article sont publiés comme ceci.
Vous pouvez également voir que le lien de pagination vers la page suivante est affiché en bas de la page.
Si vous allez à la deuxième page, qui est la dernière page pour le moment, vous pouvez voir que le lien vers la page suivante ne s'affiche pas ici.
Donc, s'il y a un lien vers la page suivante, passez à la page suivante, et s'il n'y a pas de lien, il semble que ce soit la dernière page.
Jetons ensuite un coup d'œil au contenu de la page de détail de l'article. Sur cette page, vous pouvez voir le titre de l'article, la date de publication, la catégorie et le corps de l'article.
Pour obtenir tous les articles, il semble que vous n'ayez pas à penser à passer de la page de détails de l'article à une autre page.
À partir de l'enquête sur site que j'ai mentionnée plus tôt, j'ai trouvé qu'il semble probable que ces données puissent être extraites.
--Article --Titre
En outre, il a été constaté que pour extraire les données ci-dessus pour tous les articles de LAPRAS NOTE, le site doit être suivi du flux suivant.
Ensuite, nous étudierons comment extraire les données cibles en examinant la structure HTML de la page à explorer. Ici, nous utiliserons les outils de développement du navigateur Web.
Je voudrais extraire ce qui suit de la page de liste d'articles.
Tout d'abord, recherchez l'élément qui correspond à un article afin de trouver le lien vers la page de détail de l'article.
En regardant la structure HTML de la page, j'ai trouvé que l'élément div
avec la classe de l'ensemble post-item
correspond à la portée d'un article.
De plus, si vous regardez les éléments dans le div.post-item
correspondant, vous pouvez voir que l'URL de la page de détail de l'article est définie dans la balise ʻa directement sous la balise
h2`.
Le chemin CSS pour spécifier cette balise que vous souhaitez obtenir est div.post-item h2> a
.
L'attente actuelle est que sur la première page de la liste d'articles, vous devriez pouvoir obtenir ** 10 éléments qui correspondent à ce chemin CSS **, mais j'aimerais voir si je peux obtenir des URL non pertinentes. Par exemple, vous pouvez exécuter le code JavaScript suivant à partir de la console de votre navigateur pour voir combien de sélecteurs CSS correspondent.
document.querySelectorAll("#main div.post-item h2 > a").length
En fait, si vous exécutez ce qui suit à partir de la console du navigateur alors que la première page de la page de liste d'articles est affichée, vous obtiendrez le résultat «10», vous pouvez donc confirmer que le chemin CSS ci-dessus semble correct.
Recherchez ensuite l'URL du lien vers la page suivante de la page de liste d'articles.
Si vous regardez les éléments de nav.navagation.pagination
, vous pouvez voir que c'est la zone où sont affichés les liens vers chaque page et les liens vers la page suivante.
Vous pouvez voir que la balise ʻaavec les classes
next et
page-numbers` à l'intérieur de cet élément est définie sur l'URL du lien vers la page suivante.
Le chemin CSS pour obtenir cela serait nav.navigation.pagination a.next.page-numbers
.
Vérifions le nombre de cas qui peuvent effectivement être obtenus depuis la console du navigateur.
document.querySelectorAll("nav.navigation.pagination a.next.page-numbers").length
Quand je l'ai exécuté, j'ai obtenu le résultat «1», il semble donc que vous pouvez obtenir l'URL du lien cible.
Vous pouvez également voir que l'élément du lien vers la page suivante n'est pas affiché sur la deuxième page, qui est la dernière page.
Juste au cas où, j'ai cherché l'élément du lien vers la page suivante à partir de la console et j'ai obtenu le résultat «0».
Je voudrais extraire ce qui suit de la page de détail de l'article.
--Titre
Comme précédemment, regardez la structure HTML pour trouver le chemin CSS vers l'élément souhaité.
Puisque la procédure est la même qu'avant, je vais l'omettre, mais j'ai trouvé que je devais extraire les données des éléments suivants.
--Titre
- h1
article header div.entry-meta
--Catégoriearticle header div.entry-meta a
article div.entry-content
La logique de l'exploration est presque claire d'après le contenu étudié jusqu'à présent, nous allons donc l'implémenter dans le code. Peu importe le langage que vous utilisez dans la plupart des cas, mais ici, j'aimerais écrire un exemple d'implémentation en Python.
Tout d'abord, je vais énumérer solidement ce qu'il faut faire.
# TODO: https://note.lapras.com/Accéder
# TODO:Obtenez l'URL des détails de l'article à partir du code HTML de la réponse
# TODO:Obtenir s'il y a un lien sur la page suivante
# TODO:Accéder à la page de détails de l'article
# TODO:Obtenir des informations sur l'article à partir du HTML de réponse
# TODO: URL
# TODO:Titre
# TODO:date de sortie
# TODO:Catégorie
# TODO:Texte de l'article
#Enregistrer les données récupérées dans un fichier au format JSON
Par mesure de précaution au moment de l'implémentation, ajustez l'intervalle d'accès en insérant le mode veille comme il convient afin de ne pas surcharger le service de destination de l'analyse. Dans la plupart des cas, à titre indicatif, il est préférable de le maintenir à environ 1 requête par seconde au maximum, mais ce sera un problème si le service correspondant est arrêté par l'exploration, donc à partir de la destination de l'exploration Vérifiez toujours si la réponse est une erreur.
Pour Python, j'écris souvent des robots en combinant des requêtes et Beautiful Soup. Veuillez également vous référer à Beautiful Soup in 10 minutes pour savoir comment utiliser la bibliothèque.
Il existe des frameworks qui implémentent des robots d'exploration tels que Scrapy, mais pour obtenir une image complète du robot, d'abord sans utiliser le framework. Il est recommandé de l'essayer.
Si vous exprimez le processus que vous souhaitez écrire en code solide sans réfléchir profondément à la conception, cela ressemblera à ceci.
import json
import time
import requests
from bs4 import BeautifulSoup
def parse_article_list_page(html):
"""
Analyser la page de la liste d'articles et extraire les données
:param html:
:return:
"""
soup = BeautifulSoup(html, 'html.parser')
next_page_link = soup.select_one("nav.navigation.pagination a.next.page-numbers")
return {
"article_url_list": [a["href"] for a in soup.select("#main div.post-item h2 > a")],
"next_page_link": next_page_link["href"] if next_page_link else None
}
def crawl_article_list_page(start_url):
"""
Explorez la page de la liste d'articles pour obtenir toutes les URL de détails de l'article
:return:
"""
print(f"Accessing to {start_url}...")
# https://note.lapras.com/Accéder
response = requests.get(start_url)
response.raise_for_status()
time.sleep(10)
#Obtenez l'URL des détails de l'article à partir du code HTML de la réponse
page_data = parse_article_list_page(response.text)
article_url_list = page_data["article_url_list"]
#Obtenir s'il y a un lien sur la page suivante
while page_data["next_page_link"]:
print(f'Accessing to {page_data["next_page_link"]}...')
response = requests.get(page_data["next_page_link"])
time.sleep(10)
page_data = parse_article_list_page(response.text)
article_url_list += page_data["article_url_list"]
return article_url_list
def parse_article_detail(html):
"""
Analyser la page de détail de l'article pour extraire des données
:param html:
:return:
"""
soup = BeautifulSoup(html, 'html.parser')
return {
"title": soup.select_one("h1").get_text(),
"publish_date": soup.select_one("article header div.entry-meta").find(text=True, recursive=False).replace("|", ""),
"category": soup.select_one("article header div.entry-meta a").get_text(),
"content": soup.select_one("article div.entry-content").get_text(strip=True)
}
def crawl_article_detail_page(url):
"""
Explorez la page de détails de l'article pour obtenir les données de l'article
:param url:
:return:
"""
#Accéder aux détails de l'article
print(f"Accessing to {url}...")
response = requests.get(url)
response.raise_for_status()
time.sleep(10)
#Obtenir des informations sur l'article à partir du HTML de réponse
return parse_article_detail(response.text)
def crawl_lapras_note_articles(start_url):
"""
Explorez LAPRAS NOTE pour obtenir toutes les données d'article
:return:
"""
article_url_list = crawl_article_list_page(start_url)
article_list = []
for article_url in article_url_list:
article_data = crawl_article_detail_page(article_url)
article_list.append(article_data)
return article_list
def collect_lapras_note_articles():
"""
Récupérez toutes les données de l'article LAPRAS NOTE et enregistrez-les dans un fichier
:return:
"""
print("Start crawl LAPRAS NOTE.")
article_list = crawl_lapras_note_articles("https://note.lapras.com/")
output_json_path = "./articles.json"
with open(output_json_path, mode="w") as f:
print(f"Start output to file. path: {output_json_path}")
json.dump(article_list, f)
print("Done output.")
print("Done crawl LAPRAS NOTE.")
if __name__ == '__main__':
collect_lapras_note_articles()
Le code implémenté est publié dans ce référentiel. https://github.com/Chanmoro/lapras-note-crawler
Il y a une atmosphère comme un cordon jetable, mais pour l'édition Basic, je voudrais terminer l'explication une fois.
D'ailleurs, cette fois, "Comment faire un robot - Édition de base", avec le thème de l'implémentation du robot de LAPRAS NOTE, une série de flux lors du développement d'un robot J'ai présenté les bases.
Lorsque je développe un robot d'exploration, je suis la procédure présentée ici. Le code donné dans l'exemple d'implémentation fait souvent encore défaut lorsqu'il est considéré comme un robot d'exploration qui continue à se maintenir pendant une longue période, mais lorsqu'il suffit d'acquérir un ensemble de données en une seule fois au lieu de mettre à jour en permanence les données. Je pense qu'un tel code est suffisant pour une utilisation simple. Personnellement, si vous avez un robot d'exploration pour la recherche qui est suffisant pour s'exécuter plusieurs fois, vous pouvez facilement l'implémenter avec juste un script shell sans utiliser Python.
Dans mon travail réel, je passe beaucoup plus de temps à développer la modélisation des données, la conception de flux de crawl, la gestion en cas d'erreurs, etc. pour garder les données intactes avec des crawls continus. Je prévois d'écrire quelques articles pendant la période de relais de sortie LAPRAS, mais dans mon prochain article, "Comment faire un robot d'exploration avancé", basé sur le contenu de cet article, maintenance à long terme À quoi devons-nous faire attention lors de la conception d'un robot d'exploration qui continue de fonctionner? Je voudrais présenter cela, alors attendez-le avec impatience!
Le relais de sortie LAPRAS de demain jour 2 sera écrit par @nasum! Attendez-vous aussi à cela!
Recommended Posts