BeautifulSoup解析空格
今天爬⼀个⽹站,它的class⾥有空格,导致我⽤BeautifulSoup半天没爬出来,后来看了⽂档,这叫多值属性:
HTML 4定义了⼀系列可以包含多个值的属性.在HTML5中移除了⼀些,却增加更多.最常见的多值的属性是 class (⼀个tag可以有多个CSS的class). 还有⼀些属性rel , rev , accept-charset , headers , accesskey . 在Beautiful Soup中多值属性的返回类型是list:
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会将这个属性作为字符串返回
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']
5print(rel_soup.p)
6# <p>Back to the <a rel="index contents">homepage</a></p>
如果转换的⽂档是XML格式,那么tag中不包含多值属性
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的时候要注意
举个例⼦吧:
假如我现在的HTML是这样的:
>>> html = '<div class="l_post j_l_post l_post_bright  "></div>'
先对他⽤html.parser解析,然后我们看⼀看⾥⾯的class是什么
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="example/elsie" id="link1">Elsie</a>,
3#  <a class="sister" href="example/lacie" id="link2">Lacie</a>,
4#  <a class="sister" href="example/tillie" id="link3">Tillie</a>]
class_参数同样接受不同类型的过滤器 ,字符串,正则表达式,⽅法或True :
1 soup.find_all(class_=repile("itl"))
2# [<p class="title"><b>The Dormouse's story</b></p>]
3
4def has_six_characters(css_class):
5return css_class is not None and len(css_class) == 6
6
7 soup.find_all(class_=has_six_characters)
8# [<a class="sister" href="example/elsie" id="link1">Elsie</a>,
9#  <a class="sister" href="example/lacie" id="link2">Lacie</a>,
10#  <a class="sister" href="example/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="example/elsie" id="link1">Elsie</a>,
3#  <a class="sister" href="example/lacie" id="link2">Lacie</a>,
4#  <a class="sister" href="example/tillie" id="link3">Tillie</a>]
以上是⽂档对class_的解释,但是我发现在有些⽹站的解析时这种⽅式还是⾏不通,所以在这种⽅式⾏不通的时候,我⽤了这种re
1 InfoList = Soup.find_all(class_ = repile('l_post j_l_post l_post_bright'))
⽐如说这个多值属性,我⽤前⾯的⽅法都不⾏,tag的class是“l_post j_l_post l_post_bright  ”,这样才解决了我的问题

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。