尝试/除了一系列BeautifulSoup命令的优雅方式?

时间:2012-12-09 01:52:26

标签: python beautifulsoup

我正在解析显示商品数据的网站上的网页。这些物品有大约20个可能会或可能不会发生的字段 - 例如:价格,数量,上次购买,高,低等。

我目前正在使用一系列命令;大约20行soup.find('div',{'class':SOME_FIELD_OF_INTEREST})来查找每个单独的感兴趣的字段。 (有些位于divspandd,依此类推,因此很难只执行soup.find_all('div')命令。)

我的问题:tryexcept是否有一种优雅的方式,以便查看所述代码可以更紧凑或简洁?现在,样本行看起来像:

try:
    soup.find('div', {'id':'item-pic'}).img["src"]
except:
    ""

我希望将所有内容组合在一行中。我不认为我可以在语法上运行try:<line of code> except: <code>,而且我不确定如何在没有实际运行命令的情况下编写一个try_command(soup.find('div',{'id':'item-pic'}).img["src"])的函数。

我很想知道是否有人有任何建议(包括:“这不可能/不实用,继续前进”)。 :)

编辑:在谈了一下之后,我想我想看看内联异常处理的好习惯是什么,如果这是正确的路线。

2 个答案:

答案 0 :(得分:1)

也许是这样的:

def try_these(start_obj, *args) :
        obj = start_obj
        for trythat in args :
            if obj is None :
                return None
            try :
                if isinstance(trythat, str) :
                    obj = getattr(obj, trythat)
                else :
                    method, opts = trythat
                    obj = getattr(obj, method)(*opts)
            except :
                return None
        return obj    
src = try_these(soup, ('find', ({'id':'item-pic'},),), 
                      'img', 
                      ('get', ('src',),) )

您可以通过str传递来自对象或tuple(str方法,元组参数)的属性,最后您将获得None或结果。我不熟悉汤,所以我不确定get('src')是否是一个好的方法(可能不是一个词典),无论如何你可以轻松地修改那个片段以接受更多的东西而不仅仅是'call或attr ”。


受你的问题的启发,我编写了简单的python模块,有助于处理这种情况,你可以找到它here

import silentcrawler    

wrapped = silentcrawler.wrap(soup)
# just return None on failure
print wrapped.find('div', {'id':'item-pic'}).img["src"].value_

# or
def on_success(value) :
    print 'found value:', value
wrapped = silentcrawler.wrap(soup, success=on_success)
# call on_success if everything will be ok
wrapped.find('div', {'id':'item-pic'}).img["src"].value_ 

有更多可能性

答案 1 :(得分:1)

如果我理解正确,你想根据一个有趣的类名找到一些字段,但它们不一定是相同的元素(不是全部<div>

如果是这样,使用BeautifulSoup,您可以传递已编译的正则表达式(在re.compile中代替字符串)。例如:

print soup.findAll(re.compile(".*"), {'class': 'blah'})
# [<div class="blah"></div>, <span class="blah"></span>]

我们可以使用它来整理所有可能包含图像的相关外观DOM元素:

import re
import urllib

from BeautifulSoup import BeautifulSoup as BS


html = """
<html>
<body>
<div class="blah"></div>
<span class="blah"><img src="yay.jpg"></span>
<span class="other"></div>

</body>
</html>
"""

def get_img_src(soup, cssclass):
    for item in soup.findAll(re.compile(".*"), {'class': cssclass}):
        if item.img is not None and 'src' in dict(item.img.attrs):
            return item.img['src']


soup = BS(html)
img = get_img_src(soup, cssclass = "blah")
print img # outputs yay.jpg, or would return None if nothing was found

有争议,但我认为在这种情况下使用if检查更合适,因为item.img['src']

同样可以这样写:

def get_img_src(soup, cssclass):
    for item in soup.findAll(re.compile(".*"), {'class': cssclass}):
        try:
            return item.img['src']
        except TypeError:
            pass

..但是在这里捕获TypeError很奇怪(因为'NoneType' object has no attribute '__getitem__'并不是你想要捕获的异常,它是BeautifulSoup用来访问属性的语法的副产品)