02 爬虫数据解析之re,xpath,beautifulsoup

一.正则匹配

简单用法演示:

 1 字符:
 2 print(re.findall(".","abccc31223dn哈哈")) ###  . 匹配除了换行符以外的任意字符,搭配re.S可搭配任意字符(包括空行)#['a', 'b', 'c', 'c', 'c', '3', '1', '2', '2', '3', 'd', 'n', '哈', '哈']
 3 print(re.findall("ab[c,d]f","ab,f")) #匹配集合中任意一个字符,注意逗号不是分隔符,[]不需要分隔符
 4 print(re.findall("ab\df","ab5f")) #数字[0 - 9]
 5 print(re.findall("ab\Df","ab5f")) #非数字 结果为[]
 6 print(re.findall("ab\wf","ab_f")) #数字、字母、下划线、中文 结果:['ab_f']
 7 print(re.findall("ab\Wf","ab$f"))   #非\w也就是非(数字、字母、下划线、中文 ) 结果为:['ab$f']
 8 print(re.findall("ab\sf","ab f"))  # 所有的空白字符包,括空格、制表符、换页符等等 结果为:['ab f']
 9 print(re.findall("ab\Sf","ab f"))  # \S 非空白  结果为:[]
10 
11 
12 量词:
13 print(re.findall("abc*","abccc")) #['abccc']  任意多次  >=0  贪婪匹配
14 print(re.findall("abc?","abccc"))  #['abc'] 可有可无  0次或者1次 惰性匹配
15 print(re.findall("abc+","ab"))  #至少1次   >=1 没有匹配不成功
16 print(re.findall("abc{3}","abcc")) #固定m次 不够匹配不成功,超过了m个剩下的字符不要
17 print(re.findall("abc{3,}","abccccc")) #至少m次 不够匹配不成功,超过了m个剩下的字符全要
18 print(re.findall("abc{3,5}","abccccccc")) #固定3-5次不够匹配不成功,超过3-5的字符不要
19 
20 边界:
21 print(re.findall("^(.*?)c$","abccdsac")) #: 以某某结尾
22 print(re.findall("^a(.*?)$","abccdsac")) #: 以某某开头
23 
24 分组:(ab)
25 贪婪模式: .*
26 非贪婪(惰性)模式: .*?
27 
28 re.I : 忽略大小写
29 re.M :多行匹配
30 re.S :单行匹配
31 
32 re.sub(正则表达式, 替换内容, 字符串)
View Code

 

二.Xpath

如何使用xpath?

1.下载:pip install lxml
2.导包:from lxml import etree

3.将html文档或者xml文档转换成一个etree对象,然后调用对象中的方法查找指定的节点

  2.1 本地文件:tree = etree.parse(文件名)
                tree.xpath("xpath表达式")

  2.2 网络数据:tree = etree.HTML(网页内容字符串)
                tree.xpath("xpath表达式")

 

xpath用法展示参考如下:

1.文档文件

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

2.xpath查询实例

 1 from lxml import etree
 2 etree.parse("github.html")   #用于打开文件 parse
 3 tree=etree.HTML(doc)         #打开HTML文档 用.HTML即可
 4 
 5 
 6 注意在使用xpath,方法是 // 代表打开的整个文档 /代表下一级
 7 属性定位:
 8     找到class属性值为song的div标签
 9 ret = tree.xpath("//div[@class='song']")
10 
11 层级&索引定位:
12     找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a的网址
13 ret = tree.xpath("//div[@class='tang']/ul/li[2]/a/@href")
14 print(ret)
15 
16 
17 逻辑运算:
18     #找到href属性值为空且class属性值为du的a标签
19 ret = tree.xpath('//a[@class="du" and @href=""]')
20 print(ret)
21 
22 
23 模糊匹配:
24 查找属性title包含ng的a标签的内容
25 ret = tree.xpath('//a[contains(@title,"ng")]/text()')   #注意:在contains和starts-with 中@xx和格式是以逗号,分开的
26 print(ret)
27 查找属性title以qin开始的a标签的内容
28 ret=tree.xpath("//a[starts-with(@title,'qin')]/text()")
29 print(ret)
30 
31 
32 
33 取文本:
34     # /表示获取某个标签下的文本内容
35     # //表示获取某个标签下的文本内容和所有子标签下的文本内容
36 
37 ret = tree.xpath('div[@class="song"]/p[1]/text()')
38 ret = tree.xpath('div[@class="tang"]//text()')
39 
40 取属性:
41 ret = tree.xpath('div[@class="tang"]//li[2]/a/@href')
View Code

 

三:Beautifulsoup(BS)

概念:简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据。官方解释如下:

'''
Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。
它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
'''

Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.你可能在寻找 Beautiful Soup3 的文档,Beautiful Soup 3 目前已经停止开发,官网推荐在现在的项目中使用Beautiful Soup 4。

 

解析器:

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

下面具体介绍BS的语法以及相应操作:

1.使用流程

