Почему я получаю пустой массив в python с использованием xpath lxml

#python #web-scraping

#python #очистка веб-страниц

Вопрос:

Я хочу очистить эту страницу:https://www.leagueofgraphs.com/summoner/na/samrick41#championsData-soloqueue чтобы получить определенное значение winrate для роли.

 import requests
from lxml import html

url = 'https://www.leagueofgraphs.com/summoner/na/samrick41#championsData-soloqueue'
headers = {my headers here}
page = requests.get(url, headers=headers)
contents = page.content

tree = html.fromstring(contents)

print (tree.xpath('//*[@id="profileRoles"]/div[2]/div[2]/table/tbody/tr[2]/td[3]/a/progressbar/div[2]/text()'))
  

[]

В ответ я получаю пустой массив. Я думаю, мне нужно удалить «tbody», потому что, по крайней мере, я получаю элемент до узла «progressbar», не уверен, почему. Но почему я не могу получить оттуда процентное значение с последним «div [2]». Я уверен, что есть другие способы получить значение, которое я ищу, но я чувствую, что это должно сработать, поэтому я здесь чего-то не понимаю, если кто-нибудь может просветить меня, спасибо.

Комментарии:

1. Я удалил данные «headers», чтобы я мог опубликовать здесь, просто к вашему сведению.

Ответ №1:

Вы получаете правильный ответ, но нужный вам HTML-код на самом деле загружен через javascript. Вы можете увидеть это, когда отключите javascript в браузере, у вас не будет дочернего элемента progressbar в html.

В Chrome вы можете легко отключить javascript, просмотрев страницу, в правой части которой есть три точки -> дополнительные инструменты -> настройки -> Прокрутите вниз до debugger. Фактически, я всегда делаю это перед попыткой какой-либо очистки, часто DOM управляется javascript, если на веб-сайте есть какая-либо функциональность.

Вы не получаете красивого аккуратного изображения с числами. Сказав это, нужная вам информация фактически находится в атрибуте progressbar data-value .

 import requests
from lxml import html

url = 'https://www.leagueofgraphs.com/summoner/na/samrick41#championsData-soloqueue'

headers = {
    'Connection': 'keep-alive',
    'Cache-Control': 'max-age=0',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36',
    'Accept': 'text/html,application/xhtml xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-User': '?1',
    'Sec-Fetch-Dest': 'document',
    'Accept-Language': 'en-US,en;q=0.9',
}
page = requests.get(url, headers=headers)
contents = page.content

tree = html.fromstring(contents)

for a in tree.xpath('//td[3]/a/progressbar'):
    winrate = a.get('data-value')
    print('Winrate: ',round(float(winrate)*100,1),'%')
  

Вывод

 Winrate:  52.0 %
Winrate:  45.5 %
Winrate:  37.5 %
Winrate:  100.0 %
Winrate:  0.0 %
Winrate:  0.0 %
Winrate:  0.0 %
...
  

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

Значения выводятся как значения 2dp, поэтому возникла необходимость преобразовать это в%, функцию round (), которую я использую для округления до одного десятичного знака, мы должны преобразовать строку, которую мы получаем из селектора xpath, в значение с плавающей точкой, чтобы манипулировать ею.