爬虫(第二部分)

                      爬虫总结02(爬虫解析器:正则,xpath,BS)
一:常用正则表达式解析
  单字符:
        . : 除换行以外所有字符
        [] :[aoe] [a-w] 匹配集合中任意一个字符
        \d :数字  [0-9]
        \D : 非数字
        \w :数字、字母、下划线、中文
        \W : 非\w
        \s :所有的空白字符包,括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
        \S : 非空白
    数量修饰:
        * : 任意多次  >=0
        + : 至少1次   >=1
        ? : 可有可无  0次或者1次
        {m} :固定m次 hello{3,}
        {m,} :至少m次
        {m,n} :m-n次
    边界:
        $ : 以某某结尾
        ^ : 以某某开头
    分组:
        (ab)
    贪婪模式: .*
    非贪婪(惰性)模式: .*?

    re.I : 忽略大小写
    re.M :多行匹配
    re.S :单行匹配

    re.sub(正则表达式, 替换内容, 字符串)

二:xpath解析

  01:测试html数据:

<html lang="en">
        <head>
            <meta charset="UTF-8" />
            <title>测试bs4</title>
        </head>
        <body>
            <div>
                <p>百里守约</p>
            </div>
            <div class="song">
                <p>李清照</p>
                <p>王安石</p>
                <p>苏轼</p>
                <p>柳宗元</p>
                <a href="http://www.song.com/" title="赵匡胤" target="_self">
                    <span>this is span</span>
                宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
                <a href="" class="du">总为浮云能蔽日,长安不见使人愁</a>
                <img src="http://www.baidu.com/meinv.jpg" alt="" />
            </div>
            <div class="tang">
                <ul>
                    <li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
                    <li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li>
                    <li><a href="http://www.126.com" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li>
                    <li><a href="http://www.sina.com" class="du">杜甫</a></li>
                    <li><a href="http://www.dudu.com" class="du">杜牧</a></li>
                    <li><b>杜小月</b></li>
                    <li><i>度蜜月</i></li>
                    <li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li>
                </ul>
            </div>
        </body>
        </html>

  02:常用xpath表达式及符号说明:‘/’ 取文本

属性定位:
    #找到class属性值为song的div标签
    //div[@class="song"]
层级&索引定位:
    #找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a
    //div[@class="tang"]/ul/li[2]/a
逻辑运算:
    #找到href属性值为空且class属性值为du的a标签
    //a[@href="" and @class="du"]
模糊匹配:
    //div[contains(@class, "ng")]
    //div[starts-with(@class, "ta")]
取文本:
    # /表示获取某个标签下的文本内容
    # //表示获取某个标签下的文本内容和所有子标签下的文本内容
    //div[@class="song"]/p[1]/text()
    //div[@class="tang"]//text()
取属性:
    //div[@class="tang"]//li[2]/a/@href
03:基本操作:
#第一部导安装模块
 pip3 install lxml
#第二步:测试前先倒入模块
 from lxml import etree

使用的基本原理:将html文件文档转换成一个etree 对象,然后调用这个对象指定的方法来查找指定的节点
方法一:
    tree=etree.HTML(doc)   #用网络数据转换成对象
方法02:用读取本地文件转换成对象
    tree=etree.parse("test.html")
    print(">>",tree)  # <lxml.etree._ElementTree object at 0x0000002F7C68E708>

  操作例子:

001: ret=tree.xpath("//a[@id='feng']/text()")
     print(ret) # ['凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘']

002: ret=tree.xpath("//a[@id='feng']/@href")
     a标签下 id值为feng下的链接--> ['http://www.haha.com']

003: ret=tree.xpath("//div[@class='tang']/ul/li/a/@href")
     ['http://www.baidu.com', 'http://www.163.com', 'http://www.126.com', 'http://www.sina.com', 'http://www.dudu.com', 'http://www.haha.com']

004: ret=tree.xpath("//div[@class='tang']/ul/li/b/text()")  # ['杜小月']
     ret=tree.xpath("//a[@class='du' and @href='']/text()")  #['总为浮云能蔽日,长安不见使人愁']

005: ret=tree.xpath("//a[@title='qin']/text()")
     ['秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山']

006: ret=tree.xpath("//a[starts-with(@title,'qin')]/text()")
     ['清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村', '秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山']
     print(ret)
三:BS解析(Beautiful Soup)
ps: Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过    你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.
Beautiful Soup会帮你节省数小时甚至数天的工作时间.你可能在寻找 Beautiful Soup3 的文档,Beautiful Soup 3 目前已经停止开发,
官网推荐在现在的项目中使用Beautiful Soup 4

01:安装BS

 pip3 install beautifusoup4

02:解析器

 001:Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,
        lxml 解析器更加强大,速度更快,推荐安装。

 002:另一个可供选择的解析器是纯Python实现的 html5lib , html5lib的解析方式与浏览器相同,可以选择下列方法来安装html5lib:
        pip3 install html5lib

03:BS的使用方法:

 001:使用方法:
        a:导包:from bs4 import BeautifulSoup
        b:可以将一个本地的html文档或者网络的文件转换成一个BeautifuSoup对象,通过操作对象的属性方法来查找指定的节点内容
           --soup=BeautifulSoup(open("test.html(本地文件)","lxml")) 或者soup=BeautifulSoup("doc(网络数据)","lxml")

 002:打印soup对象内容为html文件中的内容
