循环刮取多个页面会在第三级产生重复的结果

时间:2018-06-25 19:41:10

标签: python scrapy

在我的以下HTML模板中:


1级(模板_1)

<ul>
    <li>
        <a href="template_2.html">Template 2 (Level 2)</a>
    </li>
</ul>


2级(模板_2)

<ul>
    <li>
        <a href="template_3.html">Template 3 (Level 3)</a>
    </li>
    <li>
        <a href="template_4.html">Template 4 (Level 3)</a>
    </li>
</ul>


第3级(Template_3和Template_4)

<h1>Template 3 Text</h1>

<h1>Template 4 Text</h1>


我想做的是进入 1级 HTML页,然后拉出每个a元素的文本,然后输入使用以下蜘蛛将其拉动每个h1元素文本

# -*- coding: utf-8 -*-
import scrapy


class LESpider(scrapy.Spider):
    name = 'Loop Error'
    start_urls = ['template_1.html']

    def parse(self, response):
        data = {
            'temp_text': None,
            'text': None
        }

        yield scrapy.Request(url=response.css('a::attr(href)').extract_first(), callback=self.parse_lv2, dont_filter=True, meta={"data": data})

    def parse_lv2(self, response):
        for a in response.css('a'):
            data = response.meta.get('data')

            data['temp_text'] = a.css('a::text').extract_first()

            yield scrapy.Request(url=a.css('a::attr(href)').extract_first(), callback=self.parse_lv3, dont_filter=True, meta={"data": data})


    def parse_lv3(self, response):
        data = response.meta.get('data')

        data['text'] = response.css('h1::text').extract_first()

        yield data

我的问题如下:首先,我期望的结果是这样

[
  {"temp_text": "Template 3 (Level 3)", "text": 'Template 3 Text'},
  {"temp_text": "Template 4 (Level 3)", "text": 'Template 4 Text'}
]

但是我得到的是以下结果:

[
  {"temp_text": "Template 4 (Level 3)", "text": "Template 3 Text"},
  {"temp_text": "Template 4 (Level 3)", "text": "Template 4 Text"}
]

我在哪里获得了{strong.Level 2

temp_text元素的最后一个值的a重复项

我认为问题出在我放置yield data的位置,所以我把它放在 parse_lv2 yield下面

yield scrapy.Request(url=a.css('a::attr(href)').extract_first(), callback=self.parse_lv3, dont_filter=True, meta={"data": data})

yield data

但是没有从 parse_lv3

获得数据

试图检查出问题所在,所以我从 parse_lv2 中删除了 parse_lv3 yield scrapy.Request(url=a.css('a::attr(href)').extract_first(), callback=self.parse_lv3, dont_filter=True, meta={"data": data})

yield data代替

问题解决了(没有 parse_lv3 数据),

因此,我确定问题是在循环中还是在 parse_lv3 yield中,但不知道如何解决。

1 个答案:

答案 0 :(得分:1)

问题可能是您只在data中定义了一次parse,因此parse_lv2中的每个循环将共享相同的字典data,而{{1}中的每个循环}也将共享parse_lv3,这就是为什么最后在data中有parse_lv2的最后一个循环的结果的原因。

最好在data['temp_text']循环中初始化data

parse_lv2