# 页面解析和数据提取
- 结构数据: 先有的结构,在谈数据
- JSON文件
- JSON Path
- 转换成Python类型进行操作(json类)
- XML文件
- 转换成python类型(xmltodict)
- XPath
- CSS选择器
- 正则
- 非结构化数据:先有数据,再谈结构
- 文本
- 电话号码
- 邮箱地址
- 通常处理此类数据,使用正则表达式
- Html文件
- 正则
- XPath
- CSS选择器
# 正则表达式
- 一套规则,可以在字符串文本中进行搜查替换等
- 案例v23,re的基本使用流程
import re
"""
正则 re
使用步骤:
1.compile 函数将正则表达式的字符串生成一个Pattern 对象
2.通过Pattern 对象的一些方法对文本进行匹配,匹配结果是一个Match 对象
3.用Match 对象的方法,对结果操作
"""
if __name__ == '__main__':
s = r"\d+ \d+"
# s = r'(\w+) (\w+)'
pattern = re.compile(s)
# m = pattern.match("12 1one34two56three")
m = pattern.match("one two three four")
print(type(m))#<class '_sre.SRE_Match'>
print(m) #<_sre.SRE_Match object; span=(0, 4), match='12 1'>
print(m.group(0)) #12 1
# print(m.start(0)) #0
# print(m.end(0)) #4
# print(m.span(0))
print(m.groups())
- 案例v24,match的基本使用
'''
正则结果Match的使用案例
'''
import re
# 以下正则分成了两个组,以小括号为单位
s = r'([a-z]+) ([a-z]+)'
pattern = re.compile(s, re.I) # s.I表示忽略大小写
m = pattern.match("Hello world wide web")
# goup(0)表示返回匹配成功的整个子串
s = m.group(0)
print(s)
a = m.span(0) # 返回匹配成功的 整个子串的跨度
print(a)
# gourp(1)表示返回的第一个分组匹配成功的子串
s = m.group(1)
print(s)
a = m.span(1) # 返回匹配成功的第一个子串的跨度
print(a)
s = m.groups() #等价于m.gourp(1), m.group(2).......
print(s)
- 正则常用方法:
- match: 从开始位置开始查找,一次匹配
- search:从任何位置查找,一次匹配, 案例v25
"""
search
"""
import re
s = r'\d+'
pattern = re.compile(s)
m = pattern.search("one12two34three56")
print(m.group())
# 参数表明搜索的起始范围
m = pattern.search("one12two34three56",10,40)
print(m.group())
- findall: 全部匹配,返回列表, 案例v26
"""
findall 用法
"""
import re
parttern = re.compile(r"\d+")
m = parttern.findall("i am 18 years and 185 high")
print(type(m)) #<class 'list'>
s = [i for i in m ]
print(s)
mi = parttern.finditer("i am 18 years and 185 high")
print(type(mi)) #<class 'callable_iterator'>
im = [i.group() for i in mi]
print(im) #['18', '185']
- finditer: 全部匹配,返回迭代器, 案例v26
- split: 分割字符串,返回列表
- sub:替换
- 匹配中文
- 中文unicode范围主要在[u4e00-u9fa5]
- 案例v27
"""
匹配中文
"""
import re
s = u'你好 世界'
pattern = re.compile(r'[\u4e00-\u9fa5]+')
m = pattern.findall(s)
print(m)
- 贪婪与非贪婪模式
- 贪婪模式: 在整个表达式匹配成功的前提下,尽可能多的匹配
- 非贪婪模式: xxxxxxxxxxxxxxxxxxxxxx, 尽可能少的匹配
- python里面数量词默认是贪婪模式
- 例如:
- 查找文本abbbbbbccc
- re是 ab*
- 贪婪模式: 结果是abbbbbb
- 非贪婪: 结果是a
# XML
- XML(EXtensibleMarkupLanguage)
- http://www.w3school.com.cn/xml/index.asp
- 概念:父节点,子节点,先辈节点,兄弟节点,后代节点
# XPath
- XPath(XML Path Language), 是一门在XML文档中查找信息的语言,
- 官方文档: http://www.w3school.com.cn/xpath/index.asp
- XPath开发工具
- 开元的XPath表达式工具: XMLQuire
- chrome插件: Xpath Helper
- Firefox插件: XPath CHecker
- 常用路径表达式:
- nodename: 选取此节点的所有子节点
- /: 从根节点开始选
- //: 选取元素,而不考虑元素的具体为止
- .: 当前节点
- ..:父节点
- @: 选取属性
- 案例:
- booksotre: 选取bookstore下的所有子节点
- /booksotre: 选取根元素
- booksotre/book: 选取bookstore的所有为book的子元素
- //book: 选取book子元素
- //@lang:选取名称为lang的所有属性
- 谓语(Predicates)
- 谓语用来查找某个特定的节点,被向前在方括号中
- /bookstore/book[1]: 选取第一个属于bookstore下叫book的元素
- /bookstore/book[last()]: 选取最后一个属于bookstore下叫book的元素
- /bookstore/book[last()-1]: 选取倒数第二个属于bookstore下叫book的元素
- /bookstore/book[position()<3]: 选取属于bookstore下叫book的前两个元素
- /bookstore/book[@lang]: 选取属于bookstore下叫book的,含有属性lang元素
- /bookstore/book[@lang="cn"]: 选取属于bookstore下叫book的,含有属性lang的值是cn的元素
- /bookstore/book[@price < 90]: 选取属于bookstore下叫book的,含有属性price的,且值小于90的元素
- /bookstore/book[@price < 90]/title: 选取属于bookstore下叫book的,含有属性price的,且值小于90的元素的子元素title
- 通配符
- `*` : 任何元素节点
- @*: 匹配任何属性节点
- node(): 匹配任何类型的节点
- 选取多个路径
- //book/tile | //book/author : 选取book元素中的title和author元素
- //tile | //price: 选取文档中所有的title和price元素
# lxml库
- python的HTML/XML的解析器
- 官方文档: http://lxml.de/index.html
- 功能:
- 解析HTML,案例v29.py
"""
安装lxml
"""
from lxml import etree
"""
用lxml 解析HTML代码
"""
text ='''
<div>
<ul>
<li class="item-0"> <a href="0.html"> first item </a></li>
<li class="item-1"> <a href="1.html"> first item </a></li>
<li class="item-2"> <a href="2.html"> first item </a></li>
<li class="item-3"> <a href="3.html"> first item </a></li>
<li class="item-4"> <a href="4.html"> first item </a></li>
<li class="item-5"> <a href="5.html"> first item </a>
</ul>
</div>
'''
# 利用etree.HTML 把字符串解析成HTML文档
html = etree.HTML(text)
s = etree.tostring(html)
#自动补全</li> 标签
print(s.decode())
- 文件读取,案例v30.html, v31.py
<?xml version="1.0" encoding="utf-8"?>
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Gidada De</author>
<year>2018</year>
<price>23</price>
</book>
<book category="education">
<title lang="en">Python is Python</title>
<author>Food War</author>
<year>2008</year>
<price>83</price>
</book>
<book category="sport">
<title lang="en">Running</title>
<author>Klaus Kuka</author>
<year>2010</year>
<price>43</price>
</book>
</bookstore>
from lxml import etree
html = etree.parse("./v30.html")
rst = etree.tostring(html,pretty_print=True)
print(rst)
- etree和XPath的配合使用, 案例v32.py
from lxml import etree
html = etree.parse("./v30.html")
# print(type(html)) #<class 'lxml.etree._ElementTree'>
# print(html) #<lxml.etree._ElementTree object at 0x0000018FA2F4E348>
rst = html.xpath("//book")
# print(type(rst)) #<class 'list'>
# print(rst) #[<Element book at 0x2369dd2e2c8>, <Element book at 0x2369dd2e408>, <Element book at 0x2369dd2e448>]
# bs = [i.text for i in rst]
# print(bs)
rst1 = html.xpath("//book[@category='sport']")
# print(type(rst1)) #<class 'list'>
# print(rst1) #[<Element book at 0x22670e9e3c8>]
rst2 = html.xpath("//book[@category='sport']/year")
# print(type(rst2)) #<class 'list'>
# print(rst2) #[<Element book at 0x22670e9e3c8>]
rst2 = rst2[0]
print(rst2.tag)
print(rst2.text)