lxml xpath не может отобразить элементы HTML

1

Я пытаюсь использовать lxml для анализа веб-страницы ниже. Но что-то кажется неправильным с моим xpath. Я не уверен, что я делаю неправильно.

web_content = requests.get(r"https://www.quandl.com/data/TSE").content
dataset_count = html.fromstring(web_content)
print(dataset_count.xpath(r'//*[@id="ember667"]/div[2]/main/section/section/section[2]/div[3]/div[2]/span[2]'))

Я пытаюсь вернуть это число набора данных 3908. Но этот xpath, похоже, не работает для меня. Любые мысли?

Кроме того, я надеюсь, что, если я передам другую ссылку quandl через запросы, я могу использовать один и тот же путь xpath для извлечения номера набора данных. Возможно ли это?

  • 0
    3908 самом деле не является частью исходного кода HTML, который вы получаете этим методом.
  • 0
    Какие еще методы я могу использовать, чтобы получить его тогда?
Теги:
xpath
lxml

2 ответа

1
Лучший ответ

Кажется, что число наборов данных также находится в элементе <noscript>:

<div class='centered' id='main' role='main'>
<div id='content'>
<noscript>
<table>
<tbody>
<tr>
<td>Database Name</td>
<td>Tokyo Stock Exchange</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td>Datasets</td>
<td>3908</td>
</tr>
<tr>
<td>Downloads</td>
<td>4067259</td>
</tr>
<tr>
...

Итак, вы можете захватить это, используя что-то вроде этого:

>>> import requests
>>> import lxml.html

>>> r = requests.get('https://www.quandl.com/data/TSE')
>>> h = lxml.html.fromstring(r.text)
>>> h
<Element html at 0x7ffb5f6ed0a8>

>>> h.xpath('//noscript')
[<Element noscript at 0x7ffb5c16ac58>, <Element noscript at 0x7ffb5c16ac00>]

>>> h.xpath('string(//noscript//tr[td[1]="Datasets"]/td[2])')
'3908'
>>> h.xpath('string(//div[@id="content"]//noscript//tr[td[1]="Datasets"]/td[2])')
'3908'
>>> h.xpath('number(//div[@id="content"]//noscript//tr[td[1]="Datasets"]/td[2])')
3908.0

Объяснение в XPath по запросу OP:

//div[@id="content"]          <-- look for a <div> element with "id" attribute equal to "content"
  //noscript                  <-- look for a <noscript> descendant
    //tr[                     <-- look for a <tr> descendant...
        td[1]="Datasets"      <-- ... which 1st <td> child string value is "Datasets"...
                              (this is true if the <td> contains only 1 text node "Datasets"
        ]
      /td[2]                  <-- select the 2nd <td> of previous matching <tr> rows
  • 0
    Благодарю. Было интересно , если вы могли бы дать краткое объяснение о tr td код , который вы написали? если это не слишком много проблем?
  • 1
    @jakewong, я добавил объяснение частей выражения XPath.
Показать ещё 1 комментарий
0

В ответе нет числа 3908, которое requests получает, поскольку число загружается динамически с помощью дополнительного запроса.

Один из вариантов решения этой проблемы - использовать реальный браузер и управлять им с помощью selenium. Вот пример рабочего кода, который использует PhantomJS браузер без браузера:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


driver = webdriver.PhantomJS()
driver.get("https://www.quandl.com/data/TSE")

wait = WebDriverWait(driver, 10)
elm = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".database-statistics .column:nth-child(2) span:nth-child(2)")))
print(elm.text)

driver.close()

Печать 3,908.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню