Scrapy - Как я могу вернуть данные в основной метод анализа из полученного запроса? - PullRequest
0 голосов
/ 30 апреля 2020

Так что я застрял на этом пару дней. Я анализирую объект JSON, который содержит некоторую информацию. В этом объекте есть список, содержащий n номеров контактов. У каждого из них есть идентификатор, который можно использовать для создания URL. В этом URL есть номер телефона для этого контакта.

Итак, я хочу начать создавать элемент, добавить некоторую информацию, затем l oop через контакты, и для каждого l oop я хочу добавить к этому исходному элементу номер телефона, найденный в URL. .

Моя проблема: как вернуть набранный номер телефона и добавить его в элемент? Если я заканчиваю основной метод синтаксического анализа с помощью «yield items», к элементу не добавляются никакие данные, собранные в l oop. Но если я вместо этого заканчиваю parseContact с помощью "yield items", весь элемент дублируется для каждого l oop.

Пожалуйста, помогите, у меня скоро произойдет сбой: D

Вот код:

def parse(self, response):

        items = projectItem()
        rData = response.xpath('//*[@id="data"]/text()').get()
        dData = json.loads(rData)
        listOfContacts = dData["contacts"]
        Data = dData["customer"]

        items['customername'] = Data["companyName"]
        items['vatnumber'] = Data["vatNo"]
        items['contacts'] = []


        i=0
        for p in listOfContacts:
            id = json.dumps(p["key"])
            pid = id.replace("\"","")
            urlP = urljoin("https://example.com/?contactid=", pid)
            items['contacts'].append({"pid":pid,"name":p["name"]})

            yield scrapy.Request(urlP, callback=self.parseContact,dont_filter=True,cb_kwargs={'items':items},meta={"counter":i})
            i +=1
        #IF I YIELD HERE, NONE OF THE DATA IN THE LOOP GETS SAVED    
        yield items 




    def parseContact(self, response,items):
        i = response.meta['counter']

        data = response.xpath('//*[@id="contactData"]/script/text()').get()
        items['contacts'][i].update({"data":data})
        #IF I YIELD HERE THE ITEM iS DUPLICATED N TIMES
        yield items

1 Ответ

0 голосов
/ 30 апреля 2020

Если вы хотите 1 предмет на компанию, вам нужно полностью создать предмет перед тем, как получить его. Я бы сделал это так:

import json
import scrapy
from urllib.parse import urljoin

def parse(self, response):
    items = projectItem()
    rData = response.xpath('//*[@id="data"]/text()').get()
    dData = json.loads(rData)
    listOfContacts = dData["contacts"]
    Data = dData["customer"]
    items['contacts'] = []

    items['customername'] = Data["companyName"]
    items['vatnumber'] = Data["vatNo"]
    contacts_info = []
    # prepare list with the contact urls, pid & name
    for p in listOfContacts:
        id = json.dumps(p["key"])
        pid = id.replace("\"", "")
        urlP = urljoin("https://example.com/?contactid=", pid)
        contacts_info.append((urlP, pid, p["name"]))
    # get the first item from the list, and pass the rest of the list along in the meta
    urlP, pid, name = contacts_info.pop()
    yield scrapy.Request(urlP,
                         callback=self.parseContact,
                         dont_filter=True,
                         meta={"contacts_info": contacts_info,
                               "items": items})

def parseContact(self, response, items):
    contacts_info = response.meta['contacts_info']
    # get count from meta, or default to 0
    count = response.meta.count('count', 0)
    count += 1
    items = response.meta['items']
    data = response.xpath('//*[@id="contactData"]/script/text()').get()
    items['contacts'][count].update({"data": data})
    try:
        urlP, pid, name = contacts_info.pop()
    except IndexError:
        # list contacts info is empty, so the item is finished and can be yielded
        yield items
    else:
        yield scrapy.Request(urlP,
                             callback=self.parseContact,
                             dont_filter=True,
                             meta={"contacts_info": contacts_info,
                                   "items": items,
                                   "count": count})

Я не уверен, что связь между pid и counter (поэтому часть о добавлении pid & name должна быть добавлена ​​в код), но я надеюсь, вы поняли идею здесь.

...