今天爬一個網站,它的class裏有空格,致使我用BeautifulSoup半天沒爬出來,後來看了文檔,這叫多值屬性:css
HTML 4定義了一系列能夠包含多個值的屬性.在HTML5中移除了一些,卻增長更多.最多見的多值的屬性是 class (一個tag能夠有多個CSS的class). 還有一些屬性 rel , rev , accept-charset , headers , accesskey . 在Beautiful Soup中多值屬性的返回類型是list:html
1 css_soup = BeautifulSoup('<p class="body strikeout"></p>') 2 css_soup.p['class'] 3 # ["body", "strikeout"] 4 5 css_soup = BeautifulSoup('<p class="body"></p>') 6 css_soup.p['class'] 7 # ["body"]
若是某個屬性看起來好像有多個值,但在任何版本的HTML定義中都沒有被定義爲多值屬性,那麼Beautiful Soup會將這個屬性做爲字符串返回python
1 id_soup = BeautifulSoup('<p id="my id"></p>') 2 id_soup.p['id'] 3 # 'my id'
將tag轉換成字符串時,多值屬性會合併爲一個值正則表達式
1 rel_soup = BeautifulSoup('<p>Back to the <a rel="index">homepage</a></p>') 2 rel_soup.a['rel'] 3 # ['index'] 4 rel_soup.a['rel'] = ['index', 'contents'] 5 print(rel_soup.p) 6 # <p>Back to the <a rel="index contents">homepage</a></p>
若是轉換的文檔是XML格式,那麼tag中不包含多值屬性post
1 xml_soup = BeautifulSoup('<p class="body strikeout"></p>', 'xml') 2 xml_soup.p['class'] 3 # u'body strikeout'
這是文檔對多值屬性的解釋網站
因此在使用BeautifulSoup.find or BeautifulSoup.find_all的時候要注意spa
舉個例子吧:code
假如我如今的HTML是這樣的:orm
>>> html = '<div class="l_post j_l_post l_post_bright "></div>'
先對他用html.parser解析,而後咱們看一看裏面的class是什麼xml
1 >>> Soup = BeautifulSoup(html,'html.parser') 2 >>> Soup.div['class'] 3 ['l_post', 'j_l_post', 'l_post_bright', '']
咦,咱們發現若是最後又空格的話會多一個'',咱們用find_all或者find能夠找到咱們想要的這個標籤,可是class能夠只要第一個,也能夠要整個列表均可以
notice:我在爬一個網站的時候發現了這個的問題,你用列表的化是隻要有列表中任一一個元素都能匹配上
1 >>> Soup.find('div', attrs = {'class':'1_post'}) 2 >>> Soup.find('div', attrs = {'class':'l_post'}) 3 <div class="l_post j_l_post l_post_bright "></div> 4 >>> Soup.find('div', attrs = {'class':['l_post', 'j_l_post']}) 5 <div class="l_post j_l_post l_post_bright "></div> 6 >>> Soup.find('div', attrs = {'class':['l_post', 'j_l_post', 'l_post_bright']}) 7 <div class="l_post j_l_post l_post_bright "></div> 8 >>> Soup.find('div', attrs = {'class':['l_post', 'j_l_post', 'l_post_bright', '']}) 9 <div class="l_post j_l_post l_post_bright "></div>
這裏再補充一點知識吧,就是find,和find_all的用法,拿這個例子繼續(對了,find_all由於經常使用,全部能夠省略,能夠直接寫Soup(.....))
1 >>> Soup.find(attrs = {'class':['l_post', 'j_l_post', 'l_post_bright', '']}) 2 <div class="l_post j_l_post l_post_bright "></div> 3 >>> Soup.find_all(attrs = {'class':['l_post', 'j_l_post', 'l_post_bright', '']})[0] 4 <div class="l_post j_l_post l_post_bright "></div> 5 >>> Soup.find_all('div', attrs = {'class':['l_post', 'j_l_post', 'l_post_bright', '']})[0] 6 <div class="l_post j_l_post l_post_bright "></div>
通過對BeautifulSoup的深度閱讀後,以爲下面這個點對分析多值屬性的html很重要:
按照CSS類名搜索tag的功能很是實用,但標識CSS類名的關鍵字 class 在Python中是保留字,使用 class 作參數會致使語法錯誤.從Beautiful Soup的4.1.1版本開始,能夠經過 class_ 參數搜索有指定CSS類名的tag:
1 soup.find_all("a", class_="sister") 2 # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, 3 # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, 4 # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
class_ 參數一樣接受不一樣類型的 過濾器 ,字符串,正則表達式,方法或 True :
1 soup.find_all(class_=re.compile("itl")) 2 # [<p class="title"><b>The Dormouse's story</b></p>] 3 4 def has_six_characters(css_class): 5 return css_class is not None and len(css_class) == 6 6 7 soup.find_all(class_=has_six_characters) 8 # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, 9 # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, 10 # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
tag的 class 屬性是 多值屬性 .按照CSS類名搜索tag時,能夠分別搜索tag中的每一個CSS類名:
1 css_soup = BeautifulSoup('<p class="body strikeout"></p>') 2 css_soup.find_all("p", class_="strikeout") 3 # [<p class="body strikeout"></p>] 4 5 css_soup.find_all("p", class_="body") 6 # [<p class="body strikeout"></p>]
搜索 class 屬性時也能夠經過CSS值徹底匹配:
1 css_soup.find_all("p", class_="body strikeout") 2 # [<p class="body strikeout"></p>]
徹底匹配 class 的值時,若是CSS類名的順序與實際不符,將搜索不到結果:
1 soup.find_all("a", attrs={"class": "sister"}) 2 # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, 3 # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, 4 # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
以上是文檔對class_的解釋,可是我發如今有些網站的解析時這種方式仍是行不通,因此在這種方式行不通的時候,我用了這種re
1 InfoList = Soup.find_all(class_ = re.compile('l_post j_l_post l_post_bright'))
好比說這個多值屬性,我用前面的方法都不行,tag的class是「l_post j_l_post l_post_bright 」,這樣才解決了個人問題