Python beautifulsoup提取没有标识符的值

时间:2014-09-29 07:50:08

标签: python regex beautifulsoup

我遇到了问题,并且不知道如何正确解决问题。 我想提取价格(所以在第一个例子130€,在第二个130€)。

问题是属性一直在变化。所以我无法做到这样的事情,因为我正在抓取数百个网站,并且在每个网站上的前两个字符都是" id"属性可能不同:

tag = soup_expose_html.find('span', attrs={'id' : re.compile(r'(07_content$)')})    

即使我会使用这样的东西它也不会起作用,因为没有价格的链接,我可能会得到一些其他价值:

tag = soup_expose_html.find('span', attrs={'id' : re.compile(r'([0-9]{2}_content$)')})   

示例html代码:

<span id="07_lbl" class="lbl">Price:</span>
<span id="07_content" class="content">130  €</span>
<span id="08_lbl" class="lbl">Value:</span>
<span id="08_content" class="content">90000  €</span>


<span id="03_lbl" class="lbl">Price:</span>
<span id="03_content" class="content">130  €</span>
<span id="04_lbl" class="lbl">Value:</span>
<span id="04_content" class="content">90000  €</span>

目前我唯一能想到的就是用类似于&#34; text =&#39; Price:&#39;&#34;然后获取.next_sibling并提取字符串。但我不确定是否有更好的方法来做到这一点。有什么建议? : - )

3 个答案:

答案 0 :(得分:2)

findAll解决方案怎么样? 首先收集所有可能的id前缀,然后迭代它们并获取所有元素

>>> from bs4 import BeautifulSoup
>>> import re
>>> html = """
...         <span id="07_lbl" class="lbl">Price:</span>
...         <span id="07_content" class="content">130  €</span>
...         <span id="08_lbl" class="lbl">Value:</span>
...         <span id="08_content" class="content">90000  €</span>
... 
... 
...         <span id="03_lbl" class="lbl">Price:</span>
...         <span id="03_content" class="content">130  €</span>
...         <span id="04_lbl" class="lbl">Value:</span>
...         <span id="04_content" class="content">90000  €</span>
... """
>>> 
>>> soup = BeautifulSoup(html)
>>> span_id_prefixes = [
...     span['id'].replace("_content","")
...     for span in soup.findAll('span', attrs={'id' : re.compile(r'(_content$)')})
... ]
>>> for prefix in span_id_prefixes:
...     lbl     = soup.find('span', attrs={'id' : '%s_lbl' % prefix})
...     content = soup.find('span', attrs={'id' : '%s_content' % prefix})
...     if lbl and content:
...         print lbl.text, content.text
... 
Price: 130  €
Value: 90000  €
Price: 130  €
Value: 90000  €

答案 1 :(得分:1)

尝试美丽的汤选择功能。它使用css选择器:

for span in soup_expose_html.select("span[id$=_content]"):
    print span.text

结果是一个包含所有跨度的列表,其id以_content

结尾

答案 2 :(得分:1)

以下是您如何轻松提取原始帖子中的价格值。

html = """
        <span id="07_lbl" class="lbl">Price:</span>
        <span id="07_content" class="content">130  €</span>
        <span id="08_lbl" class="lbl">Value:</span>
        <span id="08_content" class="content">90000  €</span>


        <span id="03_lbl" class="lbl">Price:</span>
        <span id="03_content" class="content">130  €</span>
        <span id="04_lbl" class="lbl">Value:</span>
        <span id="04_content" class="content">90000  €</span>
"""

from bs4 import BeautifulSoup
soup = BeautifulSoup(html)

price_texts = soup.find_all('span', text='Price:')
for element in price_texts:
    # .next_sibling() might work, too, with a parent element present
    price_value = element.find_next_sibling('span')
    print price_value.get_text()

# It prints:
# 130  €
# 130  €

此解决方案的代码较少,IMO更清晰。