3-⾮结构化数据与结构化数据提取
正则表达式匹配规则
在 Python 中,我们可以使⽤内置的 re 模块来使⽤正则表达式。
有⼀点需要特别注意的是,正则表达式使⽤对特殊字符进⾏转义,所以如果我们要使⽤原始字符串,只需加⼀个 r 前缀,⽰例:
r'chuanzhiboke\t\.\tpython'
re 模块的⼀般使⽤步骤如下:
1. 使⽤compile()函数将正则表达式的字符串形式编译为⼀个Pattern对象
2. 通过Pattern对象提供的⼀系列⽅法对⽂本进⾏匹配查,获得匹配结果,⼀个 Match 对象。
3. 最后使⽤Match对象提供的属性和⽅法获得信息,根据需要进⾏其他的操作
compile 函数
compile 函数⽤于编译正则表达式,⽣成⼀个 Pattern 对象,它的⼀般使⽤形式如下:
import re
# 将正则表达式编译成 Pattern 对象
pattern = repile(r'\d+')
match ⽅法
match ⽅法⽤于查字符串的头部(也可以指定起始位置),它是⼀次匹配,只要到了⼀个匹配的结果就返回,⽽不是查所有匹配的结果。它的⼀般使⽤形式如下:
其中,string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。因此,当你不指定 pos 和 endpos 时,match ⽅法默认匹配字符串的头部。
match(string[, pos[, endpos]])
>>> import re
>>> pattern = repile(r'\d+')  # ⽤于匹配⾄少⼀个数字
>>> m = pattern.match('one12twothree34four')  # 查头部,没有匹配
>>> print (m)
None
>>> m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配
>>> print (m)
None
>>> m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配
>>> print (m)                                        # 返回⼀个 Match 对象
<_sre.SRE_Match object at 0x10a42aac0>
>>> m.group(0)  # 可省略 0
'12'
search ⽅法
  search ⽅法⽤于查字符串的任何位置,它也是⼀次匹配,只要到了⼀个匹配的结果就返回,⽽不是查所有匹配的结果,它的⼀般使⽤形式如下:
search(string[, pos[, endpos]])
其中,string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。当匹配成功时,返回⼀个 Match 对象,如果没有匹配上,则返回 None。
import re
>>> pattern = repile('\d+')
>>> m = pattern.search('one12twothree34four')  # 这⾥如果使⽤ match ⽅法则不匹配
>>> m
<_sre.SRE_Match object at 0x10cc03ac0>
>>> m.group()
'12'
>>> m = pattern.search('one12twothree34four', 10, 30)  # 指定字符串区间
>>> m
<_sre.SRE_Match object at 0x10cc03b28>
>>> m.group()
'34'
findall
⽅法
上⾯的 match 和 search ⽅法都是⼀次匹配,只要到了⼀个匹配的结果就返回。然⽽,在⼤多数时候,我们需要搜索整个字符串,获得所有匹配的结果。
findall ⽅法的使⽤形式如下:
findall(string[, pos[, endpos]])
其中,string 是待匹配的字符串,pos 和 endpos 是可选参数,指定字符串的起始和终点位置,默认值分别是 0 和 len (字符串长度)。
findall 以列表形式返回全部能匹配的⼦串,如果没有匹配,则返回⼀个空列表。
import re
pattern = repile(r'\d+')  # 查数字
result1 = pattern.findall('hello 123456 789')
result2 = pattern.findall('one1two2three3four4', 0, 10)
print (result1)
print (result2)
执⾏结果:
1 2['123456', '789'] ['1', '2']
split
⽅法
split ⽅法按照能够匹配的⼦串将字符串分割后返回列表,它的使⽤形式如下:1split(string[, maxsplit])
 其中,maxsplit ⽤于指定最⼤分割次数,不指定将全部分割。
1 2 3import re
p =repile(r'[\s\,\;]+') print(p.split('a,b;; c  d'))
  执⾏结果:['a', 'b', 'c', 'd']
sub
⽅法
sub ⽅法⽤于替换。它的使⽤形式如下:
sub(repl, string[, count])
其中,repl 可以是字符串也可以是⼀个函数:
如果 repl 是字符串,则会使⽤ repl 去替换字符串每⼀个匹配的⼦串,并返回替换后的字符串,另外,repl 还可以使⽤ id 的形式来引⽤分组,但不能使⽤编号 0;
如果 repl 是函数,这个⽅法应当只接受⼀个参数(Match 对象),并返回⼀个字符串⽤于替换(返回的字符串中不能再引⽤分组)。count ⽤于指定最多替换次数,不指定时全部替换。
1 2 3 4 5 6import re
p =repile(r'(\w+) (\w+)') # \w = [A-Za-z0-9]
s ='hello 123, hello 456'
print(p.sub(r'hello world', s))  # 使⽤ 'hello world' 替换 'hello 123' 和 'hello 456' print(p.sub(r'\2 \1', s))        # 引⽤分组
  执⾏结果:
