Scrapy爬取IMDB时jl文件为空及遇弃用警告的问题求助
问题排查与修正:Scrapy IMDB爬虫无输出+弃用警告
执行命令 scrapy crawl imdb --logfile imdb.log -o imdb.jl -t jsonlines 后,生成了imdb.jl和imdb.log文件,但imdb.jl内容为空,同时收到ScrapyDeprecationWarning弃用警告,以下是用户的爬虫代码:
import re from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from w3lib.url import url_query_cleaner import extruct def process_links(links): for link in links: link.url = url_query_cleaner(link.url) yield link class ImdbCrawler(CrawlSpider): name = 'imdb' allowed_domains = ['www.imdb.com'] start_urls = ['https://www.imdb.com/'] rules = ( Rule( LinkExtractor( deny=[ re.escape('https://www.imdb.com/offsite'), re.escape('https://www.imdb.com/whitelist-offsite'), ], ), process_links=process_links, callback='parse_item', follow=True ), ) def parse_item(self, response): return { 'url': response.url, 'metadata': extruct.extract( response.text, response.url, syntaxes=['opengraph', 'json-ld'] ), }
问题原因分析
1. 无输出(jl文件为空)
- 链接规则过散+去重机制:当前
LinkExtractor几乎允许所有IMDB站内链接,但Scrapy默认去重会跳过重复URL;且首页大量链接指向导航、登录等非内容页,无法触发有效解析,甚至部分链接被规则过滤后无有效请求触发parse_item。 - 反爬拦截:IMDB会识别非浏览器请求,直接返回空页面或拦截,导致抓取不到内容。
- URL清理问题:
url_query_cleaner可能过度修改URL结构,导致链接无法访问或被判定为重复。
2. ScrapyDeprecationWarning弃用警告
主要是LinkExtractor的deny参数使用了完整URL,新版本Scrapy推荐用相对路径或正则匹配路径部分;另外process_links返回生成器的写法在部分版本存在兼容提示。
修正方案
1. 解决无输出问题
(1)聚焦内容页,优化链接规则
只抓取电影/剧集详情页(匹配/title/tt开头的URL),避免无效请求:
LinkExtractor( allow=r'/title/tt\d+/', # 仅匹配电影、剧集详情页 deny=[ r'/offsite', r'/whitelist-offsite' ], allow_domains=allowed_domains )
(2)添加请求头模拟浏览器
在爬虫类中加入custom_settings,设置User-Agent和延迟,绕过基础反爬:
custom_settings = { 'USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', 'DOWNLOAD_DELAY': 2, # 控制请求频率,避免被封 }
(3)调整URL清理逻辑
改为返回列表而非生成器,同时保留必要URL参数:
def process_links(links): cleaned_links = [] for link in links: link.url = url_query_cleaner(link.url, remove_blank=True) cleaned_links.append(link) return cleaned_links
2. 解决弃用警告
将deny中的完整URL改为相对路径正则,无需写完整域名(LinkExtractor会基于allowed_domains自动处理),比如把re.escape('https://www.imdb.com/offsite')改为r'/offsite'。
完整修正代码
import re from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from w3lib.url import url_query_cleaner import extruct def process_links(links): cleaned_links = [] for link in links: link.url = url_query_cleaner(link.url, remove_blank=True) cleaned_links.append(link) return cleaned_links class ImdbCrawler(CrawlSpider): name = 'imdb' allowed_domains = ['www.imdb.com'] start_urls = ['https://www.imdb.com/'] custom_settings = { 'USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', 'DOWNLOAD_DELAY': 2, 'LOG_LEVEL': 'INFO' } rules = ( Rule( LinkExtractor( allow=r'/title/tt\d+/', deny=[ r'/offsite', r'/whitelist-offsite' ], allow_domains=allowed_domains ), process_links=process_links, callback='parse_item', follow=True ), ) def parse_item(self, response): if response.status != 200: self.logger.warning(f"请求失败,状态码:{response.status},URL:{response.url}") return metadata = extruct.extract( response.text, response.url, syntaxes=['opengraph', 'json-ld'] ) if metadata.get('opengraph') or metadata.get('json-ld'): return { 'url': response.url, 'metadata': metadata } else: self.logger.info(f"无有效元数据,URL:{response.url}") return
验证方式
执行命令时去掉日志文件参数,直接在终端查看请求和解析日志,确认是否有内容生成:
scrapy crawl imdb -o imdb.jl -t jsonlines
内容的提问来源于stack exchange,提问作者Ayush V Jain
相关产品推荐
相关产品推荐

