2016-07-21 52 views
1

我使用bs4從js-stream-item類中拉出li標籤,但不包含以下的scroll-bump-user-card。 (這是隻得到a,b只)使用BeautifulSoup查找所有包含AND NOT NOT的標籤b

<li class="js-stream-item stream-item ">a<li> 
<li class="js-stream-item stream-item stream-item ">b<li> 
<li class="js-stream-item stream-item scroll-bump-user-card ">c<li> 

有兩種方法我在想。

  1. 使用soup.find_all('li', class_=re.compile('js-stream-item'))獲取所有標籤,然後使用scroll-bump-user-card移除標籤。

  2. 使用[tag.extract() for tag in soup.find_all('li', class_=re.compile('scroll-bump-user-card'))]先刪除,然後查找全部。

問題是如果有一個體面的方式在re.compile()編輯正則表達式,且不語法來獲得A,B。

更新我重新寫alecxe的回答的第一個選項爲一個單一的長行如下:

所有的
soup.find_all(lambda tag: re.compile('js-stream-item').search(str(tag)) 
         and not re.compile('scroll-bump-user-card').search(str(tag)) 
         and tag.name == 'li') 

回答

0

首先,class是一個特殊的multi-valued attribute需要special handling

一種選擇是使用searching function,檢查js-stream-item類的存在和不存在scroll-bump-user-card類:

def search_function(tag): 
    if tag.name == "li": 
     class_ = tag.get("class", []) 
     return "js-stream-item" in class_ and "scroll-bump-user-card" not in class_ 

for li in soup.find_all(search_function): 
    print(li.get_text(strip=True)) 

另一種選擇是找到所有lijs-stream-item類裏跳過li元素有scroll-bump-user-card等級:

for li in soup.select("li.js-stream-item"): 
    if "scroll-bump-user-card" in li["class"]: 
     continue 
    print(li.get_text(strip=True)) 

另外,檢查class結束與stream-itemCSS selector(不要用這個):

for li in soup.select("li[class$=' stream-item ']"): 
    print(li.get_text(strip=True)) 

注意,對於這種使用情況更好的CSS選擇器將是:

li.js-stream-item:not(.scroll-bump-user-card) 

但由於BeautifulSoup中有限的CSS選擇器支持,它不會工作。

+0

謝謝!我將您的第一個選項重寫爲我的文章中更新的一行。對此有何建議?我還研究了一些正則表達式,嘗試類似^(?!。* scroll-bump)* js-stream-item,但沒有運氣。你有什麼主意嗎? – PhantomKidding

+0

@PhantomKidding,我不確定你爲什麼要在一行中做第一個選項,並修改它來做正則表達式搜索。另外,你有沒有看過鏈接答案中的多值屬性意味着什麼?您不會將單個字符串作爲類 - 它是一個字符串列表 - 每個類都有一個字符串。謝謝。 – alecxe

相關問題