#python #multithreading #web-scraping #python-requests #threadpool
Вопрос:
Я создаю скребок с использованием python и заставил его работать синхронно; затем я решил запустить его параллельно, чтобы ускорить его работу, но это, похоже, не работает, так как он завершается до завершения всех запросов. Код ниже, спасибо за любую помощь. Я использую параллельные фьючерсы для потоковой передачи. Я не уверен, что может быть причиной этой проблемы
import time
from bs4 import BeautifulSoup
import requests
import hashlib
import json
import threading
from concurrent.futures import ThreadPoolExecutor
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0'
}
start_time = time.time()
workers = 100
def getGardenia():
json_file = open('datasets2/Gardenia.json', 'w', encoding='utf-8')
json_file_details = open(
'datasets2/GardeniaDetails.json', 'w', encoding='utf-8')
pool = ThreadPoolExecutor(max_workers=workers)
def getMedDetails(link, name):
document = requests.get(link, headers=headers)
soup = BeautifulSoup(document.content, 'html.parser')
for element in soup.find_all('div', class_='woocommerce-Tabs-panel woocommerce-Tabs-panel--description panel entry-content wc-tab'):
obj = {hashlib.md5(name.encode()
).hexdigest(): element.get_text()}
json.dump(obj, json_file_details, ensure_ascii=False, indent=4)
print(str(obj)[:30])
def getMeds(page):
URL = f'https://gardeniapharmacy.com/product-category/find-a-medicine/page/{page}/'
document = requests.get(URL, headers=headers)
soup = BeautifulSoup(document.content, 'html.parser')
for element in soup.find_all('div', class_='astra-shop-summary-wrap'):
a = element.a
span = element.span.get_text()
link = a.get('href')
name = a.get_text()
obj = {
'name': name, 'link': link, 'category': span[1:]
}
json.dump(obj, json_file, ensure_ascii=False, indent=4)
print(obj)
pool.submit(getMedDetails, link, name)
for page in range(1, 221):
pool.submit(getMeds, page)
pool.shutdown(wait=True)
json_file.close()
json_file_details.close()
def getEDS():
json_file = open('datasets2/EDS.json', 'w', encoding='utf-8')
json_file_details = open(
'datasets2/EDSDetails.json', 'w', encoding='utf-8')
pool = ThreadPoolExecutor(max_workers=workers)
def generateCategoryURL():
urls = []
URL = f'http://egyptiandrugstore.com/index.php?route=product/categoryamp;path=59'
document = requests.get(URL)
soup = BeautifulSoup(document.content, 'html.parser')
for element in soup.find_all('li', class_='accordion'):
link = element.a.get('href')
urls.append(link 'amp;page=1')
return urls
def getNumPages(URL):
document = requests.get(URL)
soup = BeautifulSoup(document.content, 'html.parser')
div = soup.find('div', class_='results').text
start = div.find('(') 1
end = div[start:].find(' ')
return int(div[start:start end])
def getMedDetails(URL, name):
document = requests.get(URL, headers=headers)
soup = BeautifulSoup(document.content, 'html.parser')
for element in soup.find_all('div', id='tab-description'):
obj = {hashlib.md5(name.encode()).hexdigest(): element.get_text()}
json.dump(obj, json_file_details, ensure_ascii=False, indent=4)
print(str(obj)[:30])
def getMeds(URL, page):
document = requests.get(URL[:-1] str(page), headers=headers)
soup = BeautifulSoup(document.content, 'html.parser')
category = soup.find('h2', id='title-page').get_text()
for element in soup.find_all('div', class_='name'):
element = element.a
link = element.get('href')
name = element.get_text()
obj = {'link': link, 'name': name, 'category': category[:-12]}
pool.submit(getMedDetails, link, name)
json.dump(obj, json_file, ensure_ascii=False, indent=4)
print(obj)
catUrl = generateCategoryURL()
def startMeds(URL):
numOfPages = getNumPages(URL) 1
for page in range(1, numOfPages 1):
pool.submit(getMeds, URL, page)
for URL in catUrl:
pool.submit(startMeds, URL)
pool.shutdown(wait=True)
json_file.close()
json_file_details.close()
mainThreads = [
threading.Thread(target=getEDS),
threading.Thread(target=getGardenia)
]
for x in mainThreads:
x.start()
for x in mainThreads:
x.join()
print("time to complete: --- %s seconds ---" % (time.time() - start_time))
Ответ №1:
Однако приведенный выше код работает для меня!
Единственное незначительное исправление, которое я могу предложить (которое я также сделал в соответствии со своей локальной машиной).
datasets2
Папки не было, и, следовательно, либо создайте ее, либо позвольте программе выплевывать файлы только в одном и том же напрямую. В противном случае программа сломается только там.
Комментарии:
1. Вы позволили ему пройти через завершение? Если вы проверите один из файлов json, он должен быть в 37 тысяч строк. Скребок останавливается до завершения всех запросов