Я пытаюсь восстановить сообщения в Интернете, и мне удалось добиться успеха на большинстве сайтов, используя приведенный ниже код для очистки текстов.
parent = driver.find_element(By.XPATH, "//*") # main post element
child = parent.find_elements(By.XPATH, ".//*") # child containing texts/emojis/links/images
for i in child:
if i.text is not None:
post.append(i.get_attribute('textContent'))
if i.get_attribute('alt') is not None:
post.append(i.get_attribute('alt'))
text = ''.join(post)
print(text)
По сути, я реконструирую сообщение, получая textContent
и alt
в том виде, в котором они найдены и перечислены с помощью find_elements
. Если ребенок содержит text
, будет получен текст, если нет, будет получен alt
для смайликов/изображений.
Все содержимое публикации можно получить с помощью get_attribute
, поскольку каждый текст и смайлик находятся внутри дочернего элемента. Однако я столкнулся со структурой, в которой есть только один дочерний элемент (<div>
), содержащий все text
и alt
. Пример ниже:
<span class = "post">
<div class = "paragraph1">
<div>
<span class = "html-span link">
<a>#link1 </a>
</span>
"A "
<span class = "html-span emoji">
<img alt = ":)">
</span>
"B "
</div>
</div>
<div class = "paragraph2">
<div>
"C "
<span class = "html-span link">
<a>#link2</a>
</span>
"D "
<span class = "html-span emoji">
<img alt = ":(">
</span>
"E"
</div>
</div>
</span>
Можно ли воплотить идею //text() or //*[@img='alt']
в жизнь? Кажется, использование find_elements
с By.XPATH, //text()
запрещено.
Ожидаемый результат:
#link1 A :) B C#link2 D :( E
Пытался:
parent = driver.find_element(By.XPATH, "//*") # main post element
child = parent.find_elements(By.XPATH, ".//*[contains(@class, 'html-span')]//*") # child containing texts/emojis/links/images
for i in child:
print(i.get_attribute('textContent'))
if i.text is not None:
post.append(i.get_attribute('textContent'))
if i.get_attribute('alt') is not None:
post.append(i.get_attribute('alt'))
print(post)
text = ''.join(post)
print(text)
Результат:
[#link, '', :), '', '', #link2, '', :(, ''] # пропал text
ребенка
parent = driver.find_element(By.XPATH, //span[@class='post']")
print(parent.get_attribute('textContent'))
Результат:
#link1 A B C#link2 D E
# отсутствует атрибут alt
Я пытаюсь сгруппировать каждый абзац class
и составить из них предложения. Но возможность получить и атрибут, и текст всего сообщения по порядку уже достаточно хорошо.
Любая идея о том, как действовать, очень ценится.
🤔 А знаете ли вы, что...
Python поддерживает многозадачность и многопоточность.
Этот скрипт должен работать:
script = '''
function getText(node){
let text = [];
for (let i = 0; i < node.childNodes.length; i++){
const child = node.childNodes[i];
if (child.alt){
text.push(child.alt);
} else if (child.children){
text.push(getText(child));
} else {
const content = child.textContent.trim();
content && text.push(content);
}
}
return text.join(' ');
}
return getText(arguments[0])
'''
span = driver.find_element(By.CSS_SELECTOR, 'span.post')
text = driver.execute_script(script, span)
print(text)
Редактировать:
Если вам нужно собственное решение на Python, вы можете использовать BeautifulSoup следующим образом:
from bs4 import BeautifulSoup
def getText(soup):
text = []
for child in soup.children:
if child.string:
text.append(child.get_text(strip=True))
elif alt := child.get('alt'):
text.append(alt)
elif child.contents:
text.append(getText(child))
return ' '.join(text).strip()
span = driver.find_element(By.CSS_SELECTOR, 'span.post')
html = span.get_attribute('innerHTML')
text = getText(BeautifulSoup(html, 'html.parser'))
print(text)