爬取文件类网站时如何跳过父目录?
解决目录式网站爬虫中重复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
相关产品推荐
相关产品推荐

