Xpath не возвращает содержимое ‹table› в ‹a› (проблема не в tbody)

В следующем коде используется scrapy + scrapy-splash + Python. Я пытаюсь извлечь предстоящие матчи (в том числе: названия команд, название турнира, время начала) с этого сайта: https://www.hltv.org/matches

Мой код в функции обратного вызова 'parse':

    match_days = response.xpath("//div[@class = 'upcoming-matches']//div[@class = 'match-day']")
    for match in match_days.xpath("./a"):
        print(match.extract()) 
        # tournament_name = match.xpath(".//td[@class='event']//span[@class='event-name']/text()").extract_first()
        # team1_name = match.xpath(".//td[@class='team-cell'][1]//div[@class='team']/text()").extract_first()

Предполагается, что я получу содержимое для каждого элемента "‹ a >" (т.е. должно выглядеть примерно так, например:

<a href="/matches/2318355/dkiss-vs-psychoactive-prowince-winner-winner-of-the-future-2017" class="a-reset block upcoming-match standard-box" data-zonedgrouping-entry-unix="1514028600000">
   <table class="table">
      <tbody>
         <tr>
            <td class="time">
               <div class="time" data-time-format="HH:mm" data-unix="1514028600000">12:30</div>
            </td>
            <td class="team-cell">
               <div class="line-align">
                  <img alt="DKISS" src="https://static.hltv.org/images/team/logo/8657" class="logo" title="DKISS">
                  <div class="team">DKISS</div>
               </div>
            </td>
            <td class="vs">vs</td>
            <td class="team-cell">
               <div class="team">PSYCHOACTIVE/proWince winner</div>
            </td>
            <td class="event"><img alt="Winner of the Future 2017" src="https://static.hltv.org/images/eventLogos/3464.png" class="event-logo" title="Winner of the Future 2017"><span class="event-name">Winner of the Future 2017</span></td>
            <td class="star-cell">
               <div class="map-text">bo3</div>
            </td>
         </tr>
      </tbody>
   </table>
</a>

Но я получаю это только для каждого "‹ a >":

<a href="/matches/2318355/dkiss-vs-psychoactive-prowince-winner-winner-of-the-future-2017" class="a-reset block upcoming-match standard-box" data-zonedgrouping-entry-unix="1514028600000">
</a>

Я пробовал это в оболочке scrapy и тот же результат.

Я пробовал инструменты Chrome Developer и вижу все содержимое для каждого "‹ a >" в свойстве innerHTML.

Я не думаю, что проблема связана с «‹ tbody >», так как я понял, что в некоторых случаях он опускается и добавляется веб-браузерами, потому что, когда я распечатываю html-содержимое возвращаемой страницы из «ответа» "‹ tbody >" есть (кстати, я использую lua-скрипт через scrapy-splash, чтобы сделать POST-запрос к URL-адресу и получить html-страницу)

Кто-нибудь знает, почему это происходит? Я потратил последние пару дней на это без ответа, и у меня нет никаких идей о том, что еще проверить, чтобы понять, почему это происходит, когда этого не должно быть.

Спасибо.


person Vasko    schedule 22.12.2017    source источник


Ответы (1)


С селектором css мне было проще.

import scrapy

class MySpider(scrapy.Spider):

    name = 'myspider'

    start_urls = ['https://www.hltv.org/matches']

    def parse(self, response):
        print('url:', response.url)

        days = response.css('.match-day')

        for day in days:

            date = day.css('.standard-headline::text').extract_first()
            print('date:', date)

            tables = day.css('table')

            for table in tables:

                time = table.css('div.time::text').extract_first()
                teams = table.css('.team::text').extract()
                event = table.css('.event-name::text').extract_first()
                placeholder = table.css('.placeholder-text-cell::text').extract_first()

                print('  time:', time)
                if teams:
                    print('    teams 1:', teams[0])
                    print('    teams 2:', teams[1])
                    print('    event:', event)
                else:
                    print('    placeholder:', placeholder)

# --- it runs without project and saves in `output.csv` ---

from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0',
    # save in file as CSV, JSON or XML
    'FEED_FORMAT': 'csv',     # csv, json, xml
    'FEED_URI': 'output.csv', # 
})
c.crawl(MySpider)
c.start()

Результат

url: https://www.hltv.org/matches

date: 2017-12-24
  time: 03:00
    teams 1: NSPR
    teams 2: MiTH
    event: WESG 2017 Thailand LAN
  time: 06:00
    teams 1: Signature
    teams 2: Beyond
    event: WESG 2017 Thailand LAN
  time: 09:00
    placeholder: WESG Thailand - Grand Final
  time: 10:00
    teams 1: DKISS
    teams 2: Izako Boars
    event: Winner of the Future 2017
date: 2017-12-26
  time: 14:00
    teams 1: Recca
    teams 2: Signature
    event: GOTV.GG Invitational #1
  time: 17:00
    teams 1: AGO
    teams 2: Vega Squadron
    event: LOOT.BET Cup 2
  time: 20:00
    teams 1: mousesports
    teams 2: Spirit
    event: LOOT.BET Cup 2
date: 2017-12-27
  time: 12:00
    teams 1: Singularity
    teams 2: GoodJob
    event: CSesport.com XMAS Cup
  time: 13:00
    placeholder: GOTV.GG - Semi-Final #1
  time: 15:00
    placeholder: GOTV.GG - Semi-Final #2
  time: 15:00
    teams 1: MANS NOT HOT
    teams 2: VenatoreS
    event: CSesport.com XMAS Cup
  time: 17:00
    teams 1: Heroic
    teams 2: Valiance
    event: LOOT.BET Cup 2
date: 2017-12-28
  time: 13:00
    placeholder: GOTV.GG - 3rd place decider
  time: 15:00
    placeholder: GOTV.GG - Grand Final
person furas    schedule 24.12.2017
comment
Извините за поздний ответ. Да, это работает отлично, я переписал его с помощью Xpath вместо css, и это сработало отлично. Но я до сих пор не понимаю, почему вам нужно перебирать элемент «таблица» и не может сделать то же самое с элементом «а» (т.е. изменение таблиц = день.css('таблица') на таблицы = день.css ('a') вернет None для всех переменных, которые вы печатаете в результате). - person Vasko; 29.12.2017
comment
когда я проверяю исходный код в браузере, я вижу table внутри a, поэтому он должен дать тот же результат. Но когда я проверяю print(day.extract()), то вижу, что a пусто, а table находится не внутри a, а после a. Почему-то scrapy видят этот код по-другому. Возможно, страница отправляет другой HTML-код, если некоторые параметры (заголовки, файлы cookie) не заполнены, или, возможно, HTML-код построен неправильно, и браузер интерпретирует его иначе, чем scrapy. - person furas; 29.12.2017