2016-07-21 38 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

相关问题