Зачистка элементов с изменением xpath под тем же классом - PullRequest
0 голосов
/ 20 января 2019

Я пытаюсь очистить элементы "li", которые изменят свой xpath в зависимости от того, сколько элементов "li" будет добавлено. Я не знаю, как описать это лучше, поэтому я перейду к примеру, чтобы сделать его более понятным.

Скажем, речь идет о сборе данных о футболе. Структура сайта выглядит следующим образом:

<ul class="stats">
    <p class="results">Man of The Match</p>
    <li>Player12
        <span>1 man of the match</span>
    </li>    
    <p class="results">Goals</p>
    <li>Player1 
        <span>2 goal(s)</span>
    </li>
    <p class="results">Assists</p>
    <p class="results">Yellow Cards</p>
    <li>Player2                                             
    <span>1 yellow card(s)</span>
    </li>
    <p class="results">Red Cards</p>
</ul>

Как видите, элементы p и li не "отображаются" друг на друга. Они независимы, хотя заголовок и содержание. Легко очистить «Человек матча», потому что элемент для очистки всегда будет «ul / li [1] / span / text ()», а в матче только один человек. Но сейчас возникает проблема. Поскольку голы, голевые передачи и т. Д. Не имеют собственного класса и не перечислены в списке «p», может случиться так, что будет больше игроков, которые забили, получили карты и т. Д. Так, в одном примере li [3] - игрок, который забил гол. В другом примере (когда целей нет), li [3] может быть желтой карточкой.

Давайте посмотрим на другой пример:

<ul class="stats">
    <p class="results">Man of The Match</p>
    <li>Player12
        <span>1 man of the match</span>
    </li>    
    <p class="results">Goals</p>
    <li>Player1 
    <span>2 goal(s)</span>
    </li>
    <li>Player2 
    <span>3 goal(s)</span>
    </li>
    <p class="results">Assists</p>
    <p class="results">Yellow Cards</p>
    <li>Player2                                             
    <span>1 yellow card(s)</span>
    </li>
    <li>Player13 
    <span>3 goal(s)</span>
    </li>  
    <p class="results">Red Cards</p>
</ul>

Так что в приведенном выше примере у нас будет разный xpath для всех li-элементов.

Как мне написать свой код, чтобы сообщить scrapy, какой «li» -элемент принадлежит голам, ассистам, желтым карточкам и т. Д., Поскольку структура сайта не совсем понятна?

Я пытался:

'player_stats' = extract_with_xpath('ul[@class="stats"]/p/li/text()')

, который дает мне все элементы li, но не промежутки. Конечно, я мог бы добавить span в конце, но я не смогу сопоставить его с элементом записи (потому что li всегда меняются). Но на самом деле я хотел бы иметь предметы цели, голевые передачи, желтые карточки и т. Д.

По сути, я хочу знать, как сопоставить элементы одним и тем же элементам, которые изменят свой путь в зависимости от количества добавленных элементов (в данном случае цели, голевые передачи и т. Д.). Я надеюсь, что смогу прояснить мою проблему, так как английский не мой родной язык, я прошу прощения за возможное плохое описание Заранее спасибо, помощь очень ценится.

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Вы можете использовать XPath 'preceding-sibling, чтобы найти элементы li, которым предшествует определенный ключ:

stats = response.css('.stats')
for key in stats.css('p::text').getall():
    for li in stats.xpath('./li[./preceding-sibling::p[1][contains(text(), "{}")]]'.format(key)):
        player = li.xpath('./text()').get()
        value = li.css('span::text').get()
0 голосов
/ 20 января 2019

Эта строка: response.css("ul.stats p, ul.stats li")
возвращает список селекторов тегов p и ul в том же порядке, что и в ответе.После этого вам нужно отдельно обрабатывать каждый тип узлов.

player_data = {}
categoty = ""
for node in response.css("ul.stats p, ul.stats li"):  #returs list of p and li tags selectors in the same order as in response
    if '<p class="results"' in node.extract():
        category = node.css("::text").extract_first()
    if '<li>' in node.extract():
        player = node.css("::text").extract_first().strip()
        if player not in player_data.keys():
            player_data[player]={}
        player_data[player][category]=node.css("span::text").extract_first().strip()


print(player_data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...