zoukankan      html  css  js  c++  java
  • 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']
    5 print(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="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  ”,这样才解决了我的问题

  • 相关阅读:
    使用sshfs挂载远程服务器目录
    yum install --downloadonly 下载依赖包到本地 但不安装
    CentOS 7安装SSHFS 实现远程主机目录 挂载为本地目录
    CentOS7下FTP的安装与配置
    标签传播算法(Label Propagation Algorithm, LPA)初探
    线性模型(linear model)基本定义及参数求解数学本质、损失函数的选择与评估数学原理、及其基于线性模型衍生的其他机器学习模型相关原理讨论
    贝叶斯A/B测试
    谨慎选择我们的先验
    关于年会抢红包游戏的一个思考
    WMI攻击技术研究
  • 原文地址:https://www.cnblogs.com/ducklu/p/9002211.html
Copyright © 2011-2022 走看看