Ad

Crawler Update Data To An Array, Yield Inside A Loop

- 1 answer

I want to continuous crawl and update an array value using loop because I need to click some button to get next value on array. However it seem yield inside loop works as parallel thread and the item was yield many time. What I want is go through the loop, update data and yield item only one time. example: current output:

{'field1': 'data1',
 'filed2' : 'data2',
 'field3' : ['data31']}

{'field1': 'data1',
 'filed2' : 'data2',
 'field3' : ['data32']}

{'field1': 'data1',
 'filed2' : 'data2',
 'field3' : ['data33']}

expected:

{'field1': 'data1',
 'filed2' : 'data2',
 'field3' : ['data31', 'data32', 'data3']}

Here is my code

def parse_individual_listings(self, response):
     ...
     data = {}
     data[field1] = 'data1'
     data[field1] = 'data2'
     ...
     for i in range(3):
         yield scrapy.Request(
                urlparse.urljoin(response.url, link['href']), #different link
                callback=self.parse_individual_tabs,
                meta={'data': data, 'n':i};
         )
def parse_individual_tabs(self, response):
     data = response.meta['data']
     i = response.meta['i']
     ...
     # keep populating `data`
     data[field3][i] = "data3[i]"  #this value change when I click a button to update
     yield data
Ad

Answer

Try to use inline_requests library (https://pypi.org/project/scrapy-inline-requests/). It let's you to make requests inside the same function. It is useful to collect data to one object instead of yielding different. Check this example with some pseudocode:

from inline_requests import inline_requests
from scrapy import Selector

@inline_requests
def parse_individual_listings(self, response):
    ...
    data = {}
    data[field1] = 'data1'
    data[field1] = 'data2'
     ...
    for i in range(3):
        extra_req = yield scrapy.Request(
            response.urljoin(link['href']), #different link
        )
        # apply your logics here, say extract some data
        sel = Selector(text=extra_req.text)
        data['field3'].append(sel.css('some css selector').get())
    yield data
Ad
source: stackoverflow.com
Ad