鱼C论坛

 找回密码
 立即注册
查看: 747|回复: 4

[已解决]异步爬虫,东西是爬到了,但是结束时一片红,是什么问题?

[复制链接]
发表于 2023-11-26 18:16:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
代码如下
  1. import asyncio
  2. import aiohttp
  3. import aiofile
  4. import os

  5. class HeroSkin:
  6.     def __init__(self):
  7.         self.json_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2834976'
  8.         self.skin_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2834984'
  9.         self.headers = {
  10.             'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
  11.             }

  12.     async def get_image_content(self,session,heroid):
  13.         async with session.get(self.skin_url.format(heroid),headers=self.headers) as response:
  14.             result = await response.json(content_type = None)
  15.             for skin in result['skins']:
  16.                
  17.                 skin_name = skin['name'].replace(' ','_')
  18.                 hero_title = skin['heroTitle']
  19.                 img_url = skin['mainImg']
  20.                 async with session.get(img_url) as skin_res:
  21.                     content = await skin_res.read()
  22.                     async with aiofile.async_open('./images/'+hero_title+'-'+skin_name+'.jpg',mode='wb') as f:
  23.                         await f.write(content)
  24.                         print('保存成功:',skin_name)

  25.     async def main(self):
  26.         tasks = list()
  27.         async with aiohttp.ClientSession() as session:
  28.             async with session.get(self.json_url,headers=self.headers) as response:
  29.                 result = await response.json(content_type = None)
  30.                 for item in result['hero']:
  31.                     heroid = item['heroId']
  32.                     coro_obj = self.get_image_content(session,heroid)
  33.                     tasks.append(asyncio.create_task(coro_obj))
  34.                 await asyncio.wait(tasks)

  35. if __name__ == '__main__':
  36.     if not os.path.exists('./images'):
  37.         os.mkdir('./images')

  38.     hero_skin = HeroSkin()
  39.     asyncio.run(hero_skin.main())
复制代码

最佳答案
2023-11-26 18:50:16
因为异步当其中一个协程出错的时候不会导致程序中断,所以程序结束后一并抛出

而你的程序中导致协程异常的原因就两个:

1、英雄名中带着无法作为windwos文件名的非法字符

2、有一些英雄不知道是没有图片还是怎样,总之 skin['mainImg'] 字段为空,所以出现了无效的 url 错误

对你的程序修改如下:
  1. import asyncio
  2. import aiohttp
  3. import aiofile
  4. import os
  5. import re

  6. class HeroSkin:
  7.     def __init__(self):
  8.         self.json_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2834976'
  9.         self.skin_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2834984'
  10.         self.headers = {
  11.             'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
  12.             }

  13.     async def get_image_content(self,session,heroid):
  14.         async with session.get(self.skin_url.format(heroid),headers=self.headers) as response:
  15.             result = await response.json(content_type = None)
  16.             for skin in result['skins']:
  17.                
  18.                 skin_name = skin['name'].replace(' ','_')
  19.                 hero_title = skin['heroTitle']
  20.                 img_url = skin['mainImg']
  21.                 if img_url:
  22.                     async with session.get(img_url) as skin_res:
  23.                         content = await skin_res.read()
  24.                         filename = hero_title+'-'+skin_name+'.jpg'
  25.                         # 定义文件名非法字符的正则表达式模式
  26.                         pattern = r"[\\/:*?"<>|]"

  27.                         # 使用re.sub()函数将非法字符替换为空字符
  28.                         new_filename = re.sub(pattern, "", filename)

  29.                         async with aiofile.async_open(os.path.join('images', new_filename),mode='wb') as f:
  30.                             await f.write(content)
  31.                             print('保存成功:',skin_name)

  32.     async def main(self):
  33.         tasks = list()
  34.         async with aiohttp.ClientSession() as session:
  35.             async with session.get(self.json_url,headers=self.headers) as response:
  36.                 result = await response.json(content_type = None)
  37.                 for item in result['hero']:
  38.                     heroid = item['heroId']
  39.                     coro_obj = self.get_image_content(session,heroid)
  40.                     tasks.append(asyncio.create_task(coro_obj))
  41.                 await asyncio.wait(tasks)

  42. if __name__ == '__main__':
  43.     if not os.path.exists('./images'):
  44.         os.mkdir('./images')

  45.     hero_skin = HeroSkin()
  46.     asyncio.run(hero_skin.main())
