【问题标题】:Trouble Pulling HTML attribute无法提取 HTML 属性
【发布时间】:2021-10-28 06:04:30
【问题描述】:

我是 python 新手,在抓取一些 HTML 代码时遇到了麻烦。

我正在尝试从下面的 HTML 代码中提取文本“优惠券”、“到期日”和“初始发行价格”以及 float-right 类中的文本。我只包含了部分 HTML 代码,但我试图从中提取九个不同的部分

<span class="label genericQtipHelp" help="Annual interest rate payable on a security expressed as a percentage of the principal" data-hasqtip="160" aria-describedby="qtip-160">Coupon:</span>
<span class="float-right">3 %</span>
<span class="label genericQtipHelp" help="Date the principal becomes due and payable to bondholders" data-hasqtip="161">Maturity Date:</span>
<span class="float-right">08/12/2021</span>
<span class="label genericQtipHelp" help="Price / Yield at which a new issue of municipal securities is offered to the public" data-hasqtip="163">Initial Offering Price/Yield:</span>
<span class="float-right">3 %</span>

我能够使用以下代码从 HTML 的第二行(float-right 类)中提取日期:

输入

elements2 = driver.find_elements_by_class_name("float-right")
for data2 in elements2:
    print(data2.text)

输出

3 %
08/01/2022
08/12/2021
102.829% / 0.08%
$4,525,000
07/30/2021 09:14 AM
07/30/2021 01:30 PM
08/12/2021
-

这将返回存储在float-right 类中的所有数据,这正是我所需要的。但是,当我尝试从 HTML 的第一行提取“到期日期”和其他数据时,我遇到了错误。我相信这是因为我正在尝试获取属性?

代码用于尝试拉取到期日期,其他文字如下:

输入 1

elements = driver.find_elements_by_class_name("label genericQtipHelp").__getattribute__('data-hasqtip')
for data in elements:
   print(data.text)

输出 1

 elements = driver.find_elements_by_class_name("label genericQtipHelp").__getattribute__('data-hasqtip')
AttributeError: 'list' object has no attribute 'data-hasqtip'

输入 2

elements = soup.find('class', attrs={"label genericQtipHelp":'data-hasqtip'})
print(elements.text)

输出 2

AttributeError: 'NoneType' object has no attribute 'text'

我尝试了其他一些方法,但最终遇到了类似的错误。我如何提取这些数据,有没有更简单的方法来提取所有九个的 成熟日期3%

谢谢!

【问题讨论】:

    标签: python html selenium web-scraping beautifulsoup


    【解决方案1】:

    请不要将 Selenium 用于解析 HTML。它非常慢(在大页面(1M+ 大小)上比 lxml 慢 10 倍以上。我建议使用 lxml(或 Beautiful Soup):

    from lxml import html
    
    .....
    content = driver.page_source
    tree = html.fromstring(content)
    
    data = {}
    for float_right_node in tree.xpath('//span[@class="float-right"]'):
        value = float_right_node.xpath('string(./text())')
        key = float_right_node.xpath('string(./preceding-sibling::span[1]/text())')
        data[key] = value
        print(f"{key:35} {value}")
    

    【讨论】:

    • 谢谢@gangabas!这行得通,不过我还有最后一个问题。有没有办法将输出格式化为一个列表,就像我使用 Ram 的答案得到的那样,而不仅仅是一行?我使用了'for details in data: print(details)',它可以返回所有的标题名称(优惠券、到期日期..),但不返回值(3%,2021 年 8 月 12 日)。与之相关联。
    • 谢谢,你能解释一下{key:35}中的35是什么吗?
    • @user16768885 key 是变量名,:35 是输出中该字段的宽度。
    【解决方案2】:

    label genericQtipHelp 实际上是 2 个单独的类名:labelgenericQtipHelpfind_elements_by_class_name 方法应该得到一个类名。如果有多个类名,您必须使用 XPath 或 css 选择器。
    另外label genericQtipHelp 类属性值不是唯一的,它匹配Annual interest rateDate the principalPrice / Yield 元素。
    因此,要唯一匹配您可以使用的 Annual interest rate 元素

    elements = driver.find_elements_by_xpath("//span[contains(@help,'Annual interest rate')]").__getattribute__('data-hasqtip')
    for data in elements:
        print(data)
    

    您不需要在data 上应用.text,因为它已经是一个字符串,而不是一个网络元素。
    与上面类似,要查看可以使用的Date the principal 元素data-hasqtip

    elements = driver.find_elements_by_xpath("//span[contains(@help,'Date the principal')]").__getattribute__('data-hasqtip')
    for data in elements:
        print(data)
    

    help 属性中包含Price / Yield 的第三个元素相同。

    【讨论】:

    • 嗨@Prophet,感谢您抽出宝贵时间帮助回答我的问题!我尝试实现上面的代码,但我仍然收到 AttributeError。我正在尝试从以下 HTML 代码中获取“优惠券”:aria-describedby="qtip-160"&gt;Coupon:&lt;/span。我正在研究多个班级名称,所以感谢您展示这一点。在我原始帖子的 HTML 代码中,您将看到有优惠券、到期日期和初始发行价格/收益。这是我正在尝试获取的数据。它们都有一个共同的类属性,data-hasqtip..我想..有没有办法提取链接到这个的文本?
    【解决方案3】:

    您可以使用beautifulsoup 执行此操作。

    • 使用.find_all()方法查找所有类名为label genericQtipHelp&lt;span&gt;这将为您提供所有具有给定类名的 &lt;span&gt; 的列表。 它的文本是名称 [Maturity, Coupon, Yield etc.,]
    • 遍历上面的列表,对于每个跨度,使用findNext('span') 找到下一个跨度(值存在于这个跨度内。)并获取它的值。
    from bs4 import BeautifulSoup
    
    s = '''
    <span class="label genericQtipHelp" help="Annual interest rate payable on a security expressed as a percentage of the principal" data-hasqtip="160" aria-describedby="qtip-160">Coupon:</span>
    <span class="float-right">3 %</span>
    <span class="label genericQtipHelp" help="Date the principal becomes due and payable to bondholders" data-hasqtip="161">Maturity Date:</span>
    <span class="float-right">08/12/2021</span>
    <span class="label genericQtipHelp" help="Price / Yield at which a new issue of municipal securities is offered to the public" data-hasqtip="163">Initial Offering Price/Yield:</span>
    <span class="float-right">3 %</span>'''
    
    soup = BeautifulSoup(s, 'lxml')
    spans = soup.find_all('span', class_='label genericQtipHelp')
    
    
    for span in spans:
        name = span.text.strip()
        val = span.findNext('span').text.strip()
        print(f"{name:35} {val}")
    
    Coupon:                             3 %
    Maturity Date:                      08/12/2021
    Initial Offering Price/Yield:       3 %
    

    【讨论】:

      猜你喜欢
      • 2020-02-11
      • 2021-03-18
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-21
      • 1970-01-01
      • 2011-10-02
      相关资源
      最近更新 更多