GNU/Linux >> Tutoriales Linux >  >> Ubuntu

¿Cómo crear una araña web CLI que use palabras clave y filtre contenido?

Quiero encontrar mis artículos en el foro de literatura en desuso (obsoleto) e-bane.net. Algunos de los módulos del foro están deshabilitados y no puedo obtener una lista de artículos de su autor. Además, el sitio no está indexado por los motores de búsqueda como Google, Yndex, etc.

La única forma de encontrar todos mis artículos es abrir la página de archivo del sitio (fig.1). Luego debo seleccionar cierto año y mes, p. Enero 2013 (fig.1). Y luego debo inspeccionar cada artículo (fig.2) si al principio está escrito mi apodo:pa4080 (Fig. 3). Pero hay unos pocos miles de artículos.

He leído algunos temas como los siguientes, pero ninguna de las soluciones se ajusta a mis necesidades:

  • Araña web para Ubuntu
  • Cómo escribir una araña web en un sistema Linux
  • Obtener una lista de URL de un sitio

Voy a publicar mi propia solución. Pero para mí es interesante:
¿Hay alguna forma más elegante de resolver esta tarea?

Respuesta aceptada:

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

Aquí está la versión python3 del script (probado en python3.5 en Ubuntu 17.10 ).

Cómo usar:

  • Para usarlo, coloque ambos códigos en los archivos. Como ejemplo, el archivo de código es script.py y el archivo del paquete es requirement.txt .
  • Ejecute pip install -r requirement.txt .
  • Ejecute el script como ejemplo python3 script.py pa4080

Utiliza varias bibliotecas:

  • haga clic para el analizador de argumentos
  • beautifulsoup para el analizador html
  • aiohttp para descargar html
Relacionado:¿Cómo cambiar de forma segura el nombre del sistema operativo en el menú de inicio de grub?

Cosas que debe saber para desarrollar más el programa (aparte de la documentación del paquete requerido):

  • biblioteca de python:asyncio, json y urllib.parse
  • selectores css (mdn web docs), también algo de html. vea también cómo usar el selector css en su navegador como este artículo

Cómo funciona:

  • Primero, creo un descargador html simple. Es una versión modificada de la muestra dada en aiohttp doc.
  • Después de eso, cree un analizador de línea de comando simple que acepte el nombre de usuario y el nombre del archivo de salida.
  • Cree un analizador para enlaces de hilos y artículo principal. El uso de pdb y la manipulación simple de URL deberían hacer el trabajo.
  • Combine la función y coloque el artículo principal en json, para que otro programa pueda procesarlo más tarde.

Alguna idea para poder desarrollarla más

  • Cree otro subcomando que acepte el enlace del módulo de fecha:se puede hacer separando el método para analizar el módulo de fecha en su propia función y combinarlo con el nuevo subcomando.
  • Almacenamiento en caché del enlace del módulo de fecha:cree un archivo json de caché después de obtener el enlace de los subprocesos. para que el programa no tenga que volver a analizar el enlace. o simplemente almacenar en caché todo el artículo principal del hilo, incluso si no coincide

Esta no es la respuesta más elegante, pero creo que es mejor que usar bash answer.

  • Utiliza Python, lo que significa que se puede usar entre plataformas.
  • Instalación simple, todo el paquete requerido se puede instalar usando pip
  • Se puede desarrollar aún más, más legible el programa, más fácil se puede desarrollar.
  • Hace el mismo trabajo que el script bash solo durante 13 minutos .

Ubuntu
  1. Ansible Playbook:Cómo crear y configurar Playbooks

  2. Cómo instalar SQL Server y SQL Server CLI Tools en Ubuntu

  3. Cómo instalar VeraCrypt y crear un disco cifrado en Ubuntu 20.04

  4. Debian:¿cómo rizar el contenido completo de la página web?

  5. ¿Cómo crear un archivo y montarlo como un sistema de archivos?

Cómo crear y ejecutar un archivo de libro de jugadas de Ansible

Cómo instalar y configurar el servidor web Apache en Ubuntu

Cómo crear y editar archivos PDF en Ubuntu

Cómo crear un nuevo usuario y otorgar permisos en MySQL

¿Cómo crear un Usb de arranque múltiple que permita la partición de datos persistente, no persistente y?

¿Cómo crear un USB en vivo de arranque que use Ext4 en oposición a Iso-9660, Squashfs y Casper?