我写使用ASYNCIO / aiohttp网络爬虫。我希望抓取工具只需要下载HTML内容,并跳过一切。我写了一个简单的函数来筛选基于扩展网址,但因为很多下载链接,不包括在其中的文件名/扩展,这是不可靠的。
我可以用aiohttp.ClientSession.head()
发送HEAD请求,检查Content-Type
场,以确保它的HTML,然后发送一个单独的GET请求。但是,这将需要每页两个独立的请求(单头,一个GET)增加延迟,我想避免,如果可能的。
是否有可能只是发送一个普通的GET请求,并设置成aiohttp“流”模式,仅下载标题,然后用只有在MIME类型是正确的身体继续进行下载?或者是有用于滤除非HTML内容,我应该考虑的一些(快)的替代方法?
UPDATE
正如意见中的要求,我已经包括了我的意思通过使两个独立的HTTP请求(一个HEAD请求和一个GET请求)一些示例代码:
import asyncio
import aiohttp
urls = ['http://www.google.com', 'http://www.yahoo.com']
results = []
async def get_urls_async(urls):
loop = asyncio.get_running_loop()
async with aiohttp.ClientSession() as session:
tasks = []
for u in urls:
print(f"This is the first (HEAD) request we send for {u}")
tasks.append(loop.create_task(session.get(u)))
results = []
for t in asyncio.as_completed(tasks):
response = await t
url = response.url
if "text/html" in response.headers["Content-Type"]:
print("Sending the 2nd (GET) request to retrive body")
r = await session.get(url)
results.append((url, await r.read()))
else:
print(f"Not HTML, rejecting: {url}")
return results
results = asyncio.run(get_urls_async(urls))
这是一个协议的问题,如果你做一个GET
,服务器要发送的身体。如果不找回身体,你不得不丢弃的连接(其实这是它做什么,如果你不read()
之前做__aexit__
上的响应)。
所以上面的代码应该做更多的少,你想要什么。注:服务器可能在第一块已经有送不仅仅是头