是否可以在一个for循环中使用2种不同的BeautifulSoup soup.select?

时间:2015-04-14 10:02:06

标签: python for-loop beautifulsoup web-crawler

是否可以减少代码,以便我有一个for循环而不是两个?我之所以这样做,是因为它是一个时间关键的抓取循环。

i = 0
data = []
data.append([])
data.append([])

for product in soup.select('div > span.name'):
    data[0].append(product.text)
    i += 1

i = 0

for product in soup.select('div > span.value'):
    data[1].append(product.text)
    i += 1

这是我想要获取数据的HTML部分:

<html><body><div id="pagecontent"><div id="container"><div id="content"><div id="tab-description"><div id="attributes">
<div class="attr">
    <span class="name">Ugug</span>
    <span class="value">dfgd454</span>
</div>

1 个答案:

答案 0 :(得分:0)

您可以使用列表推导轻松收集数据:

In [2]: html = """<div><span class='name'>Andrew</span><span class='value'>42</span></div>
   ...: <div><span class='name'>Bob</span><span class='value'>128</span></div>"""

In [3]: soup = BeautifulSoup(html)

In [4]: patterns = ['div > span.name', 'div > span.value']

In [5]: data = [[product.text for product in soup.select(pattern)] for pattern in patterns] 

In [6]: data
Out[6]: [['Andrew', 'Bob'], ['42', '128']]

但是,此代码仍为每个选择模式调用单独的for循环。如果要使用一个循环,则应提供文档结构示例。


对于给定的文档结构,我可以建议另一种解决方案:

In [7]: html = '''<html><body><div id="pagecontent"><div id="container"><div id="content"><div id="tab-description"><div id="attributes">
   ...: <div class="attr">
   ...:     <span class="name">Ugug</span>
   ...:     <span class="value">dfgd454</span>
   ...: </div>'''

In [8]: soup = BeautifulSoup(html)

In [9]: attrs = soup.select('div.attr')

In [10]: attrs
Out[10]: 
[<div class="attr">
 <span class="name">Ugug</span>
 <span class="value">dfgd454</span>
 </div>]

In [11]: def parse_attr(attr):
   ....:     return {
   ....:         'name': attr.find(class_='name').text,
   ....:         'value': attr.find(class_='value').text
   ....:     }
   ....: 

In [12]: list(map(parse_attr, attrs))
Out[12]: [{'name': 'Ugug', 'value': 'dfgd454'}]

您也可以扩展属性数量。在这种情况下,您可以通过以下方式重写函数parse_attr

In [25]: def parse_attr(attr):
    return {span['class'][0]: span.text for span in attr('span')}
   ....: 

In [26]: list(map(parse_attr, attrs))
Out[26]: [{'name': 'Ugug', 'value': 'dfgd454'}]