【问题标题】:How to extract texts from multiple textnodes within an element using Selenium and BeautifulSoup如何使用 Selenium 和 BeautifulSoup 从元素内的多个文本节点中提取文本
【发布时间】:2019-09-03 16:38:14
【问题描述】:

我通过 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,另一个 New York,另一个 Appartamento,另一个 100.000 /200.000(不是强标签)和最后一个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 内容,这没关系,但我需要获取单独的信息行,例如纽约的“result[1]”、Appartamento 的“result[2]”等等。有方法吗?

【问题讨论】:

    标签: python selenium xpath beautifulsoup webdriverwait


    【解决方案1】:

    我混合使用了 BeautifulSoup4 和正则表达式,你可以玩弄 regex

    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    '
    

    Wich 更容易解析。

    【讨论】:

      【解决方案2】:

      由于您想要的所有文本都在 &lt;div&gt; 标记中,似乎最简单的方法是获取 &lt;div&gt; 文本,并将换行符 '\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
      

      【讨论】:

        【解决方案3】:

        这里不是真正的 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 不是必需的,只是字符串操作

        【讨论】:

          【解决方案4】:

          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()
          

          【讨论】:

          • 不幸的是,当我运行此代码时,它在第一行(元素 = ...)引发了 TimeoutException,我导入了这样的所有内容: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
          • ...TimeoutException on the first line (element )... 表示即使在 WebDriverWait 之后也没有唯一标识所需的元素。你能用更多的outerHTML来更新这个问题吗?
          【解决方案5】:

          你可以使用navigable string and .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)
          

          【讨论】:

            猜你喜欢
            • 2021-03-05
            • 2020-11-03
            • 1970-01-01
            • 1970-01-01
            • 2021-12-29
            • 1970-01-01
            • 2019-02-16
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多