Как использовать многопоточность при веб-очистке с использованием запросов

#python #multithreading #web-scraping #python-requests #pool

#python #многопоточность #веб-очистка #python-запросы #Бассейн

Вопрос:

Ниже приведен код, который я использую для очистки своих данных и сохранения их в виде файла pickle. Для ссылок, по которым возвращается ошибка, код просто записывает URL-адрес и добавляет его в другой список, чтобы я мог очистить их снова.

 data= []
failed_url = []
error =[]
start = time.asctime( time.localtime(time.time()) )

# list_url is a list containing all urls
for path in list_url:
    try:
        headers = {'Content-Type': 'application/json'}
        filters = [dict(source_location="petitions_browse")]
        params = dict(q=json.dumps(dict(filters=filters)))
        result = requests.get(url=path,params=params)
        time.sleep(5)
        
        data_dict = result.json()

        data.append({
            'Data_dict': data_dict,
            'id': data_dict['id'],
            'title': data_dict['title'],
            'text':  data_dict['description'],
            'Topic': data_dict['topic'],
            'Topic_alt': data_dict['tags'][0]['name'],
            'Created_date': data_dict['created_at'].split("T")[0],
            'Created_time': data_dict['created_at'].split("T")[1],
            })
        time.sleep(5)
        
    except Exception as e:
        print(e)
        error.append(e)
        failed_url.append(path)
        continue
    
    if len(data)%50 == 0:
        pickle.dump(data, open("data_checkpoint" ".pkl", "wb"))
        
pickle.dump(data, open("data" ".pkl", "wb"))
pickle.dump(failed_url, open("failed_url" ".pkl", "wb"))
end = time.asctime( time.localtime(time.time()) )
print('start time:', start, 'end time:', end)
print('Failed Links:', failed_url)
  

Я адаптирую его для многопроцессорной обработки, используя следующий код:

 def get_data(url):
    try:
        headers = {'Content-Type': 'application/json'}
        filters = [dict(source_location="petitions_browse")]
        params = dict(q=json.dumps(dict(filters=filters)))
        result = requests.get(url=url,params=params)
        data_dict = result.json()
        return{
            'Data_dict': data_dict,
            'id': data_dict['id'],
            'title': data_dict['title'],
            'text':  data_dict['description'],
            'Topic': data_dict['topic'],
            'Topic_alt': data_dict['tags'][0]['name'],
            'Created_date': data_dict['created_at'].split("T")[0],
            'Created_time': data_dict['created_at'].split("T")[1],
            
            }
        #time.sleep(5)        
     except Exception as e:
        print(e)
        try:
            return {'Data_dict': data_dict}
        except Exception as c:
            return("failed_url", path)
        #continue

  
 with Pool(10) as pool:
    result = pool.map(get_data, url_list)
    print(result)

failed_url,data=[],[]
for res in result:
    if isinstance(res,tuple):
        failed_url.append(res[1])
    else:
        data.append(res)
        
pickle.dump(data, open("data" ".pkl", "wb"))
pickle.dump(failed_url, open("failed_url_test" ".pkl", "wb"))
  

Похоже, что эта адаптация не выполняется. Для небольшого количества ссылок он продолжает работать в течение длительного времени, и, таким образом, кажется, что с этим есть проблема, потому что для того же количества ссылок код без многопоточности выполняется быстрее.

Комментарии:

1. map Когда-нибудь возвращается? «похоже, что не выполняется» немного расплывчато.

2. Я буду рекомендовать использовать scrapy фреймворк, он прост в использовании, и вы можете настроить его на использование mt-запросов

3. Если вы действительно хотите добиться параллелизма при выполнении запросов, я рекомендую aiohttp . Он использует asyncio под капотом, и это, вероятно, будет быстрее, чем многопоточность и мультиобработка с requests . Документы: docs.aiohttp.org/en/stable

4. Также обратите внимание, что вы делаете широкий охват всех Exeption , что является плохим. В этом случае, если какая-либо из первых четырех строк в функции вызовет исключение, будет введен except блок, который data_dict вызовет NameError , потому что он еще не был установлен. Поскольку вы не упоминаете ошибку, похоже, что проблема здесь не в этом. Я бы все равно знал об этом.

5. @Carcigenicate Я отредактировал перехват исключения. Я думаю, это должно исправить то, о чем вы говорите!