- 导包:from bs4 import BeautifulSoup
- 使用方式:可以将一个html文档,转化为BeautifulSoup对象,然后通过对象的方法或者属性去查找指定的节点内容
    (1)转化本地文件:
         - soup = BeautifulSoup(open('本地文件'), 'lxml')
    (2)转化网络文件:
         - soup = BeautifulSoup('字符串类型或者字节类型', 'lxml')
    (3)打印soup对象显示内容为html文件中的内容

2.基本方法总结:

(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选择器返回永远是列表,需要通过下标提取指定的对象
View Code

 

3.基本方法示例:

from bs4 import BeautifulSoup
soup=BeautifulSoup(html_doc,"lxml")
查找第一个a标签对象
print(soup.a)
print(type(soup.a)) # 查找到的标签类型为:<class 'bs4.element.Tag'> 是一个标签对象

################################################## 一 Tag对象的操作 ###################################################
------------------->> 属性操作
print(soup.a.attrs)   #返回一个字典 结果:{'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'}
print(soup.a.attrs["href"]) #结果为:http://example.com/elsie
print(soup.a.attrs["class"]) #结果为:['sister']
print(soup.a.attrs.get("id"))  #结果为:link1
建议取法:
print(soup.a["href"])  # http://example.com/elsie

------------------->> 文本操作
print(soup.a.text) # Elsie
print(soup.a.get_text()) # Elsie   #text和get_text() 取得的结果是一样的.调用方式不一样而已
print(soup.a.string)  # Elsie

#注意:text和string正常情况下取得的结果是一样,但取得的标签内含有多个标签取内容时:text全部取出 string不取
print(soup.p.text)   # The Dormouse's story123
print(soup.p.string) # None
View Code

 

4.有关find_all和all,以及selector的具体使用

 1 # 两个重要的搜索方法:find,find_all()
 2 ################################################ 二 find,find_all()###########################################
 3 
 4 
 5 #------------------------------>>  2.1 find_all()
 6 # 1.取出文本中所有a标签,并循环打印连接和属性
 7 # for link in soup.find_all("a"):
 8 #     print(link["href"],link['class'])
 9 '''
10 #结果为:
11 http://example.com/elsie    ['sister']
12 http://example.com/lacie    ['sister']
13 http://example.com/tillie   ['sister']
14 '''
15 
16 #相应参数: find_all(self, name=None, attrs={}, recursive=True, text=None,limit=None, **kwargs):
17 
18 #------------------>>  2.1.1 name参数:name的五种过滤器: 字符串、正则表达式、列表、True、方法
19 #1.1、字符串:即标签名
20 # print(soup.find_all("a"))  # name="a"
21 
22 #1.2、正则表达式
23 # import re
24 # print(soup.find_all(re.compile('^p'))) #找出p开头的标签,结果有body和b标签
25 
26 '''
27 知识补充:re.compile()在正则表达式中的应用
28 cd = re.compile('abc{2}')
29 ret = re.findall(cd,"abccc")
30 print(ret)
31 
32 '''
33 
34 #1.3、列表:如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签:
35 # print(soup.find_all(["a","b"])) # name=["a","b"]  查找a标签和b标签
36 
37 #1.4、True:可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
38 # print(soup.find_all(True))
39 # for tag in soup.find_all(True):
40 #     print(tag.name)
41 
42 #1.5、方法:如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False
43 # def has_class_but_no_id(tag):
44 #     return tag.has_attr('class') and not tag.has_attr('id')
45 # print(soup.find_all(has_class_but_no_id))
46 
47 
48 
49 #------------------>> 2.1.2 属性参数 attrs={}
50 # print(soup.find_all("a",attrs={"class":"sister","id":"link2"}))
51 # print(soup.find_all("a",id="link2"))
52 # print(soup.find_all("a",class_="sister"))  #因为class是关键字,需要查找的话在class加下划线,形式为:class_
53 
54 #------------------>>  2.1.3 文本参数
55 # print(soup.find_all("a",text="Elsie"))
56 
57 #------------------>> 2.1.4 limit参数
58 # print(soup.find_all("a",limit=2)) #limit主要限制查找的条数
59 
60 #------------------>> 2.1.5 recursive参数
61 #recursive:调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,
62 # 如果只想搜索tag的直接子节点,可以使用参数 recursive=False .
63 
64 # print(soup.find_all("div",recursive=False))   ##结果为[],因为第一层没有div
65 # print("----------------")
66 # print(soup.body.find_all("div",recursive=False))   #有结果 因为当前层为body 也就是说只找第一层,下面的层次不管有没有都不会去找了
67 
68 #  局部查找
69 # print(soup.div.find_all(recursive=False))   ##只找div的子标签,子孙标签不管
70 
71 
72 ################################################ 2.2 find()
73 
74 # print(soup.find("a")) # 等同于 soup.a
75 #  find参数和find_all完全一样,但find只找一个标签
76 
77 ################################################ 三 selector ##################################################
78 
79 #  这个selector等同于css选择器
80 
81 # print(soup.select(".sister"))
82 # print(soup.select("#link2"))
83 # print(soup.select(".c1 a"))
View Code

 

 

详细请参考:https://www.cnblogs.com/pyedu/p/10303283.html

 

posted @ 2019-03-01 17:17  Mixtea  阅读(466)  评论(0编辑  收藏  举报