You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:57:21