复制代码
%)Z[W0Y3LY%($GZ~OB3(~SA.png
AH27L(%)F])8S~S$G`DBT%R.png

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-11-26 18:16:18 | 显示全部楼层
在异步爬虫中,红色错误可能表明出现了异常,通过查看错误信息可以确定具体的问题。一般来说,常见的问题包括网络连接错误、网站反爬虫机制导致的请求被阻止、文件路径不存在等。

首先,你可以尝试打印出异常信息,以便进一步分析问题。在`get_image_content`方法中的`await response.json(content_type = None)`处使用`try...except`块,捕获异常并打印出错误信息。修改代码如下:
  1. async def get_image_content(self,session,heroid):
  2.     async with session.get(self.skin_url.format(heroid),headers=self.headers) as response:
  3.         try:
  4.             result = await response.json(content_type=None)
  5.             for skin in result:
  6.                 # 省略部分代码
  7.                 pass
  8.         except Exception as e:
  9.             print('出现异常:', str(e))
复制代码

运行程序,查看控制台输出的错误信息,根据错误信息尝试解决问题。

如果是网络连接错误,可以检查网络环境是否正常,或者尝试使用代理进行请求。

如果是网站反爬虫机制导致的请求被阻止,可以尝试在请求头中加入更多的参数,模拟浏览器行为,例如设置`Referer`头字段。

如果是文件路径不存在的问题,可以先检查路径是否正确,然后确保路径对应的文件夹存在。可以在程序开始部分添加一个判断并创建文件夹的逻辑,如下所示:
  1. if __name__ == '__main__':
  2.     if not os.path.exists('./images'):
  3.         os.mkdir('./images')
  4.     hero_skin = HeroSkin()
  5.     asyncio.run(hero_skin.main())
复制代码

这样可以确保目标文件夹`./images`存在,否则会自动创建。

以上回复来自 -- ChatGPT(FishC官方接口),如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-11-26 18:38:57 | 显示全部楼层
出现异常: Server disconnected
出现异常: [Errno 2] No such file or directory: './images/阿卡丽-K/DA_阿卡丽.jpg'
出现异常: [WinError 121] 信号灯超时时间已到
出现异常:

字符串异常忽略,这个没注意到,剩下的是网络问题和并发量太大???
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-11-26 18:39:12 | 显示全部楼层
鱼-wsyy 发表于 2023-11-26 18:38
出现异常: Server disconnected
出现异常:  No suc ...

根据你提供的错误信息,可以得出以下结论:

1. "Server disconnected":这个错误通常是网络连接问题导致的,可能是服务器关闭了连接或者网络不稳定。建议检查网络连接是否正常,尝试使用代理或更稳定的网络环境进行请求。

2. "No such file or directory: './images/阿卡丽-K/DA_阿卡丽.jpg'":这个错误是因为指定的文件夹`./images/阿卡丽-K`不存在。请确保在保存图片之前创建好对应的文件夹。

3. "信号灯超时时间已到":这是异步操作中的超时错误,可能是由于网络连接较慢或请求响应时间过长导致的。可以尝试增加超时时间,例如通过设置`timeout`参数来延长等待时间。

4. "字符串异常忽略":这个错误提示不明确,可能是某个具体的字符串处理出现了异常。你可以检查相关代码,确保字符串的处理方法正确。

至于并发量太大的问题,可以尝试减少并发请求数量,通过调整`asyncio.wait`中的并发任务数量来控制同时进行的请求数量。也可以考虑使用限制并发数量的工具,例如`asyncio.Semaphore`来限制并发数量。

综上所述,尝试解决以上问题,并确保网络连接稳定,文件夹存在,超时时间合适,并且对字符串处理进行正确的异常处理。这样应该能够解决你遇到的问题。

以上回复来自 -- ChatGPT(FishC官方接口),如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-11-26 18:50:16 | 显示全部楼层    本楼为最佳答案   
因为异步当其中一个协程出错的时候不会导致程序中断,所以程序结束后一并抛出

而你的程序中导致协程异常的原因就两个:

1、英雄名中带着无法作为windwos文件名的非法字符

2、有一些英雄不知道是没有图片还是怎样,总之 skin['mainImg'] 字段为空,所以出现了无效的 url 错误

对你的程序修改如下:
  1. import asyncio
  2. import aiohttp
  3. import aiofile
  4. import os
  5. import re

  6. class HeroSkin:
  7.     def __init__(self):
  8.         self.json_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2834976'
  9.         self.skin_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2834984'
  10.         self.headers = {
  11.             'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
  12.             }

  13.     async def get_image_content(self,session,heroid):
  14.         async with session.get(self.skin_url.format(heroid),headers=self.headers) as response:
  15.             result = await response.json(content_type = None)
  16.             for skin in result['skins']:
  17.                
  18.                 skin_name = skin['name'].replace(' ','_')
  19.                 hero_title = skin['heroTitle']
  20.                 img_url = skin['mainImg']
  21.                 if img_url:
  22.                     async with session.get(img_url) as skin_res:
  23.                         content = await skin_res.read()
  24.                         filename = hero_title+'-'+skin_name+'.jpg'
  25.                         # 定义文件名非法字符的正则表达式模式
  26.                         pattern = r"[\\/:*?"<>|]"

  27.                         # 使用re.sub()函数将非法字符替换为空字符
  28.                         new_filename = re.sub(pattern, "", filename)

  29.                         async with aiofile.async_open(os.path.join('images', new_filename),mode='wb') as f:
  30.                             await f.write(content)
  31.                             print('保存成功:',skin_name)

  32.     async def main(self):
  33.         tasks = list()
  34.         async with aiohttp.ClientSession() as session:
  35.             async with session.get(self.json_url,headers=self.headers) as response:
  36.                 result = await response.json(content_type = None)
  37.                 for item in result['hero']:
  38.                     heroid = item['heroId']
  39.                     coro_obj = self.get_image_content(session,heroid)
  40.                     tasks.append(asyncio.create_task(coro_obj))
  41.                 await asyncio.wait(tasks)

  42. if __name__ == '__main__':
  43.     if not os.path.exists('./images'):
  44.         os.mkdir('./images')

  45.     hero_skin = HeroSkin()
  46.     asyncio.run(hero_skin.main())
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-18 10:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表