У меня огромный список URL-адресов (около 40 миллионов).
Я написал сценарий, который очищает этот URL-адрес с помощью многопоточности. Но мне нужно дополнительное решение, которое должно быть экономичным в ресурсах ОС, поэтому я решил также разработать версию ASYN C.
Я изучал asyncio и aiohttp в Python на неделю.
Ниже рабочий код:
from pathlib import Path
import time
import asyncio
import aiohttp
import pypeln as pl
import async_timeout
# for calculating the total elapsed time
start = time.time()
successful_counter = 0
# files and folders
urlFile = open('url500.txt', 'r')
# list for holding processed url's so far
urlList = []
#######################
# crawler function start
#######################
async def crawling(line, session1): # function wrapper for parallelizing the process
# getting URL's from the file
global successful_counter
line = line.strip()
# try to establish a connection
try:
async with async_timeout.timeout(25):
async with session1.get('http://' + line) as r1:
x = r1.headers
if ('audio' in x['Content-Type'] or 'video' in x['Content-Type']):
print("Url: " + line + " is a streaming website \n")
return # stream website, skip this website
# means we have established a connection and got the expected result
if r1.status // 100 == 2:
#print("Returned 2** for the URL:", line)
try:
text1 = await r1.text()
successful_counter += 1
'''
f1 = open('200/' + line + '.html', 'w')
f1.write(text1)
f1.close()
'''
except Exception as exc:
print(line + ": " + str(exc))
return
urlList.append(line)
return
else:
return
# some error occured
except Exception as exc:
print("Url: " + line + " created the error: \n" + str(exc))
return
#######################
# crawler function end
#######################
async def main(tempList):
'''
limit = 1000
await pl.task.each(
crawling, tempList, workers=limit,
)
'''
conn = aiohttp.TCPConnector(limit=0)
custom_header1 = {'User-agent': 'Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/74.0'}
#'''
async with aiohttp.ClientSession(headers=custom_header1, connector=conn) as session1:
await asyncio.gather(*[asyncio.ensure_future(crawling(url, session1)) for url in tempList])
#'''
return
asyncio.run(main(urlFile))
print("total successful: ", successful_counter)
# for calculating the total elapsed time
end = time.time()
print("Total elapsed time in seconds:", end-start)
Вот проблема: когда я не выставляю таймауты, он работает без проблем, но требует слишком много времени. Я хочу потратить не более 25 секунд на запрос. Если веб-сайт не дает мне ответа, я должен пропустить этот веб-сайт и двигаться дальше.
До сих пор все методы, которые я пробовал, не дали мне результата. Когда я где-то устанавливаю тайм-аут 25 секунд, он всегда ограничивает всю программу, а не один запрос. Итак, независимо от того, есть ли у меня файл с 500 URL-адресами или 1000000 URL-адресов, он всегда заканчивается через 25 секунд.
Я пробовал обернуть функцию искателя с помощью async_timeout, используя встроенный тайм-аут aiohttp library
async with session1.get('http://' + line, timeout=25)
Пытался создать сеанс внутри функции искателя и установить тайм-аут для сеанса (опять же с использованием встроенных методов aiohttp).
Ничего не получилось ... Возможно, мне не хватает чего-то огромного, но я застрял на несколько дней, и у меня закончились варианты, чтобы попробовать: D