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

Scrapy解析Item失败、性能优化及爬虫项目相关问题咨询

代码运行失败原因&修复方案

错误点整理

  1. XPath语法错误:parse_item函数中.//span[contains(@class, )]缺少contains方法的第二个匹配参数,属于非法表达式,直接触发运行报错。
  2. 分页逻辑错位:下一页链接属于列表页元素,你将分页逻辑写在处理详情页的parse_item函数中,无法正常获取分页链接,导致只能爬取第一页列表数据。
  3. 数据拆分输出:列表页提取的基础字段和详情页提取的扩展字段分开yield,会导致两类字段拆分到CSV的不同行,无法合并为单条完整的房源数据。
  4. 无空值防护:直接对spanlist、alist取下标,当页面结构变化、请求异常返回空列表时,会抛出IndexError导致爬虫终止。
  5. 缩进语法错误:你贴出的代码中类定义、函数定义前有多余缩进,不符合Python语法规范,会直接触发缩进错误。

修正后可运行代码

import scrapy
from scrapy import Request
from datetime import datetime
from scrapy.crawler import CrawlerProcess

dt_today = datetime.now().strftime('%Y%m%d')
file_name = dt_today+' HPI Data'

# Create Spider class
class UneguiApartments(scrapy.Spider):
    name = 'unegui_apts'
    allowed_domains = ['www.unegui.mn']
    custom_settings = {'FEEDS': {f'{file_name}.csv': {'format': 'csv'}},
                   'USER_AGENT': "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36"}
    start_urls = [
        'https://www.unegui.mn/l-hdlh/l-hdlh-zarna/oron-suuts-zarna/'
    ]

    def parse(self, response):
        cards = response.xpath('//li[contains(@class,"announcement-container")]')
        for card in cards:
            name = card.xpath(".//a[@itemprop='name']/@content").extract_first()
            price = card.xpath(".//*[@itemprop='price']/@content").extract_first()
            date_block = card.xpath("normalize-space(.//div[contains(@class,'announcement-block__date')]/text())").extract_first().split(',')
            date = date_block[0].strip()
            city = date_block[1].strip()
            link = card.xpath(".//a[@itemprop='url']/@href").extract_first()
            # 列表页基础数据通过meta传给详情页处理函数
            base_info = {
                'name': name,
                'price': price,
                'date': date,
                'city': city,
                'link': response.urljoin(link)
            }
            yield Request(response.urljoin(link), callback=self.parse_item, meta={'base_info': base_info})
        
        # 分页逻辑移到列表页处理函数中
        next_url = response.xpath("//a[contains(@class,'red')]/parent::li/following-sibling::li/a/@href").extract_first()
        if next_url:
            yield response.follow(next_url, callback=self.parse)

    def parse_item(self, response):
        base_info = response.meta['base_info']
        # 补全contains的第二个参数,匹配你需要的span的class特征
        spanlist = response.xpath('.//span[contains(@class, "你要匹配的class关键词")]//text()').extract()
        alist = response.xpath(".//a[@itemprop='url']/@href").extract()
        # 增加空值判断
        base_info['item1'] = spanlist[0].strip() if len(spanlist)>=1 else None
        base_info['item2'] = spanlist[1].strip() if len(spanlist)>=2 else None
        base_info['item3'] = alist[0].strip() if len(alist)>=1 else None
        base_info['item4'] = alist[1].strip() if len(alist)>=2 else None
        # 合并后统一输出,保证所有字段在同一行
        yield base_info

# main driver
if __name__ == "__main__":
    process = CrawlerProcess()
    process.crawl(UneguiApartments)
    process.start()
咨询问题解答
  1. 同一站点下,如果不同分类的页面结构、字段规则相似,建议抽离公共基类爬虫,各分类爬虫继承基类仅重写差异化的规则即可,不用完全独立开发;如果分类之间结构差异极大,再单独开发独立爬虫。
  2. 同一个站点的爬虫代码放在同一个Scrapy项目的spiders目录下即可,不同站点的爬虫再拆分到不同项目;字段定义、存储逻辑、中间件这类公共组件统一放在对应公共目录,不用拆分。
  3. 命名遵守Python PEP8规范即可:爬虫名用小写+下划线,比如unegui_apartment_rent;Item类用大驼峰命名,比如UneguiHouseItem;函数、变量用小写+下划线,禁止用拼音,尽量见名知意。
  4. ItemLoader不会提升运行速度,但会大幅提升代码可维护性,把数据清洗逻辑和爬虫提取逻辑解耦,后续调整清洗规则不需要修改爬虫代码,非常适配你后续做数据标准化、清洗的需求,完全可以使用。
  5. 优化方向:用Item类统一定义所有字段,不要直接yield字典;数据清洗、存储逻辑全部放到Pipeline中,不要写在爬虫代码里;用Scrapy自带的去重过滤器+数据库唯一索引实现房源去重;动态页面优先抓AJAX接口,确实需要渲染的话用scrapy-playwright替代Selenium,性能更高适配性更好;调优并发数、下载延迟配置,搭配UA池、代理池应对反爬;完善日志配置,方便故障排查。
扩展建议

你的项目目标完全可以实现,不需要认为过于宏大,按模块迭代开发即可:

  • 数据存储:DBeaver是数据库管理工具,实际存储建议用MySQL/PostgreSQL这类关系型数据库,写Pipeline实现存储逻辑,通过配置项切换输出CSV还是存入数据库。
  • 定时运行:简单需求直接用Linux crontab或Windows任务计划,复杂调度可以用Airflow实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:36:03