es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Añadiendo elementos a un array de piscina en Python dentro de una función.

Quiero codificar un webcrawler en el que necesito agregar enlaces de las páginas al arreglo dentro del pool, pero el pool solo funciona con las urls dadas y no funciona con los enlaces adicionados que le doy en la función def.

from concurrent import futures
from urllib.request import Request, urlopen
from bs4 import BeautifulSoup
from urllib.request import urlopen

def linksSearchAndAppend(url):
    req = Request(url)
    html_page = urlopen(req)

soup = BeautifulSoup(html_page, "lxml")

links = []
for link in soup.findAll('a'):
    links.append(link.get('href'))
    if link[0]=="/":
        link[0]=""
        link=url+link

global urls
urls.append(links)
print (urls)

urlListend=open("urlList.txt", "r")
urls=[]
for line in urlListend:
    urls.append(line.rstrip())
urlListend.close()

La multihilo principal funciona

e = futures.ThreadPoolExecutor(max_workers=8)
for url in urls:
e.submit(linksSearchAndAppend, url)
e.shutdown()

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Parece que estás intentando agregar enlaces de páginas rastreadas al array urls dentro de la función linksSearchAndAppend, pero el pool no está funcionando con los enlaces agregados. Una posible razón podría ser que el array urls no está siendo accesado apropiadamente por el pool de hilos.

    Para solucionar este problema, podrías intentar usar una estructura de datos Queue en lugar de un simple array. Las colas son estructuras de datos seguras para hilos que permiten a múltiples hilos accesar y modificarlas de manera segura. Puedes crear un objeto Queue, poner en él las urls iniciales, y hacer que los hilos trabajadores tomen enlaces de ella y agreguen nuevos enlaces a ella.

    Aquí hay un ejemplo de cómo podrías modificar tu código para usar una Queue:

    from concurrent import futures
    from urllib.request import Request, urlopen
    from bs4 import BeautifulSoup
    import queue
    
    # función para obtener enlaces de una página
    def fetch_links(url, q):
        req = Request(url)
        html = urlopen(req)
        soup = BeautifulSoup(html, "lxml")
        links = []
        for link in soup.find_all('a'):
            href = link.get('href')
            if href and href.startswith('http'):
                links.append(href)
        q.put(links)
    
    # leer las urls iniciales desde el archivo
    with open('urlList.txt') as f:
        urls = f.read().splitlines()
    
    # crear una cola para los enlaces
    q = queue.Queue()
    
    # agregar las urls iniciales a la cola
    for url in urls:
        q.put(url)
    
    # crear hilos trabajadores
    num_threads = 8
    with futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
        while not q.empty():
            # obtener una url de la cola
            url = q.get()
            # enviar una tarea para obtener enlaces de la url
            future = executor.submit(fetch_links, url, q)
            # esperar a que la tarea se complete
            future.result()
    
    # obtener todos los enlaces de la cola
    all_links = set()
    while not q.empty():
        links = q.get()
        all_links.update(links)
    
    # escribir todos los enlaces en un archivo
    with open('allLinks.txt', 'w') as f:
        for link in all_links:
            f.write(link + '\n')
    

    En este código modificado, la función fetch_links recibe una url y un objeto Queue como parámetros. Obtiene los enlaces de la página y los pone en la cola. El programa principal crea una cola, agrega las urls iniciales a ella, y crea hilos trabajadores. Cada hilo trabajor obtiene una url de la cola, envía una tarea para obtener enlaces, y espera a que se complete. Después de procesar todas las urls, el programa principal obtiene todos los enlaces de la cola y los escribe en un archivo.

    Nota que la función fetch_links filtra enlaces que no empiezan con “http”. Podrías modificar esta condición dependiendo de tus necesidades. Además, la variable all_links es un conjunto para eliminar duplicados.

Comments are closed.