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

爬取文件类网站时如何跳过父目录?

解决目录式网站爬虫中重复URL的问题

这个问题我之前爬文件服务器的时候也碰到过!核心原因是直接用字符串拼接URL会导致路径不规范,比如../这类相对路径符号没被正确解析,生成了不同字符串但指向同一资源的URL,让爬虫重复抓取。下面给你两个关键的修复步骤:

1. 用urljoin正确拼接相对路径

别直接用response.url + url来拼接,这种方式完全没处理相对路径的逻辑。换成urllib.parse.urljoin,它会自动根据基础URL(response.url)来解析相对路径,比如把http://example.com/root/sub/和../sub/file拼接成正确的http://example.com/root/sub/file,而不是错误的http://example.com/root/sub/../sub/file。

2. 规范化URL(可选但推荐)

如果还担心有其他路径不规范的情况(比如重复的/、大小写问题),可以用Scrapy自带的w3lib.url.canonicalize_url来生成标准格式的URL,确保同一资源只有唯一的URL标识,彻底避免重复请求。

修改后的完整代码

from urllib.parse import urljoin
from w3lib.url import canonicalize_url
import scrapy
from scrapy import Item, Spider

class fileSpider(Spider):
    name = 'filespider'
    videoext = ['.mp4', '.avi', '.mov']  # 假设你定义了视频后缀列表

    def __init__(self, filename=None):
        if filename:
            with open(filename, 'r') as f:
                self.start_urls = [url.strip() for url in f.readlines()]

    def parse(self, response):
        item = Item()
        for url in response.xpath('//a/@href').extract():
            # 第一步:正确拼接相对路径
            raw_url = urljoin(response.url, url)
            # 第二步:规范化URL,消除路径冗余
            normalized_url = canonicalize_url(raw_url)

            if normalized_url[-4:] in self.videoext:
                item['name'] = url.split('/')[-1]  # 优化:提取真实文件名而非原相对路径
                item['url'] = normalized_url
                item['depth'] = response.meta.get("depth", 0)  # 加默认值避免KeyError
                yield item
            elif normalized_url[-1] == '/':
                # 用规范化后的URL发起请求,确保不会重复爬取同一目录
                yield scrapy.Request(normalized_url, callback=self.parse)

额外说明

  • Scrapy的调度器默认会对URL去重,只要你传递给scrapy.Request的是规范化后的URL,相同资源就只会被请求一次。
  • w3lib是Scrapy的依赖库,一般已随Scrapy安装,若缺失可通过pip install w3lib补充安装。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:19:48