Для одного из пауков в моем проекте я загружаю аудиопоток, в основном получая доступ к базовым файлам AA C, вызываемым потоком. Я делаю это, сначала извлекая URL-адрес для каждого сегмента в запись элемента, а затем использую пользовательский конвейер, который в основном использует request.get для каждой части и суммирует их все вместе, чтобы получить мой аудиофайл. Я также использовал многопоточность этих загрузок, поскольку они, как правило, составляют ~ 200-300 частей на аудиофайл, поэтому последовательная загрузка мучительно медленная.
Тем не менее, она все еще очень медленная. Более того, поскольку библиотека запросов не работает асинхронно вместе со Spider, каждый раз, когда я загружаю эти файлы, весь паук перестает что-либо делать и ждет. Мне было интересно, если бы кто-нибудь знал о лучшем способе, как я мог бы справиться с загрузкой аудио, как это? Помощь очень ценится, и, пожалуйста, обратитесь к приведенному ниже коду, спасибо!
PS. Я не передаю URL-адреса напрямую в Scrapy, потому что не хочу, чтобы каждый чанк загружался с другим прокси-сервером, и это кажется очень медленным, когда я его пробовал.
def loop_function_on_threads(function, arguments_iterable, **kwargs):
"""Uses ThreadPoolExecutor to start up multiple threads and spreads the given
iterable across them, running them through the given function on each thread.
Used for vastly increasing performance of intensive loops."""
with ThreadPoolExecutor() as threads:
conversion_iterable = threads.map(function, arguments_iterable)
results = list(tqdm(conversion_iterable, total=len(arguments_iterable)))
return results
class AudioDownloadPipeline(object):
"""Downloads a stream of audio files and sums the bytes to return a single audio file."""
def process_item(self, item, spider):
files_urls_field = spider.settings.get("FILES_URLS_FIELD")
audio_responses = loop_function_on_threads(
requests.get, item.get(files_urls_field, [])
)
export_path = os.path.join(
spider.settings.get("FILES_STORE"),
f"{item.get('filename')}.aac"
)
if os.path.exists(export_path):
raise DropItem()
audio = None
for response in audio_responses:
if audio_responses.index(response) == 0:
audio = response.content
else:
audio += response.content
with open(export_path, "wb") as file:
file.write(audio)
item[files_urls_field] = export_path.rsplit("/", 1).pop(-1)
item[spider.settings.get("FILES_RESULT_FIELD")] = audio
return item