You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用Scrapy爬取视频?爬虫无法正确下载视频求助

解决Scrapy FilesPipeline无法正确下载视频的问题

嘿,我来帮你搞定这个问题——用FilesPipeline能爬图片但视频下载异常,这是个很常见的情况,大概率是你抓的不是真实的视频源URL,或者请求时缺了必要的头信息,导致服务器返回的不是视频文件(比如返回404、网页内容甚至缩略图)。下面分几个方向一步步排查解决:

1. 先确认file_urls里的是真实视频源地址

很多网站不会把视频的真实URL直接暴露在页面里,你当前抓到的可能是:

  • 嵌入播放器的iframe链接
  • 视频的缩略图URL
  • 经过加密或跳转的中间链接

怎么验证?
file_urls里的链接复制到浏览器新标签页打开:

  • 如果打开后是视频播放页面,不是直接弹出下载框或播放视频,说明你抓的不是真实源地址
  • 如果能直接下载或播放视频,那这个URL才是正确的

怎么获取真实源?
打开浏览器开发者工具(按F12),切换到「网络」标签,筛选「媒体(Media)」类型,然后播放页面上的视频,就能看到浏览器请求的真实视频URL,这个才是你要放进file_urls里的地址。

2. 给视频请求添加必要的请求头/参数

有些网站会校验请求的User-AgentReferer甚至Cookie,如果你的Scrapy请求头和浏览器不一样,服务器可能拒绝返回视频,转而返回其他内容。

修改你的get_media_requests方法,加上模拟浏览器的请求头:

def get_media_requests(self, item, info):
    adapter = ItemAdapter(item)
    for file_url in adapter["file_urls"]:
        # 根据目标网站调整请求头,这里用Chrome的UA举例
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
            'Referer': adapter.get('page_url', '')  # 视频所在页面的URL,很多网站会校验这个字段
        }
        yield scrapy.Request(file_url, headers=headers)

3. 检查FilesPipeline的配置是否正确

确保你的settings.py里的配置没问题:

# 启用FilesPipeline
ITEM_PIPELINES = {
    'scrapy.pipelines.files.FilesPipeline': 1,
}
# 设置视频下载的存储目录
FILES_STORE = './downloaded_videos'
# 指定item中存储URL和结果路径的字段(如果你的字段名和默认一致,可以不用写,但建议明确)
FILES_URLS_FIELD = 'file_urls'
FILES_RESULT_FIELD = 'file_paths'

如果想只下载特定格式的视频(比如mp4、mkv),可以在get_media_requests里加个过滤:

def get_media_requests(self, item, info):
    adapter = ItemAdapter(item)
    # 只允许这些格式的视频URL
    allowed_extensions = ('.mp4', '.mov', '.avi', '.mkv')
    for file_url in adapter["file_urls"]:
        if file_url.endswith(allowed_extensions):
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
                'Referer': adapter.get('page_url', '')
            }
            yield scrapy.Request(file_url, headers=headers)

4. 处理m3u8分段视频的情况

如果目标网站用的是m3u8流媒体格式,FilesPipeline是无法直接处理的,因为m3u8是一个播放列表文件,里面包含了很多视频分片的URL。这种情况需要额外处理:

  • 可以使用scrapy-m3u8这类第三方库来简化流程
  • 或者自己编写逻辑:先下载m3u8文件,解析出所有分片URL,下载分片后再合并成完整视频

举个简单的m3u8处理思路(需要先安装m3u8库:pip install m3u8):

import m3u8
from scrapy.exceptions import DropItem

def get_media_requests(self, item, info):
    adapter = ItemAdapter(item)
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
        'Referer': adapter.get('page_url', '')
    }
    for file_url in adapter["file_urls"]:
        if file_url.endswith('.m3u8'):
            # 解析m3u8播放列表
            m3u8_obj = m3u8.load(file_url, headers=headers)
            # 遍历所有分片URL并发起请求
            for segment in m3u8_obj.segments:
                segment_url = segment.absolute_uri
                yield scrapy.Request(segment_url, headers=headers)
        else:
            # 处理普通视频URL
            yield scrapy.Request(file_url, headers=headers)

注意:下载完分片后,需要用工具(比如ffmpeg)把分片合并成完整视频,你可以在item_completed方法里调用命令行来完成这个操作。

最后做个小验证

修改完代码后,先跑一个小测试,查看Scrapy的日志:

  • 检查请求的URL是不是你之前在浏览器里找到的真实视频源
  • 查看响应的状态码是不是200
  • 看下载的文件大小,如果只有几KB,那大概率是错误页面或者缩略图,说明URL还是没抓对

内容的提问来源于stack exchange,提问作者MyungHun

火山引擎 最新活动