#python #python-3.x #web-scraping #concurrent.futures
#python #python-3.x #очистка веб-страниц #concurrent.futures
Вопрос:
Я создал скрипт с использованием библиотеки concurrent.futures для многопоточности, чтобы ускорить выполнение скрипта. Если первая функция get_content_url()
в скрипте создала несколько ссылок, текущая реализация будет работать. Однако, поскольку первая функция создает единственную ссылку, я не понимаю, как использовать concurrent.futures в таких случаях.
Чтобы вы поняли, что делает первая функция — когда я передаю идентификаторы из файла csv в эту функцию get_content_url()
, она генерирует единственную ссылку, используя токен, собранный из ответа json.
Как я могу
concurrent.futures
правильно применить в скрипте, чтобы ускорить выполнение?
Я пробовал с:
import requests
import concurrent.futures
from bs4 import BeautifulSoup
base_link = "https://www.some_website.com/{}"
target_link = "https://www.some_website.com/{}"
def get_content_url(item_id):
r = requests.get(base_link.format(item_id['id']))
token = r.json()['token']
content_url = target_link.format(token)
yield content_url
def get_content(target_link):
r = requests.get(target_link)
soup = BeautifulSoup(r.text,"html.parser")
try:
title = soup.select_one("h1#maintitle").get_text(strip=True)
except Exception: title = ""
print(title)
if __name__ == '__main__':
with open("IDS.csv","r") as f:
reader = csv.DictReader(f)
with concurrent.futures.ThreadPoolExecutor(max_workers=6) as executor:
for _id in reader:
future_to_url = {executor.submit(get_content,item): item for item in get_content_url(_id)}
concurrent.futures.as_completed(future_to_url)
Ответ №1:
Это может быть немного сложно воспроизвести, поскольку я не знаю, что внутри IDS.csv
, и в вашем вопросе отсутствует допустимый URL-адрес, но вот с чем можно поиграть:
import csv
import random
import requests
import concurrent.futures
from bs4 import BeautifulSoup
base_link = "https://www.some_website.com/{}"
target_link = "https://www.some_website.com/{}"
def get_content_url(item_id):
url = base_link.format(item_id)
print(f"Requesting {url}...")
token = requests.get(url).json()['token']
return target_link.format(token)
def get_content(item_id):
url = get_content_url(item_id)
print(f"Fetching {url}...")
r = requests.get(url)
soup = BeautifulSoup(r.text, "html.parser")
try:
title = soup.select_one("h1#maintitle").get_text(strip=True)
return title
except Exception as exc:
return exc
def write_fake_ids():
fake_ids = [
{"item": "sample_item", "item_id": _} for _ in
random.sample(range(1000, 10001), 1000)
]
with open("IDS.csv", "w") as output:
w = csv.DictWriter(output, fieldnames=fake_ids[0].keys())
w.writeheader()
w.writerows(fake_ids)
def get_ids():
with open("IDS.csv") as csv_file:
ids = csv.DictReader(csv_file)
yield from (id_ for id_ in ids)
if __name__ == '__main__':
with concurrent.futures.ThreadPoolExecutor(max_workers=6) as executor:
future_to_url = {
executor.submit(get_content, id_['item_id']): id_ for id_ in get_ids()
}
for future in concurrent.futures.as_completed(future_to_url):
print(future.result())
Я издеваюсь над файлом .csv write_fake_ids()
. Вы можете игнорировать ее или удалить, она нигде не вызывается в коде.
Комментарии:
1. Хотя я еще не тестировал ваш скрипт, я полагаю, что он более или менее делает что-то подобное . Я не опубликовал это только потому, что думал, что есть лучший способ. Спасибо.