鱼C论坛

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

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

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

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

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

x
代码如下
import asyncio
import aiohttp
import aiofile
import os

class HeroSkin:
    def __init__(self):
        self.json_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2834976'
        self.skin_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2834984'
        self.headers = {
            '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'
            }

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

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

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

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

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

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

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

对你的程序修改如下:
import asyncio
import aiohttp
import aiofile
import os
import re

class HeroSkin:
    def __init__(self):
        self.json_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2834976'
        self.skin_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2834984'
        self.headers = {
            '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'
            }

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

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

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

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

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

    hero_skin = HeroSkin()
    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`块,捕获异常并打印出错误信息。修改代码如下:
async def get_image_content(self,session,heroid):    async with session.get(self.skin_url.format(heroid),headers=self.headers) as response:        try:            result = await response.json(content_type=None)            for skin in result:                # 省略部分代码                pass        except Exception as e:            print('出现异常:', str(e))
运行程序,查看控制台输出的错误信息,根据错误信息尝试解决问题。

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

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

如果是文件路径不存在的问题,可以先检查路径是否正确,然后确保路径对应的文件夹存在。可以在程序开始部分添加一个判断并创建文件夹的逻辑,如下所示:
if __name__ == '__main__':    if not os.path.exists('./images'):        os.mkdir('./images')    hero_skin = HeroSkin()    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 错误

对你的程序修改如下:
import asyncio
import aiohttp
import aiofile
import os
import re

class HeroSkin:
    def __init__(self):
        self.json_url = 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2834976'
        self.skin_url = 'https://game.gtimg.cn/images/lol/act/img/js/hero/{}.js?ts=2834984'
        self.headers = {
            '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'
            }

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

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

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

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

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

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-21 17:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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