学习scrapy爬虫,练习爬取豆瓣电影的数据并下载电影的封面图片。参考官方文档写完代码后,无法下载封面图片。在日志里发现了如下的提示信息
2025-04-03 23:04:12 [scrapy.downloadermiddlewares.offsite] DEBUG: Filtered offsite request to 'img9.doubanio.com': <GET https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2153663114.jpg>
2025-04-03 23:04:12 [scrapy.pipelines.media] ERROR: [Failure instance: Traceback: <class 'scrapy.pipelines.files.FileException'>:
/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/twisted/internet/defer.py:1088:_runCallbacks
/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/scrapy/pipelines/files.py:627:media_failed
]
以FileException为线索,起初怀疑是文件系统的权限问题。排除权限问题后,又看了一下scrapy的源代码,没有找到任何线索。于是求助Trae编程助手,它给出了很多尝试,多次失败后终于解决了问题。逐一排查Trae所做的代码修改,发现是把dont_filter参数设置为True解决的问题,如下
scrapy.Request(image_url, dont_filter=True)
把dont_filter参数设置为True的字面意思是禁用filter。有意思的是,在代码里并没有主动设置filter的地方。一番搜索后才发现罪魁祸首是因为我在spider里定义了错误的allowed_domains。我最开始的代码中allowed_domains是限定在movie.douban.com
class DoubanMovieSpider(scrapy.Spider):
name = "douban_movie"
allowed_domains = ["movie.douban.com"]
根据错误提示,我扩充了allowed_domains,把错误过滤掉的图片地址的domain添加到list中,于是变为
class DoubanMovieSpider(scrapy.Spider):
name = "douban_movie"
allowed_domains = ["movie.douban.com", "img9.doubanio.com"]
现在不需要Trae所做的修改(把dont_filter参数设置为True)也可能正常下载豆瓣电影的封面图片了。
回顾整个过程,有以下几点感悟
- scrapy的genspider命令生成的spider模版代码中,默认就有allowed_domains,如果要爬取的资源所在的domain不在allowed_domains中,爬取就无法成功。
- scrapy的FileException错误提示容易造成误解。如果某个URL爬取被过滤掉了,那么基于这个URL就不应该产生FileException。毕竟爬取的URL被过滤,理论上不会有相关的文件读写操作,那么报出这个异常就很容易造成误导了。
- Trae编程助手确实帮到了我,但它有点像是无头苍蝇在乱撞,给出了很多不必要的代码修改。Trae给出的最终方案也并不是问题的关键所在,只是恰好它给出的修改方案解决了问题。不过Trae确实提供了问题解决的思路。从这点来说,AI编程助手确实能在一定程度上提高编程的效率。