#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()