Тип ошибки с BeautifulSoup? Или многопоточность вызывает это? - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть список до 60 URL. Для каждого URL я создаю тему. Каждый поток запрашивает URL и выбирает ключевые слова в мета, если они предоставляются. Все потоки записывают ключевые слова в переменные данные.

Я пытался максимально упростить код, но я также хотел обеспечить многопоточность на случай, если это приведет к ошибке. В трассировке говорится следующее:

Exception in thread Thread-4:
Traceback (most recent call last):
  File "C:\Users\xxx\AppData\Local\Programs\Python\Python38-32\Lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Users\xxx\Desktop\Programming\saas\flask\routes.py", line 724, in run
    worker(url)
  File "C:\Users\xxx\Desktop\Programming\saas\flask\routes.py", line 737, in worker
            keywords1 = soup.find("meta", {"name":"keywords"})['content']
TypeError: 'NoneType' object is not subscriptable
<meta content="Metallzuschnitt, Kunststoffzuschnitt, Blechzuschnitt, Metallkonfigurator, ProKilo" name="keywords"/>
Metallzuschnitt, Kunststoffzuschnitt, Blechzuschnitt, Metallkonfigurator, ProKilo

Обратите внимание на то, как написано TypeError, но затем все равно печатает ключевые слова из выбранной мета. Но почему он не записывает данные? Это мой код:

from threading import Thread, Lock
from bs4 import BeautifulSoup
import requests

mutex = Lock()

threads = []
data = []
websitelist = ['http://www.wilmsmetall.de/', 'https://www.prokilo.de/maerkte/koeln-muelheim/', 'http://www.droesser.de/']

class ReqThread (Thread):
    def __init__(self, threadID, u_list):                                
        Thread.__init__(self) 
        self.threadID = threadID 
        self.urllist = u_list

    def run(self): 
        print ("Starting %s" % self.threadID)
        for url in self.urllist:
            worker(url)
        print ("Exiting %s" % self.threadID) 

def worker(url):
    global data
    html = requests.get(url, timeout=3)
    html_page = html.content
    soup = BeautifulSoup(html_page, 'html.parser')
    keywords1 = soup.find("meta", {"name":"keywords"})['content']
    print(keywords1)
    if keywords1 is not None:
        for keyword in keywords1.split(','):
            mutex.acquire() 
            data.append(keyword.strip())
            mutex.release()

for index, website in enumerate(websitelist):
    website = [website]
    t = ReqThread(index, website)
    t.start()
    threads.append(t)
for thread in threads:
    thread.join(5)

print(data)

1 Ответ

0 голосов
/ 09 апреля 2020

Нет, это не вызвано многопоточностью.

причина возникновения ошибки:

Из отладчика, только страница 'https://www.prokilo.de/maerkte/koeln-muelheim/ 'может работать нормально. Возможно, вам нужно изменить код в soup.find() при поиске на другой странице. enter image description here enter image description here enter image description here

Как напечатать правильный список данных?

Возможно, самый простой способ - добавить print(data) в функцию run(self). Кстати, в вашем коде:

for thread in threads:
    thread.join(5)

не дает никаких эффектов. Потому что поток запущен. Вам нужно использовать ( Если вам это действительно нужно):

t = ReqThread(index, website)
t.start()
t.join() # block the thread.
...