如何使用scrapy python从多个url中将数据收集到单个项目中

inn6fuwd  于 2022-11-09  发布在  Python
关注(0)|答案(1)|浏览(130)

简单地说,我希望从回调函数中获取返回值,直到for循环结束,然后返回一个yield项。

我想做是,

我正在创建新的链接,这些链接表示在https://www.oddsportal.com/soccer/africa/caf-champions-league/al-ahly-es-setif-GKW6I7T6/上单击选项卡,例如

  1. https://www.oddsportal.com/soccer/africa/caf-champions-league/al-ahly-es-setif-GKW6I7T6/?r=2#ah;2
    1.这是一个很好的例子,因为它是一个很好的例子。2等等。但它们基本上是同一场比赛的数据,所以我试图将下注信息收集到一个单一的时间。
    基本上,我使用一个for循环和dict来创建一个新的链接,并使用回调函数产生请求。
class CountryLinksSpider(scrapy.Spider):
    name = 'country_links'
    allowed_domains = ['oddsportal.com']
    start_urls = ['https://www.oddsportal.com/soccer/africa/caf-champions-league/es-setif-al-ahly-AsWAHRrD/']

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url=url, callback=self.create_all_tabs_links_from_url)

    def create_all_tabs_links_from_url(self, response):
        current_url = response.request.url
        _other_useful_scrape_data_dict = OrderedDict(
            [('time', '19:00'), ('day', '14'), ('month', 'May'), ('year', '22'), ('Country', 'Africa'),
             ('League', 'CAF Champions'), ('Home', 'ES Setif'), ('Away', 'Al Ahly'), ('FT1', '2'), ('FT2', '2'),
             ('FT', 'FT'), ('1H H', '1'), ('1H A', '1'), ('1HHA', 'D'), ('2H H', '1'), ('2H A', 1), ('2HHA', 'D')])

        with requests.Session() as s:
            s.headers = {
                "accept": "*/*",
                "accept-encoding": "gzip, deflate, br",
                "accept-language": "en-US,en;q=0.9,pl;q=0.8",
                "referer": 'https://www.oddsportal.com',
                "user-agent": fake_useragent.UserAgent().random
            }
            r = s.get(current_url)
            version_id = re.search(r'"versionId":(\d+)', r.text).group(1)
            sport_id = re.search(r'"sportId":(\d+)', r.text).group(1)
            xeid = re.search(r'"id":"(.*?)"', r.text).group(1)

            xhash = urllib.parse.unquote(re.search(r'"xhash":"(.*?)"', r.text).group(1))

        unix = int(round(time.time() * 1000))

        tabs_dict = {'#ah;2': ['5-2', 'AH full time', ['1', '2']], '#ah;3': ['5-3', 'AH 1st half', ['1', '2']],
                     '#ah;4': ['5-4', 'AH 2nd half', ['1', '2']], '#dnb;2': ['6-2', 'DNB full_time', ['1', '2']]}
        all_tabs_data = OrderedDict()
        all_tabs_data = all_tabs_data | _other_useful_scrape_data_dict

        for key, value in tabs_dict.items():
            api_url = f'https://fb.oddsportal.com/feed/match/{version_id}-{sport_id}-{xeid}-{value[0]}-{xhash}.dat?_={unix}'

            # goto each main tabs and get data from it and yield here
            single_tab_scrape_data = yield scrapy.http.Request(api_url,
                                                        callback=self.scrape_single_tab)
        # following i want to do (collect all the data from all tabs into single item)
        # all_tabs_data = all_tabs_data | single_tab_scrape_data # (as a dict)

    # yield all_tabs_data  # yield single dict with scrape data from all the tabs

    def scrape_single_tab(self, response):
        # sample scraped data from the response
        scrape_dict = OrderedDict([('AH full time -0.25 closing 2', 1.59), ('AH full time -0.25 closing 1', 2.3),
                                   ('AH full time -0.25 opening 2', 1.69), ('AH full time -0.25 opening 1', 2.12),
                                   ('AH full time -0.50 opening 1', ''), ('AH full time -0.50 opening 2', '')])

        yield scrape_dict

**我所尝试的,**首先,我尝试从scrape_match_data函数简单返回scrape项,但我无法找到从yield请求获取回调函数返回值的方法。

我已经尝试使用以下库,从inline_requests导入inline_requests从twisted.internet延迟导入inlineCallbacks
但我不能让它工作。我觉得必须有更简单的方法来附加刮项目从不同的链接到一个项目,并产生它。
请帮我解决这个问题。

ar5n3qh5

ar5n3qh51#

从技术上讲,在Scrray中,我们有两种方法在回调函数之间传输数据,我们使用回调函数从多个请求中构造项目:

1.请求 meta字典:

def parse(self, response):
    ...
    yield Request(
        url,
        callback=self.parse_details,
        meta = {'scraped_item_data': data})

def parse_details(self, response):
    scraped_data = response.meta.get('scraped_item_data') # <- not present in Your code
    ...

可能您没有调用response.meta.get('_scrape_dict')来访问从上一个回调函数中抓取的数据

**2. cb_kwargs**可用于Scrapy 1.7及更新版本:

def parse(self, response):
    ...
    yield Request(
        url,
        callback=self.parse_details,
        cb_kwargs={'scraped_item_data': data})

def parse_details(self, response, scraped_item_data):  # <- already accessible data from previous request
    ...

3.同一类型的多个..响应中的单个项目。

最简单的实现方法是将数据赋给类变量。代码如下所示:

def parse(self, response):
    self.tabs_data = []
    ...
    self.tabs_number = len(tabs) #  or len(list(tabs)) # <number of tabs
    for tab in tabs:
        yield Request(...

def parse_details(self, response)
    scraped_tab_data = ...
    self.tabs_data.append(scraped_tab_data)
    if len(self.tabs_data) == self.tabs_number: # when data from all tabs collected
        # compose one big item
        ...
        yield item

相关问题