V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
qtoq126
V2EX  ›  Python

写的 Scrapy 爬虫程序在 For 循环中会漏爬很多数据

  •  
  •   qtoq126 · 3 天前 · 1688 次点击

    有没有对 Scrapy 爬虫很精通的朋友,我目前的爬虫有些问题

    import scrapy
    from xxx.items import WorkItem
    
    class XXXSpider(scrapy.Spider):
        name = "xxx"
        allowed_domains = ["example.com"]
        start_urls = ["https://example.com/xx/xx"]
    
        def parse(self, response):
            year_list = response.xpath('//ul[@class="p-accordion"]/li')
            for year in year_list[:2]:
                release_dates_url_of_year = year.xpath('.//div[@class="genre -s"]/a/@href').extract()
                for date_url in release_dates_url_of_year:
                    yield scrapy.Request (
                        url = date_url,
                        callback =self.date_detail_parse
                    )
    
        def date_detail_parse(self, response):
            work_list = response.xpath('.//div[@class="swiper-slide c-low--6"]/div')
            for work in work_list:
                actress_name = work.xpath('.//a[@class="name c-main-font-hover"]/text()').extract_first()
                if actress_name is not None:
                    item = WorkItem()
                    item['actress_name'] = actress_name
                    item['image_hover'] = work.xpath('.//img[@class="c-main-bg lazyload"]/@data-src').extract_first()
                    work_detail_url = work.xpath('.//a[@class="img hover"]/@href').extract_first()
    
                    if work_detail_url is not None:
                        yield scrapy.Request (
                            url = work_detail_url,
                            callback = self.work_detail_pares,
                            meta = {'workItem' : item}
                        )
    
        def work_detail_pares(self, response):
            item = response.meta['workItem']
            pics_list = response.xpath('.//div[@class="swiper-wrapper"]/div')
            pre_images = []  
            for pic in pics_list:
                img_url = pic.xpath('./img/@data-src').extract_first()
                pre_images.append(img_url)
            item['pre_images'] = pre_images
            item['name'] = response.xpath('.//div[@class="p-workPage l-wrap"]/h2/text()').extract_first().strip()
            item['id'] = response.xpath('.//span[@class="c-tag02 c-main-bg-hover c-main-bg"]/../text()').extract_first()
            item['company'] = 'xxx'
            item['release_date'] = response.xpath('.//div[@class="p-workPage__table"]/div[2]//div[@class="item"]/a/text()').extract_first()
            actress_detail_url = response.xpath('.//div[@class="p-workPage__table"]/div[1]//div[@class="item"]/a/@href').extract_first()
            yield scrapy.Request(
                url = actress_detail_url,
                callback = self.actress_detail_pase,
                meta = {'workItem' : item}
            )
    
        def actress_detail_pase(self, response):
            item = response.meta['workItem']
            item['actress_avatar'] = response.xpath('.//div[@class="swiper-slide"]/img/@data-src').extract_first()
            yield item
    
    1. 这是我的爬虫主程序,year_list我目前就只取了前 2 条数据做测试,发现爬取下来的数据跟网站上相比,很漏爬很多很多数据,而且每次爬取的数量都是同一个,网站上应该有至少几百条数据,而爬虫爬取下来,每次只能爬 35 条数据。而且每次爬取的数据内容都是变化的,这次没爬到的数据可能下一次再启动爬虫他就爬到了,但是总数永远是 35 。
    2. 我也尝试过把item包在deepcopy()里,也没有区别。
    3. 如果不用for循环,就只爬单条数据的话,他又确实可以把完整的数据都爬取下来

    有没有大佬知道我这问题到底出在哪里?问 GPT 的各种解答方案也试了,还是不行。

    14 条回复    2024-12-25 09:52:17 +08:00
    glacer
        1
    glacer  
       3 天前
    断点调试一下不是很容易发现问题吗
    NoOneNoBody
        2
    NoOneNoBody  
       3 天前
    @class="genre -s"
    css 不会写-s 的吧?

    先在每个 for 前面 print 一下 len 吧
    dsg001
        3
    dsg001  
       3 天前
    大概率是 xpath 不对
    wineast
        4
    wineast  
       3 天前
    yeild 之前 打印下信息,看看条数对不对
    qtoq126
        5
    qtoq126  
    OP
       3 天前
    @wineast 我刚才在多个地方放了 print 打印看了下,发现有些在`work_detail_pares()`里处理的`item`,到了`actress_detail_pase()`就没有了。(比如有条 item 的一个字段是 12 月 31 日,结果在 actress_detail_pase()打印,发现没有一条 item 里有 12 月 31 日。这条数据没有传进来,甚至如果把`actress_detail_pase()`的方法删了,数据就可以抓取完全了。这是什么原因?我的传值方法也没什么不一样的啊
    airqj
        6
    airqj  
       3 天前
    碰到这种问题把网页和源码扔给 claude ,直接就给你答案了
    Jius7u
        7
    Jius7u  
       3 天前
    问下 AI 对于 AI 来说应该简单
    qtoq126
        8
    qtoq126  
    OP
       3 天前
    @airqj 我反正把源码和问题抛给 GPT ,他是没跟我干出来的
    airqj
        9
    airqj  
       3 天前
    @qtoq126 #8 代码方面 claude 好一些
    datehoer
        10
    datehoer  
       3 天前
    直接 debug 走一下就搞出来了吧。
    可以看下日志是否有报错,你这个问题一般是哪里有错误,比如网站做了反爬,然后获取数据有问题。或者有可能是 url 有重复,被自动去冲了。
    my8100
        11
    my8100  
       3 天前 via iPhone
    把 scrapy 抓取的网页保存到文件,再手动调用解析一次,看是网页还是解析问题。
    Vegetable
        12
    Vegetable  
       3 天前
    不给页面的情况下想让大家看这玩意给你解决问题很难的,大概率是你解析的代码有问题,但是不知道是你写错了还是页面规则你没搞清楚。
    你可以在 scrapy shell 一步一步手动操作,看看到底哪里不对。
    duzhuo
        13
    duzhuo  
       3 天前
    建议直接把网站发出来
    wineast
        14
    wineast  
       3 天前
    @qtoq126 yield scrapy.Request(
    url = actress_detail_url,
    callback = self.actress_detail_pase,
    meta = {'workItem' : item}
    “actress_detail_pase”,是一个回调函数。他要被执行的话,前提就是上面这个 actress_detail_url 要被执行后才能回调,你看下所有的请求,这个 12/31 的请求是不是:
    1. 没有被正确拼接 url
    2. 因为网站反扒的缘故,没有返回 200
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2796 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 03:16 · PVG 11:16 · LAX 19:16 · JFK 22:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.