1 2hello world, hello world 123hello, 456hello
匹配中⽂
在某些情况下,我们想匹配⽂本中的汉字,有⼀点需要注意的是,中⽂的 unicode 编码范围主要在 [u4e00-u9fa5],这⾥说主要是因为这个范围并不完整,⽐如没有包括全⾓(中⽂)标点,不过,在⼤部分情况下,应该是够⽤的。
假设现在想把字符串 title = u'你好,hello,世界' 中的中⽂提取出来,可以这么做:
1 2 3 4 5 6 7import re
title ='你好,hello,世界'
pattern =repile(r'[\u4e00-\u9fa5]+') result =pattern.findall(title)
print(result)
注意到,我们在正则表达式前⾯加上了两个前缀 ur,其中 r 表⽰使⽤原始字符串,u 表⽰是 unicode 字符串。执⾏结果:
1['你好', '世界']
注意:贪婪模式与⾮贪婪模式
1. 贪婪模式:在整个表达式匹配成功的前提下,尽可能多的匹配 ( * );
2. ⾮贪婪模式:在整个表达式匹配成功的前提下,尽可能少的匹配 ( ? );
3. Python⾥数量词默认是贪婪的。
主要通过正则匹配⾥⾯P标签的内容爬取内涵段⼦吧的笑话
1 2 3 4<h1 class="title">
<p>晴交了个男朋友,极为帅⽓。在⽗母旅游回来后,带他回了家。不料⼆⽼⼀见,竟⼗分反对。<br>在男友⾛后,母亲苦⼝婆⼼地告诉晴:“那个男⼈肯定靠不住!分⼿吧!”晴反驳:“你怎么知道!”遂和母亲赌⽓离家出⾛同居。母亲哭道:他爸,要不然告诉她实话吧!⽗亲吃了根蜡烛:只能这样了!
</p>
</h1>
这⾥需要注意⼀个是re.S是正则表达式中匹配的⼀个参数,,默认是不能匹配换⾏的,加
上re.S上之后就可以了
1
2import re
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17import requests
headers ={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"} r =("neihanshequ/",headers=headers)
t.decode()
data =re.findall(r'<h1 class="title">.*?<p>(.*?)</p>.*?</h1>',result,re.S)
print(data)
with open('xiaohua','a',encoding='utf-8') as f:
for i in data:
f.write(i)
f.write('\n')
爬取⾖瓣美剧和国产剧
json返回的数据如下:
我们只需要
"subject_collection_items"和"total"
View Code
XPath和xlmi库
为什么要学习XPATH和LXML类库:lxml是⼀款⾼性能的 Python HTML/XML 解析器,我们可以利⽤XPath,来快速的定位特定元素以及获取节点信息.
什么是XPATH:XPath (XML Path Language) 是⼀门在 HTML\XML ⽂档中查信息的语⾔,
可⽤来在 HTML\XML ⽂档中对元素和属性进⾏遍历。
lxml 是⼀个HTML/XML的解析器,主要的功能是如何解析和提取 HTML/XML 数据。
lxml和正则⼀样,也是⽤ C 实现的,是⼀款⾼性能的 Python HTML/XML 解析器,我们可以利⽤之前学习的XPath语法,来快速的定位特定元素以及节点信息。
需要安装C语⾔库,可使⽤ pip 安装:pip install lxml (或通过wheel⽅式安装)
初步使⽤
我们利⽤它来解析 HTML 代码,简单⽰例:
# 使⽤ lxml 的 etree 库
from lxml import etree
text = '''
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a> # 注意,此处缺少⼀个 </li> 闭合标签
</ul>
</div>
'''
#利⽤etree.HTML,将字符串解析为HTML⽂档html = etree.HTML(text)
# 按字符串序列化HTML⽂档
result = string(html).decode()
print(result)
输出结果:
1
2 3 4 5 6 7 8 9 10 11<html><body>
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>        <li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
</body></html>
  lxml 可以⾃动修正 html 代码,例⼦⾥不仅补全了 li 标签,还添加了 body,html 标签。除了直接读取字符串,lxml 还⽀持从⽂件⾥读取内容
⽂件读取:
除了直接读取字符串,lxml还⽀持从⽂件⾥读取内容。我们新建⼀个hello.html⽂件:
1 2 3 4 5 6 7 8 9 10 11<!-- hello.html -->
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>xpath语法 python
</div>
  再利⽤ etree.parse() ⽅法来读取⽂件。
1 2 3 4 5 6 7from lxml import etree
# 读取外部⽂件 hello.html
html =etree.parse('./hello.html')
result =string(html, pretty_print=True) print(result)
输出结果与之前相同
XPath实例测试
1. 获取所有的
<li>
1 2 3 4 5 6 7 8from lxml import etree
html =etree.parse('hello.html')
print type(html)  # 显⽰etree.parse() 返回类型result =html.xpath('//li')
print(result)  # 打印<li>标签的元素集合

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