#python #html #xpath #web-scraping #lxml
#python #HTML #xpath #очистка веб-страниц #lxml
Вопрос:
В python с использованием библиотеки lxml как мне прочитать значения td в html-таблицах? Я попытался прочитать таблицу xpath, но не могу найти правильный параметр для возврата значений td. Спасибо всем, я ценю это.
import sys
from glob import *
from lxml import etree, html
import requests
#Scan directory (current) and scrape the html files
dirScan = glob('html/*.*')
fileCount = 0
while(fileCount < len(dirScan)):
fileName = dirScan[fileCount]
page = open(fileName)
tree = html.fromstring(page.read())
tables = tree.xpath('//table')
print("Tables:",tables)
page.html
<table style="width:100%">
<tr align="right"><td>1</td><td>John</td><td>Smith</td>
<tr align="right"><td>2</td><td>Tody</td><td>Miller</td>
</table>
Комментарии:
1. Вы знаете, как использовать xpath?
2. Не совсем, и я не могу найти никакой хорошей документации по этому поводу. Я пытаюсь получить все значения td, которые находятся после tr align = «right», но я не могу получить правильный синтаксис.
3.w3schools.com/xml/xpath_intro.asp
xpath("//table/tr[@align='right']/td")
4. @PadraicCunningham Спасибо. Как мне преобразовать это в строковые значения. Он отображается в виде списка элементов следующим образом…..=> [0]:< Элемент td в 0x7fee11ab2958> [1]: <Элемент td в 0x7fee11ac68b8> [2]: <Элемент td в 0x7fee11ac6908> [3]: <Элемент td в 0x7fee11ac6958>
5. Просто используйте
xpath("//table/tr[@align='right']/td/text()")
для извлечения текста
Ответ №1:
Если вы хотите найти td внутри tr с выравниванием по правому краю, вам нужен фильтр ti с использованием атрибута align:
tds = tree.xpath("//table/tr[@align='right']/td")
Если вам просто нужен текст из каждого td:
.xpath("//table/tr[@align='right']/td/text()")
Но на самом деле вы, вероятно, хотите сохранить ассоциацию, поэтому вам следует просто найти trs, а затем сгруппировать текст td:
x = """<table style="width:100%">
<tr align="right"><td>1</td><td>John</td><td>Smith</td>
<tr align="right"><td>2</td><td>Tody</td><td>Miller</td>
</table> """
from lxml import html
tree = html.fromstring(x)
# first get the trs, filtering by attribute
trs = tree.xpath("//table/tr[@align='right']")
# then extract the tds from each tr
data = [row.xpath("td/text()") for row in trs]
Что дало бы вам:
[['1', 'John', 'Smith'], ['2', 'Tody', 'Miller']]
И если бы вы просто хотели каждое имя, вы могли бы пропустить первый td:
trs = tree.xpath("//table/tr[@align='right']")
# position() > 1, all but the first td, xpath has one based indexing.
names = [row.xpath("td[position()> 1]/text()") for row in trs])
Или объединение в одну строку:
full_names [" ".join(row.xpath("td[position()> 1]/text()")) for row in trs]
Комментарии:
1. Вы издеваетесь надо мной, вы изменили ответ на основе его комментария 😡
2. @HishamKaram, я изменил какой ответ? Также правильный способ просто получить текст из td — это не
//text()
, он будет извлекать текст рекурсивно, и, как указано в моем ответе, он потеряет какую-либо связь, просто собрав весь текст в один плоский список.3. я имею в виду, что он изменил ответ и отредактировал вопрос всего за 2 часа, достаточно ли это справедливо?
4. @HishamKaram, игнорируя любое редактирование,
//text()
неверно и дажеtree.xpath('//tr/td/text()')
, как я уже прокомментировал, дает вам список строк, которые не содержат ассоциаций.5. @PadraicCunningham Есть ли способ, с помощью которого я могу захватить первые 10 элементов списка td, или мне нужно просмотреть все элементы?
Ответ №2:
код
>>> page="""<table style="width:100%">
<tr>
<th>Id</th>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>1</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>2</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>3</td>
<td>Miller</td>
<td>43</td>
</tr>
</table> """
>>> tree=html.fromstring(s)
>>> tree.xpath('//tr/td//text()')
вывод:
['1', 'Smith', '50', '2', 'Jackson', '94', '3', 'Miller', '43']
Комментарии:
1. Привет, в моем списке много n и другого мусора. Это потому, что таблица, которую я очищаю, имеет атрибуты стиля.
2. Каким был бы синтаксис для чтения всех значений tr align=»right»?