GNU/Linux >> Tutoriels Linux >  >> Ubuntu

Comment créer une araignée Web Cli qui utilise des mots clés et filtre le contenu ?

Je veux trouver mes articles dans le forum de littérature obsolète (obsolète) e-bane.net. Certains modules du forum sont désactivés et je n'arrive pas à obtenir la liste des articles de leur auteur. De plus, le site n'est pas indexé par les moteurs de recherche comme Google, Yndex, etc.

Le seul moyen de retrouver tous mes articles est d'ouvrir la page d'archives du site (fig.1). Ensuite, je dois sélectionner une certaine année et un certain mois - par ex. janvier 2013 (fig.1). Et puis je dois inspecter chaque article (fig.2) si au début est écrit mon pseudo – pa4080 (fig.3). Mais il y a quelques milliers d'articles.

J'ai lu quelques sujets comme suit, mais aucune des solutions ne correspond à mes besoins :

  • Araignée Web pour Ubuntu
  • Comment écrire une araignée Web sur un système Linux
  • Obtenir une liste des URL d'un site

Je posterai ma propre solution. Mais pour moi, c'est intéressant :
Existe-t-il une manière plus élégante de résoudre cette tâche ?

Réponse acceptée :

script.py :

#!/usr/bin/python3
from urllib.parse import urljoin
import json

import bs4
import click
import aiohttp
import asyncio
import async_timeout


BASE_URL = 'http://e-bane.net'


async def fetch(session, url):
    try:
        with async_timeout.timeout(20):
            async with session.get(url) as response:
                return await response.text()
    except asyncio.TimeoutError as e:
        print('[{}]{}'.format('timeout error', url))
        with async_timeout.timeout(20):
            async with session.get(url) as response:
                return await response.text()


async def get_result(user):
    target_url = 'http://e-bane.net/modules.php?name=Stories_Archive'
    res = []
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, target_url)
        html_soup = bs4.BeautifulSoup(html, 'html.parser')
        date_module_links = parse_date_module_links(html_soup)
        for dm_link in date_module_links:
            html = await fetch(session, dm_link)
            html_soup = bs4.BeautifulSoup(html, 'html.parser')
            thread_links = parse_thread_links(html_soup)
            print('[{}]{}'.format(len(thread_links), dm_link))
            for t_link in thread_links:
                thread_html = await fetch(session, t_link)
                t_html_soup = bs4.BeautifulSoup(thread_html, 'html.parser')
                if is_article_match(t_html_soup, user):
                    print('[v]{}'.format(t_link))
                    # to get main article, uncomment below code
                    # res.append(get_main_article(t_html_soup))
                    # code below is used to get thread link
                    res.append(t_link)
                else:
                    print('[x]{}'.format(t_link))

        return res


def parse_date_module_links(page):
    a_tags = page.select('ul li a')
    hrefs = a_tags = [x.get('href') for x in a_tags]
    return [urljoin(BASE_URL, x) for x in hrefs]


def parse_thread_links(page):
    a_tags = page.select('table table  tr  td > a')
    hrefs = a_tags = [x.get('href') for x in a_tags]
    # filter href with 'file=article'
    valid_hrefs = [x for x in hrefs if 'file=article' in x]
    return [urljoin(BASE_URL, x) for x in valid_hrefs]


def is_article_match(page, user):
    main_article = get_main_article(page)
    return main_article.text.startswith(user)


def get_main_article(page):
    td_tags = page.select('table table td.row1')
    td_tag = td_tags[4]
    return td_tag


@click.command()
@click.argument('user')
@click.option('--output-filename', default='out.json', help='Output filename.')
def main(user, output_filename):
    loop = asyncio.get_event_loop()
    res = loop.run_until_complete(get_result(user))
    # if you want to return main article, convert html soup into text
    # text_res = [x.text for x in res]
    # else just put res on text_res
    text_res = res
    with open(output_filename, 'w') as f:
        json.dump(text_res, f)


if __name__ == '__main__':
    main()

requirement.txt :

aiohttp>=2.3.7
beautifulsoup4>=4.6.0
click>=6.7

Voici la version python3 du script (testé sur python3.5 sur Ubuntu 17.10 ).

Comment utiliser :

  • Pour l'utiliser, placez les deux codes dans des fichiers. Par exemple, le fichier de code est script.py et le fichier de package est requirement.txt .
  • Exécutez pip install -r requirement.txt .
  • Exécuter le script comme exemple python3 script.py pa4080

Il utilise plusieurs librairies :

  • cliquez pour l'analyseur d'arguments
  • beautifulsoup pour l'analyseur html
  • aiohttp pour le téléchargeur html
Connexe :Comment changer en toute sécurité le nom du système d'exploitation dans le menu de démarrage grub ?

Choses à savoir pour développer davantage le programme (autres que la doc du package requis) :

  • Bibliothèque Python :asyncio, json et urllib.parse
  • sélecteur css (docs web mdn), ainsi que du html. voir aussi comment utiliser le sélecteur css sur votre navigateur comme cet article

Comment ça marche :

  • D'abord, je crée un téléchargeur html simple. Il s'agit d'une version modifiée de l'exemple fourni sur la documentation aiohttp.
  • Après cela, créez un analyseur de ligne de commande simple qui accepte le nom d'utilisateur et le nom du fichier de sortie.
  • Créer un analyseur pour les liens de fils de discussion et l'article principal. L'utilisation de pdb et d'une simple manipulation d'URL devrait faire l'affaire.
  • Combinez la fonction et placez l'article principal sur json, afin qu'un autre programme puisse le traiter plus tard.

Une idée pour qu'elle puisse être développée davantage

  • Créez une autre sous-commande qui accepte le lien du module de date :cela peut être fait en séparant la méthode pour analyser le module de date en sa propre fonction et en la combinant avec une nouvelle sous-commande.
  • Mise en cache du lien du module de date :créez le fichier json de cache après avoir obtenu le lien des threads. afin que le programme n'ait pas à analyser à nouveau le lien. ou même simplement mettre en cache l'intégralité de l'article principal du fil même s'il ne correspond pas

Ce n'est pas la réponse la plus élégante, mais je pense que c'est mieux que d'utiliser la réponse bash.

  • Il utilise Python, ce qui signifie qu'il peut être utilisé sur plusieurs plates-formes.
  • Installation simple, tous les packages requis peuvent être installés à l'aide de pip
  • Il peut être développé davantage, plus le programme est lisible, plus il peut être développé plus facilement.
  • Il fait le même travail que le script bash uniquement pendant 13 minutes .

Ubuntu
  1. Ansible Playbook :comment créer et configurer des playbooks

  2. Comment installer SQL Server et les outils CLI SQL Server sur Ubuntu

  3. Comment installer VeraCrypt et créer un disque crypté dans Ubuntu 20.04

  4. Debian - Comment boucler le contenu d'une page Web complète ?

  5. Comment créer un fichier et le monter en tant que système de fichiers ?

Comment créer et exécuter un fichier Playbook Ansible

Comment installer et configurer le serveur Web Apache sur Ubuntu

Comment créer et éditer des fichiers PDF dans Ubuntu

Comment créer un nouvel utilisateur et accorder des autorisations dans MySQL

Comment créer une clé USB multiboot qui permet la persistance, la non-persistance et la partition de données ?

Comment créer une clé USB bootable en direct qui utilise Ext4 par opposition à Iso-9660, Squashfs et Casper ?