04:BS的基本语法
  soup=BeautifulSoup(open("test.html)(本地文件)","lxml")
    (1)根据标签名查找
        - soup.a   只能找到第一个符合要求的标签

    (2)获取属性
        - soup.a.attrs  获取a所有的属性和属性值,返回一个字典
        - soup.a.attrs['href']   获取href属性
        - soup.a['href']   也可简写为这种形式

    (3)获取内容
        - soup.a.string
        - soup.a.text
        - soup.a.get_text()
        -【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容

    (4)find:找到第一个符合要求的标签
        - soup.find('a')  找到第一个符合要求的
        - soup.find('a', title="xxx")
        - soup.find('a', alt="xxx")
        - soup.find('a', class_="xxx")
        - soup.find('a', id="xxx")

    (5)find_all:找到所有符合要求的标签
        - soup.find_all('a')
        - soup.find_all(['a','b']) 找到所有的a和b标签
        - soup.find_all('a', limit=2)  限制前两个

    (6)根据选择器选择指定的内容
        - select:soup.select('#feng')
        - 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
        - 层级选择器:
        div .dudu #lala .meme .xixi  下面好多级
        div > p > a > .lala          只能是下面一级
        【注意】select选择器返回永远是列表,需要通过下标提取指定的对象

五:BS解析的语法案例操作

案例源码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="c1">
   <!--<p>123</p>-->
   <!--<p>345</p>-->
   <div>

    </div>
</div>
<div>
<p id="my p" class="title"><b id="bbb" class="boldest">The Dormouse's story</b><span>123</span></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
</div>
</body>
</html>

案例代码
View Code  

  ps重点:soup.p.text和soup.p.string的区别:
  例子:<p id="my p" class="title"><b id="bbb" class="boldest">The Dormouse's story</b><span>123</span></p>
  print(soup.p.string)  # None
  print(soup.p.text)  # The Dormouse's story123

  >>总结:string在一个标签里面再套上其他标签的时候,只会打印None,text不管一个标签里面套上多少个标签,
     都会将这个标签里面所有的文本取出来
操作步骤:  
第一步:先导包,实例化一个对象出来
from bs4 import BeautifulSoup
实例化对象的两种方法:
方法01:soup = BeautifulSoup(open("test00.html"), "lxml")
方法02:# soup = BeautifulSoup(html_doc, "lxml")

 实际操作案例:

01:Tag对象的操作
    001:查找第一个a标签
        print(">>", soup.a)  # <a>111</a>
        print(">>", soup.a.attrs)  # {'class': ['a1']}

02:Tag对象的属性操作
    001:soup.a标签的类型:
        print("type是>>", type(soup.a))  # <class 'bs4.element.Tag'>
    002:Tag对象的属性操作
        print(soup.a.attrs["href"])  # 这个标签对象的链接 http://example.com/elsie
    003:Tag对象标签的class名
        print(soup.a.attrs["class"])  # ['sister']
    004:找出这个标签的id名字
        print(soup.a.attrs["id"])  # link1
    总结:----〉标签对象的属性操作的简单写法
        print(">>", soup.a["href"])  # http://example.com/elsie

03:Tag对象的文本操作
    print(soup.a.text)  # Elsie
    print(soup.a.get_text())  # Elsie 对象有get方法
    print(soup.a.string)  # Elsie  #

04:对象的find()和find_all()操作(find和find_all的详解(两者的参数说明是一样的,这里只取了find_all()为例子))
    01:find_all()  #找到文本中所有的 指定标签
      001:4种name参数过滤器
        第一种:
            例子01:
            ls = soup.find_all("a")  #name="a"
            print("ls>>", ls)  #结果是一个列表,可以进行循环
        第二种:
            例子02:
            ls = soup.find_all(["a", "p"])  # 找出所有的a标签和p标签 name=["a","p"]
            print(">>>++", ls)  # 结果是一个列表,可以进行循环
        第三种:
            例子03:
            import re
            print(">>>?",soup.find_all(re.compile("^b"))) #找出文本中所有以b开头的标签,body标签会被找出来,结果是一个列表

        第四种:
            例子04:
            def has_class_but_no_id(tag):
                return tag.has_attr('class') and not tag.has_attr('id')
            print("...",soup.find_all(has_class_but_no_id)) # name=has_class_but_no_id

      002:attrs属性参数过滤器
        print(soup.find_all("a", attrs={"class": "sister","id": "link1"}))#[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
        属性参数过滤简写:
        print(soup.find_all("a",id="link3")) #[<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

      003:text文本参数过滤
        print(soup.find_all("a",text="Tillie")) #[<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

      004:limit参数
        print(soup.find_all("a",limit=2))  #只找文本中的前2个a标签

      005:recursive参数(递归)
        print("True>>",soup.find_all("a",recursive=True))  #recursive 深度可以一直找下去,直到找完文本中所有的a标签
        print("False",soup.find_all("a",recursive=False)) # 深度为零

      006:recursive深度产生局部查询

        案例01:找第一个div标签内部所有的标签,recurs默认是True,所以会将recursive内部所有同级的标签以及同级标签的字标签全部找出来
        print(soup.div.find_all())

        案例02:recursive设置为False,则找出第一个div标签内部所有的同级标签,同级标签的字标签不会被找出来
        print("recursive>>>>",soup.div.find_all(recursive=False))  #找第一个div标签内部

04:selector操作
    ps:selector的标签查找操作和css选择器一样
 
posted @ 2019-03-01 17:42  XuMou  阅读(148)  评论(0编辑  收藏  举报