Как извлечь текст из нескольких текстовых узлов в элементе с помощью Selenium и BeautifulSoup

У меня есть элемент, найденный через BeautifulSoup, который (HTML) выглядит так:

  <div class="ListingData">
    <span id="l_Contract" class="contract">Vendita Residenziale</span><br />
    New York<br />
    Appartamento<br />
    <strong>Prezzo:</strong>
    &euro; 100.000/200.000
    - <strong>Metri quadri:</strong>
    130/170
    </div>

И мне нужно попасть в одну переменную Vendita Residenziale, в другую Нью-Йорк, в другую Appartamento, в другую 100.000 / 200.000 < / strong> (не сильный тег), а в последнем - 130/170.

Я могу извлечь текст тега span, выполнив:

x = ele.find('span', attrs = {'class': 'contract'}).get_text()

но я изо всех сил пытаюсь получить другую информацию, я пытался:

y = ele.find('div', attrs = {'class':'ListingData'}).get_text().replace("\n","").strip()

но это дает мне все содержимое div, и это нормально, но мне нужно получить отдельные строки информации, такие как «результат [1]» для Нью-Йорка, «результат [2]» для Appartamento и так далее. Есть способ?


person Filippo Foladore    schedule 12.04.2019    source источник


Ответы (5)


Я использовал смесь BeautifulSoup4 и Regular Expression, вы можете поиграть с регулярным выражением.

a=bs4.BeautifulSoup(txt,'html.parser')
a.findAll(id="l_Contract")[0].text # Vendita Residenziale
p=re.compile("<br />").split(txt)
p[1] # "New York"
p[2] # "Appartamento"
re.compile("&euro;\s+([0-9.]+\/[0-9.]+)\s+-\s+<strong>").search(txt).group(1) #100.000/200.000

Другой способ - просто сделать это

a.findAll(class_="ListingData")[0].text
#Output
'\nVendita Residenziale\n    New York\n    Appartamento\nPrezzo:\n    € 100.000/200.000\n    - Metri quadri:\n    130/170\n    '

Что легче разобрать.

person Chebli Zaki    schedule 12.04.2019

Поскольку весь текст, который вы хотите, находится в теге <div>, кажется, самым простым способом было бы получить текст <div> и разделить текст на новых строках '\n' на список result:

result = [e.strip() for e in ele.div.text.strip().split('\n')]

>>> result
[u'Vendita Residenziale', u'New York', u'Appartamento', u'Prezzo:', u'\u20ac 100.000/200.000', u'- Metri quadri:', u'130/170']

которые затем можно проиндексировать по желанию:

for n, res in enumerate(result):
    print(f'result[{n}] = {res}')

result[0] = Vendita Residenziale
result[1] = New York
result[2] = Appartamento
result[3] = Prezzo:
result[4] = € 100.000/200.000
result[5] = - Metri quadri:
result[6] = 130/170
person davedwards    schedule 12.04.2019

на самом деле это не проблема bs4, другие данные, которые вы хотите, не находятся внутри тегов span, извлеките свои данные на основе строковых наблюдений

sp=sp.find('div',id='onesiwant')
for div in sp:
    all=div.text.strip()
    #now you can split('\n') 
     html=str(div)
     get the stuff out of span
        now split by '<br>' tags

вы спрашиваете, как использовать bs4 для получения данных из текста между тегами или разделенных \ n, поэтому bs4 здесь не требуется, просто манипуляции со строками

person Edo Edo    schedule 13.04.2019

Один лишь Selenium может извлечь все необходимые тексты, и вы можно использовать следующее решение:

element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "div[@class='ListingData']")))
text_Vendita_Residenziale = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "div[@class='ListingData']/span[@class='contract' and contains(@id='Contract')]")))
text_NewYork = driver.execute_script('return arguments[0].childNodes[3].textContent;', element).strip()
text_Appartamento = driver.execute_script('return arguments[0].childNodes[5].textContent;', element).strip()
text_100_200 = driver.execute_script('return arguments[0].childNodes[8].textContent;', element).strip()
text_130_170 = driver.execute_script('return arguments[0].lastChild.textContent;', element).strip()
person DebanjanB    schedule 13.04.2019
comment
К сожалению, когда я запускаю этот код, он вызывает исключение TimeoutException в первой строке (element = ...), я импортировал все примерно так: from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException - person Filippo Foladore; 13.04.2019
comment
... TimeoutException в первой строке (элементе) ... означает, что желаемый элемент не был однозначно идентифицирован даже после WebDriverWait. Можете ли вы обновить вопрос, добавив немного внешнего HTML? - person DebanjanB; 13.04.2019

Вы можете использовать строку для навигации и .contents

from bs4 import BeautifulSoup, NavigableString

html = '''
<div class="ListingData">
    <span id="l_Contract" class="contract">Vendita Residenziale</span><br />
    New York<br />
    Appartamento<br />
    <strong>Prezzo:</strong>
    &euro; 100.000/200.000
    - <strong>Metri quadri:</strong>
    130/170
    </div>
'''

soup = bs(html, 'lxml')
item1 = soup.select_one('#l_Contract').text
items = soup.select_one('.ListingData').contents
results = []
for item in items:
    if isinstance(item, NavigableString) and item.strip():
        results.append(item.strip())

item2 = results[0]
item3 = results[1]
item4 = results[2]

print(item1, ',', item2, ',', item3, ',', item4)
person QHarr    schedule 13.04.2019