2010-11-06 40 views
3

我有這樣的事情使用BeautifulSoup:貪婪執行語句?

for line in lines: 
    code = l.find('span', {'class':'boldHeader'}).text 
    coded = l.find('div', {'class':'Description'}).text 
    definition = l.find('ul', {'class':'definitions'}).text 
    print code, coded, def 

然而,並不是在任何時候都存在的所有元素。我可以一試附上這只是使得它不會破壞程序的執行是這樣的:

for line in lines: 
    try: 
     code = l.find('span', {'class':'boldHeader'}).text 
     coded = l.find('div', {'class':'Description'}).text 
     definition = l.find('ul', {'class':'definitions'}).text 
     print code, coded, def 
    except: 
     pass 

但如何我貪婪地執行該語句?例如,如果只有兩個可用元素codecoded,我只想獲得這些並繼續執行。截至目前,即使存在codecoded,如果def不存在,print命令也不會執行。這樣做的

一種方法是把一個try...except像這樣每個語句:

for line in lines: 
    try: 
     code = l.find('span', {'class':'boldHeader'}).text 
    except: 
     pass 
    try: 
     coded = l.find('div', {'class':'Description'}).text 
    except: 
     pass 
    try: 
     definition = l.find('ul', {'class':'definitions'}).text 
    except: 
     pass 
    print code, coded, def 

但是,這是一個醜陋的方式和我想要的東西更清潔。有什麼建議麼?

回答

3

如何捕獲在一個函數「醜陋」的代碼,並調用函數需要:

def get_txt(l,tag,classname): 
    try: 
     txt=l.find(tag, {'class':classname}).text 
    except AttributeError: 
     txt=None 
    return txt 

for line in lines: 
    code = get_txt(l,'span','boldHeader') 
    coded = get_txt(l,'div','Description') 
    defn = get_txt(l,'ul','definitions') 
    print code, coded, defn 

PS。我將def更改爲defn,因爲def是一個Python關鍵字。將它用作變量名會引發一個SyntaxError。

PPS。使用裸露的例外情況並不是一個好習慣:

try: 
    .... 
except: 
    ... 

因爲它幾乎總是捕獲更多的你打算。更好地明確你想要捕捉什麼:

try: 
    ... 
except AttributeError as err: 
    ... 
+0

謝謝你的建議。 +1進行詳細說明。獲得的教訓:) – Legend 2010-11-06 20:18:10

+0

好的答案。使用try/catch作爲「正常」程序流程的一部分可能不太有利。 – zellus 2010-11-06 21:46:57

3

首先,您可以測試None而不是捕捉異常。如果找不到您的物品,l.find應返回None。例外情況應該保留用於錯誤和非常特殊的情況。

你可以做的第二件事是創建一個你想檢查的所有HTML元素的數組,然後嵌套for循環。由於我已經使用python已經有一段時間了,我將概述代碼,然後(希望)在測試時編輯答案。

喜歡的東西:

elementsToCheck = [ 
        [ 'span', {'class':'boldHeader'} ], 
        [ 'div', {'class':'Description'} ], 
        [ 'ul', {'class':'definitions'} ]] 

concatenated = '' 
for line in lines: 
    for something in elementsToCheck 
     element = l.find(something[0], something[1]) 
     if element is not None 
      concatenated += element.text 
print concatenated 

顯然上面的代碼將無法正常工作,但你應該明白我的意思。 :)

+0

謝謝我正在研究這個。但有一個問題是'find'實際上會拋出一個異常,這是我開始使用'try ... catch'塊的主要原因。所以在新方法中,如果'find'拋出一個異常,它不會從'for循環'出來嗎? – Legend 2010-11-06 20:13:13

+0

或者我可能會在for循環裏放一個'try ... catch'。我會回來的。爲你的時間+1。謝謝 – Legend 2010-11-06 20:15:28

+1

@Legend:哦,如果它拋出,那麼你將需要趕上。我仍然會檢查它是否實際上拋出一個空引用異常,因爲你正在對一個空對象調用'.text'(這看起來更符合邏輯,但是我再也不用Python來知道它的最佳值實踐)。 – Groo 2010-11-06 20:28:32