Загрузчик скребковых элементов неправильно выдает результат обратного вызова

#python #web-scraping #scrapy

Вопрос:

Я впервые пытаюсь использовать загрузчики для мусора. Я собираю детали для спортивного турнира. Он начинается с национальных команд, затем переходит к статистике национальных команд, затем к списку составов национальных сборных и, наконец, к отдельным игрокам в команде. У меня есть четыре элемента (TeamItem, TeamStatsItem, SquadListItem и PlayerDetailsItem). Каждый элемент-это отдельная страница, поэтому я использовал передачу cb_kwargs как часть запроса.

Все работает, пока я не дойду до последней части. При анализе списка команд мне нужно перейти на другую страницу для получения дополнительной информации о каждом игроке. Как я могу заставить его выдавать player_club и другие поля, которые я добавлю (часть элемента PlayerDetailsItem), чтобы они были связаны с другими элементами squad_loader (и более высокими запросами)? Например, у каждого имени игрока в списке национальных команд есть один клуб игроков. На самом высоком уровне должно быть только 24 команды со всем, что в них есть, и PlayerDetails-это последний уровень анализа, который я планирую использовать. Я хотел бы предоставить список команд только после посещения всех списков игроков и добавления этих данных в соответствующий состав. В настоящее время данные player_detail либо не отображаются, либо добавляются на верхнем уровне (создавая сотни записей вместо 24) в json. Весь код xpath верен. Я попытался настроить код parse_player и parse_squad_list с помощью различных комбинаций операторов yield и add_value. Я потратил часы, пытаясь разобраться в этом, читая отрывочную документацию и ища рекомендации в Интернете, поэтому буду признателен за любую помощь.

Items.py

класс TeamItem(лоскутный.Пункт):

 # various fields
team_stats = scrapy.Field()
squad_list = scrapy.Field()
 

класс TeamStatsItem(scrapy.Пункт):

 # various fields for statistics    
 

класс эскадрильи(лоскутный.Пункт):

 player_name = scrapy.Field(input_processor=MapCompose(remove_whitespace))
player_url = scrapy.Field()
player_group = scrapy.Field(input_processor=MapCompose(remove_whitespace))
player_details = scrapy.Field()
 

класс PlayerDetailsItem(лоскутный.Пункт):

 player_club =  scrapy.Field()
# more fields to be added to PlayerDetails, but I wanted to debug it first
 

spider.py (выбранный код)

def parse_player(сам, ответ, загрузчик команды):

     player_loader = ItemLoader(item=PlayerDetailsItem(), selector=response)
    player_profile = response.xpath('.//div[contains(@class, "player-header__profile")]')
    player_loader.add_value('player_club', player_profile.xpath('.//span[text()="Club"]/following-sibling::span/text()').get())

    squad_loader.add_value('player_details', player_loader.load_item())

    yield squad_loader.load_item()
 

def parse_squad_list(self, ответ, team_loader):

 player_groups = response.css('div.squad--team-wrap')[:-2] # drop the last 2
squad_loader = ItemLoader(item=SquadListItem(), selector=player_groups)

for group in player_groups:
    players = group.css('a.player-name')
    for player in players:
        player_name = player.css('a::attr(title)').get()
        squad_loader.add_value('player_name', player.css('a::attr(title)').get())
        player_url = BASE_URL   player.css('a::attr(href)').get()
        squad_loader.add_value('player_url', player_url)
        squad_loader.add_value('player_image_url', player.xpath('preceding-sibling::*/img[@data-srcset]/@data-srcset').get())
        squad_loader.add_value('player_group', group.css('h5::text').get())
        request = scrapy.Request(player_url, 
            callback=self.parse_player,
            dont_filter=True,
            cb_kwargs={'squad_loader' : squad_loader}
            )

        yield request

team_loader.add_value('squad_list', squad_loader.load_item())

yield team_loader.load_item()