Scrapy爬取招标网站遇访客页面拦截,求解决方案
问题分析与修复方案
核心问题点
allowed_domains配置错误:写成了单数形式allowed_domain,且值为完整URL,正确写法应为域名列表allowed_domains = ['aji-france.com']- 爬取逻辑顺序颠倒:当前代码直接跳转匿名访问链接,未先请求招标详情页,正确流程是先访问详情页,遇到拦截时再触发匿名访问
- 拦截处理缺失会话关联:匿名访问后需重新请求原详情页,而非直接在匿名访问的响应中提取内容
- XPath提取冗余:原代码提取的是HTML标签而非纯文本,需要优化XPath确保获取实体名称的文本内容
修正后的代码
import scrapy BASE_DOMAIN = "aji-france.com" class TendersSpider(scrapy.Spider): name = "tenders_spider" allowed_domains = [BASE_DOMAIN] start_urls = [ 'https://mapa.aji-france.com/mapa/marche/', ] def parse(self, response): # 遍历所有招标卡片,提取详情页链接 for tender_card in response.xpath("//div[@class='card mb-2']"): detail_url = tender_card.xpath(".//a[@class='stretched-link']/@href").get() if detail_url: # 先请求详情页,遇到拦截时处理 yield scrapy.Request( response.urljoin(detail_url), callback=self.parse_tender_detail, meta={'original_url': detail_url} # 保存原详情页URL,用于后续重访 ) def parse_tender_detail(self, response): # 检查是否是拦截页面(存在匿名访问按钮) anonymous_link = response.xpath("//a[contains(text(), 'Continuer la visite anonymement')]/@href").get() if anonymous_link: # 触发匿名访问,完成后重访原详情页 yield scrapy.Request( response.urljoin(anonymous_link), callback=self.handle_anonymous_access, meta={'original_url': response.meta['original_url']}, dont_filter=True ) return # 正常页面,提取Etablissement信息 entity_xpath = "//div[normalize-space()='Etablissement']/following-sibling::div//td/text()" entity_name = response.xpath(entity_xpath).get(default="未找到实体名称") yield { 'entity': entity_name.strip() if entity_name else "未找到实体名称", 'detail_url': response.url } def handle_anonymous_access(self, response): # 匿名访问完成后,重新请求原详情页 original_url = response.meta['original_url'] yield scrapy.Request( response.urljoin(original_url), callback=self.parse_tender_detail, dont_filter=True )
关键修复说明
- 会话保持:Scrapy自动维护CookieJar,匿名访问后Cookie会被保留,重访详情页时即可正常访问
- 逻辑调整:先请求详情页,判断是否被拦截,再触发匿名访问,最后重访详情页,符合网站访问流程
- XPath优化:提取
text()而非直接获取标签,确保拿到纯文本的实体名称 - 错误处理:用
default参数处理找不到内容的情况,保证输出稳定
内容的提问来源于stack exchange,提问作者Aurel
相关产品推荐
相关产品推荐

