背景描述:
我刚开始接触爬虫,看网上教程开始一点点学习,所有的掌握知识点掌握比较浅,如果有更好的方法欢迎评论分享。
初始爬虫非常简单:对一个网页中的数据列表进行爬取,网页返回的格式也非常简单是一个字典形式,直接用.json()
保存成字典就可以直接存取。
刚开始接触异步协程,做完练习之后,尝试把原来的爬虫进行改造,由此出现报错。
初始代码:
async def download_page(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
await result = resp.text()
async def main(urls):
tasks = []
for url in urls:
tasks.append(asyncio.create_task(download_page(url))) # 我的python版本为3.9.6
await asyncio.await(tasks)
if __name__ == '__main__':
urls = [ url1, url2, …… ]
asyncio.run(main(urls))
这是最基本的一个异步协程框架,在数据量不大的情况下,可以基本满足要求,但是,数据量稍大一些,就会把报错,我收集到的报错信息有以下几种:
aiohttp.client_exceptions.ClientOSError: [WinError 64] 指定的网络名不再可用。
Task exception was never retrieved
aiohttp.client_exceptions.ClientOSError: [WinError 121] 信号灯超时时间已到
Task exception was never retrieved
aiohttp.client_exceptions.ServerDisconnectedError: Server disconnected
Task exception was never retrieved
大概的错误信息都是网络请求和连接有问题。
因为是初学者,没有对网络连接有更多的深入了解,也没有学习过更加深入的异步协程操作。所以对于解决报错比较难办。
解决思路:
上述报错比较大的问题是在于每一个任务都创建了一个session,当创建过多session时就会报错。
解决办法:
尝试只创建一个session
import asyncio
import aiohttp
async def download_page(url,session):
async with session.get(url) as resp:
result = await resp.content.read()
print(result)
async def main(urls):
tasks = []
async with aiohttp.ClientSession() as session: # 将创建session,放在main函数中,同时,需要注意将session作为变量传入download_page函数中
for url in urls:
tasks.append(asyncio.create_task(download_page(url,session)))
# 我的python版本为3.9.6,python版本3.8及以上,如果需要创建异步任务,需要通过asyncio.creat_task()创建,否则虽然可以正常运行,但是会出警告信息
await asyncio.wait(tasks)
if __name__ == '__main__':
urls = [ url1, url2, …… ]
asyncio.run(main(urls))
这样在爬取大量数据的时候,可以一定程度上解决连接错误的问题。
比较初级的解决办法,后续知识陆续在学~
感悟:在编程过程中,思维还是要更灵活一些。稍加变动,就可能将效率提高很多。