Очистка нескольких страниц в цикле дает дублированные результаты на 3-м уровне - PullRequest
0 голосов
/ 25 июня 2018

В моих следующих шаблонах HTML:


Уровень 1 (Template_1)

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

Уровень 2 (Template_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"}
]

Где я получу temp_text, дублированный с последним значением элементов a в Уровень 2

Я думал, что проблема в том, где я разместил свой 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_lv3 и yield scrapy.Request(url=a.css('a::attr(href)').extract_first(), callback=self.parse_lv3, dont_filter=True, meta={"data": data}) из parse_lv2 ,

с заменой на yield data,

И проблема решена (без parse_lv3 data),

Итак, яуверен, что проблема этоr в цикле или parse_lv3 yield, но не могу понять, как решить эту проблему.

1 Ответ

0 голосов
/ 26 июня 2018

Проблема, вероятно, заключается в том, что вы определяете data только один раз в parse, поэтому каждый цикл в parse_lv2 будет иметь одинаковый dict data, а каждый цикл в parse_lv3 будет также иметь data, поэтомув конце у вас есть результат последнего цикла parse_lv2 в data['temp_text'].

Вам лучше инициализировать data в цикле parse_lv2, как этот

def parse(self, response):
    yield scrapy.Request(url=response.css('a::attr(href)').extract_first(), callback=self.parse_lv2, dont_filter=True)


def parse_lv2(self, response):
    for a in response.css('a'):
        data = dict()
        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})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...