Я использую Python и Selenium для очистки данных со страницы HTML. Я выбираю элемент <ul>
, который имеет несколько дочерних элементов <li>
, которые содержат данные, которые я хочу. Но когда итерация по List[WebElement]
и составление dict основаны на .text
значении <div>
s путем запроса элемента с .find_element_by_xpath()
, я получаю только значение .text
первого div
.
Я удалил код python и код HTML, насколько смог:
<html>
<head>
</head>
<body>
<ul id="listUl">
<li id="item1">
<div>
<div class="content">
<div class="titel">
<div class="item_titel">Hello World</div>
</div>
<div class="key">
<div class="item_key">HELLO_WORLD</div>
</div>
</div>
</div>
</li>
<li id="item2">
<div>
<div class="content">
<div class="titel">
<div class="item_titel">Merry Christmas</div>
</div>
<div class="key">
<div class="item_key">MERRY_CHRISTMAS</div>
</div>
</div>
<div>
</li>
</ul>
</body>
from typing import List
from selenium import webdriver
from selenium.webdriver.remote.webelement import WebElement
path: str = "file:///C:/Users/<username>/Desktop/main3.html"
list_block = "//ul[@id='listUl']"
list_elements = "//li"
driver = webdriver.Firefox()
driver.get(path)
def get_data(list_item: WebElement) -> dict:
return {
'id': list_item.find_element_by_xpath("//div[@class='item_key']").text,
'titel': list_item.find_element_by_xpath("//div[@class='item_titel']").text
}
block_we: WebElement = driver.find_element_by_xpath(list_block)
result: List[dict] = []
block: WebElement = block_we
li_list: List[WebElement] = block.find_elements_by_xpath(list_elements)
for item in li_list:
result.append(get_data(item))
print(result) #[{'id': 'HELLO_WORLD', 'titel': 'Hello World'}, {'id': 'HELLO_WORLD', 'titel': 'Hello World'}]
Я нашел это ТАК сообщение: Заполнение словаря python для l oop возвращает те же значения , поэтому я подумал, что Мэйби не хватает, чтобы создать новый dict, и первая запись всегда используется повторно. поэтому я сделал отдельную переменную для каждой записи:
item1 = { # item1: {'id': 'HELLO_WORLD', 'titel': 'Hello World'}
'id': li_list[0].find_element_by_xpath("//div[@class='item_key']").text,
'titel': li_list[0].find_element_by_xpath("//div[@class='item_titel']").text
}
item1_text = li_list[0].text #item1_text: 'Hello World\nHELLO_WORLD'
item2 = { # item2: {'id': 'HELLO_WORLD', 'titel': 'Hello World'}
'id': li_list[1].find_element_by_xpath("//div[@class='item_key']").text,
'titel': li_list[1].find_element_by_xpath("//div[@class='item_titel']").text
}
item2_text = li_list[1].text # item2_text: 'Merry Christmas\nMERRY_CHRISTMAS
Может кто-нибудь сказать мне, какую ошибку я делаю?
РЕДАКТИРОВАТЬ: Чтобы убедиться, что Xpath не ошибается, я изменил относительные //div[@class='item_key']
и //div[@class='item_titel']
к абсолютным значениям //div/div/div[1]/div
и //div/div/div[2]/div
и добавление свойства html к результату get_data
:
def get_data(list_item: WebElement) -> dict:
return {
'id': list_item.find_element_by_xpath("//div/div/div[1]/div").text,
# 'id': list_item.find_element_by_xpath("//div[@class='item_key']").text,
'titel': list_item.find_element_by_xpath("//div/div/div[2]/div").text,
# 'titel': list_item.find_element_by_xpath("//div[@class='item_titel']").text,
'text': list_item.text,
'html': list_item.get_attribute("innerHTML").replace('\t', '').replace('\n', '')
}
Вывод:
[
{
'id': 'Hello World',
'titel': 'HELLO_WORLD',
'text': 'Hello World\nHELLO_WORLD',
'html': '<div><div class="content"><div class="titel"><div class="item_titel">Hello World</div></div><div class="key"><div class="item_key">HELLO_WORLD</div></div></div></div>'
},
{
'id': 'Hello World',
'titel': 'HELLO_WORLD',
'text': 'Merry Christmas\nMERRY_CHRISTMAS', 'html': '<div><div class="content"><div class="titel"><div class="item_titel">Merry Christmas</div></div><div class="key"><div class="item_key">MERRY_CHRISTMAS</div></div></div></div>'
}
]
Но, тем не менее, если в моем List[WebElements]
содержится более 1 <li>
элемента, запросы через .find_element_by_xpath("//div/div/div[1]/div")
и .find_element_by_xpath("//div/div/div[2]/div")
возвращаются только для элемента 0. Даже если я вызываю функцию get_data с помощью block.find_elements_by_xpath(list_elements)[0]
или block.find_elements_by_xpath(list_elements)[1]
или просто с индексом 1, .find_element_by_xpath()
с абсолютным или относительным xpath просто возвращает значения для первого элемента.
При изменении файла HTML таким образом, чтобы в нем оставалась только вторая <li>
, функция .find_element_by_xpath()
возвращает титр и ключ для (ранее) второго, теперь первого элемента. При размещении (ранее) первого элемента после второго элемента (переключении) обоих элементов, результат get_data теперь переворачивается (id
и titel
show element # 1 and ony # 1)