[PYTHON] Comment créer un robot - Basic

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.

Contenu de cet article

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.

Procédure de développement du robot d'exploration

Lors du montage d'un robot d'exploration, nous suivrons à peu près les étapes ci-dessous pour étudier, concevoir et mettre en œuvre.

  1. Examinez la structure des liens du site et les pistes sur chaque page
  2. Examinez la structure HTML de la page que vous explorez
  3. Montez le robot

Je vais vous expliquer chacun en détail.

1. Examinez la structure des liens du site et les pistes sur chaque page

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.

Consultez la page de la liste d'articles

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. image.png

Vous pouvez également voir que le lien de pagination vers la page suivante est affiché en bas de la page. image.png

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. image.png

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.

Examiner la page de détail de l'article

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.

image.png

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.

Résumer la structure des données à extraire

À 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.

  1. Accédez à la page de la liste d'articles publiés pour obtenir l'URL des détails de l'article.
  2. S'il y a un lien vers la page suivante, allez à la page suivante et obtenez l'URL des détails de l'article comme dans (1)
  3. Accédez à la page des détails de l'article pour obtenir des informations sur l'article.

2. Examinez la structure HTML de la page que vous explorez

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.

Liste des articles publiés

Je voudrais extraire ce qui suit de la page de liste d'articles.

Obtenez l'URL du lien de la page de détail de l'article

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`.

image.png

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. image.png

Obtenez l'URL du lien vers la page suivante

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 classesnext et page-numbers` à l'intérieur de cet élément est définie sur l'URL du lien vers la page suivante.

image.png

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.

image.png

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.

image.png

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». image.png

Page de détail de l'article

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é.

image.png

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

3. Montez le robot

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.

Organisez quoi faire

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

Précautions lors du montage de la chenille

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.

Implémentation solide en Python

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.

Résumé

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

Comment créer un robot - Basic
Comment créer un robot - Avancé
Comment faire une traduction japonais-anglais
Comment créer un bot slack
Comment créer un Dockerfile (basique)
[Blender] Comment créer un plug-in Blender
[Python] Comment rendre une classe itérable
Comment créer un indicateur personnalisé Backtrader
Comment créer un plan de site Pelican
Comment créer un système de dialogue dédié aux débutants
Comment créer un dictionnaire avec une structure hiérarchique.
Comment créer un plug-in QGIS (génération de package)
J'ai lu "Comment créer un laboratoire de piratage"
Comment appeler une fonction
Comment pirater un terminal
Comment faire un jeu de tir avec toio (partie 1)
Comment créer un package Python à l'aide de VS Code
Bases de PyTorch (2) -Comment créer un réseau de neurones-
Comment créer un BOT Cisco Webex Teams à l'aide de Flask
[Python] Comment créer une liste de chaînes de caractères caractère par caractère
Comment mettre un lien symbolique
Comment créer un jeu d'action multijoueur en ligne avec Slack
Comment créer un package Conda
Comment créer un pont virtuel
Comment créer un laboratoire de piratage - Kali Linux (2020.1) VirtualBox 64-bit edition -
Comment créer un package Python (écrit pour un stagiaire)
[Blender] Comment rendre les scripts Blender multilingues
Comment créer un fichier de configuration
Comment transformer une chaîne en tableau ou un tableau en chaîne en Python
Comment faire une commande pour lire le fichier de paramètres avec pyramide
Comment créer une caméra de surveillance (caméra de sécurité) avec Opencv et Python
[Langage C] Comment créer, éviter et créer un processus zombie
Spigot (Paper) Introduction à la création d'un plug-in pour 2020 # 01 (Construction de l'environnement)
Comment créer une bibliothèque .dylib à partir d'une bibliothèque .a avec OSX (El Capitan)
Comment faire un test unitaire Part.1 Modèle de conception pour l'introduction
[Python] Comment créer une matrice de motifs répétitifs (repmat / tile)
Comment rendre le sélénium aussi léger que possible
Comment créer un clone depuis Github
Comment diviser et enregistrer un DataFrame
Comment créer un dossier git clone
Qiita (1) Comment écrire un nom de code
Comment ajouter un package avec PyCharm
[Python] Comment convertir une liste bidimensionnelle en liste unidimensionnelle
Faisons un noyau jupyter
[Colab] Comment copier un vaste ensemble de données
[Python] Comment inverser une chaîne de caractères
Comment installer un package à l'aide d'un référentiel
[Ubuntu] Comment exécuter un script shell
Comment obtenir stacktrace en python
[Cocos2d-x] Comment créer une liaison de script (partie 2)
Comment créer une clé USB à démarrage multiple (compatible Windows 10)
Comment créer un référentiel à partir d'un média
Pour rendre une propriété de type dict en lecture seule
Comment choisir une palette de couleurs Seaborn
Comment tester sur une page authentifiée par Django
[Cocos2d-x] Comment créer une liaison de script (partie 1)
Comment utiliser le bloc-notes Jupyter [super basique]
Comment installer le tissu et comment l'utiliser
Comment exécuter des scripts Maya Python