1.0爬虫正则表达式,xpath,写匹配这些就够了

正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")
正则表达式用来匹配,检索,替换和分割那些符合规定模式规则的文本

一.re正则表达式的方法介绍

re模块具有python全部正则表达式功能,使用 import re 导入这个模块:

import re
re.match() #从开始位置开始匹配,如果开头没有则无
re.search() #搜索整个字符串,返回一个对象
re.sub()    
re.findall() #搜索整个字符串,返回一个list
re.finditer()

在这里插入图片描述

re.match()

格式:re.match(pattern, string, flags=0)
re.match()在string中从头开始检索符合pattern的字符串,匹配一次成功即返回,开始检索不到则匹配失败,函数返回None

>>> re.match('yang','yangsss')
<re.Match object; span=(0, 4), match='yang'>

注:这里的flag 是模式修正符,比如re.I 是模式修正符的忽略大小写.修正正则表达式,后面会详细演示

在这里插入图片描述

re.search()

格式:re.search(pattern, string, flags=0)
re.search()在string中检索符合pattern的字符串,匹配一次成功即返回,并不要求必须从字符串的开头进行匹配

>>> re.search('yang','ddddyangssyangs')
<re.Match object; span=(4, 8), match='yang'>

注:
match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:
group() 返回被 re 匹配的字符串
start() 返回匹配开始的位置
end() 返回匹配结束的位置
span() 返回一个元组包含匹配 (开始,结束) 的位置,跨度

>>> re.match('yang','yangsss').group()
'yang'
>>> re.match('yang','yangsss').start()
0
>>> re.match('yang','yangsss').end()
4
>>> re.match('yang','yangsss').span()
(0, 4)


>>> re.search('yang','ddddyangssyangs').group()
'yang'
>>> re.search('yang','ddddyangssyangs').start()
4
>>> re.search('yang','ddddyangssyangs').end()
8
>>> re.search('yang','ddddyangssyangs').span()
(4, 8)
re.sub()

格式:re.sub(pattern, repl, string, count=0, flags=0)
在字符串 string 把符合 pattern的字符串替换为 repl
pattern : 要被替换的字符串
repl : 被替换后的字符串
string :要被检索的字符串
count : 模式匹配后替换的最大次数,默认0表示替换所有的匹配

>>> re.sub('A','a','AFFAHHA')
'aFFaHHa'
>>> re.sub('A','a','AFFAHHA',0)
'aFFaHHa'
>>> re.sub('A','a','AFFAHHA',1)
'aFFAHHA'
>>> re.sub('A','a','AFFAHHA',2)
'aFFaHHA'
>>> re.sub('A','a','AFFAHHA',3)
'aFFaHHa'

在这里插入图片描述

re.compile()

格式:re.compile(pattern,flags=0)
编译正则表达式模式,返回一个正则对象,使用这个对象调用match,search,sub等方法,可以提高一点效率
(可以把那些常用的正则表达式编译成正则表达式对象,这样可以提高一点效率)

>>> pattern = re.compile(r'\d+')
>>> pattern.match('12twothree34four')
<re.Match object; span=(0, 2), match='12'
>>> pattern.search('one12twothree34four')
<re.Match object; span=(3, 5), match='12'>
>>> pattern.sub('#','one12twothree34four')
'one#twothree#four'

在这里插入图片描述

re.findall()

格式:re.findall(pattern, string, flags=0)
在字符串string中找到正则表达式pattern所匹配的所有的字符串,并返回一个列表,如果没有找到匹配的,则返回空列表.

>>> re.findall(r"doc","https://docs.python.org/3/whatsnew/doctype/3.6.html")
['doc', 'doc']

在这里插入图片描述

re.finditer()

格式:re.finditer(pattern,string,flags=0)
在字符串string中找到正则表达式pattern所匹配的所有的字符串,把它们作为一个迭代器返回,需要迭代获取数据,节省内存开销

>>> re.finditer('you','Life was like a box of chocolates, you never know what you are going to get.')
<callable_iterator object at 0x00000000022D35C8>
>>> res = re.finditer('you','Life was like a box of chocolates, you never know what you are going to get.')
>>> for i in res:
...     i
...
<re.Match object; span=(35, 38), match='you'>
<re.Match object; span=(55, 58), match='you'>

在这里插入图片描述

二.正则表达式字符介绍

在这里插入图片描述
通用字符:
在这里插入图片描述
元字符:
在这里插入图片描述
模式修正符:
在这里插入图片描述

三. 正则表达式的案例实战

1. 正则表达式在Python中的使用–解析数据

案例要求:
如下图所示有一个网页文件,请使用Python的正则将网页中的title正文,超级链接信息(名称和url地址)取出输出
实现步骤:使用open()、read()读取文件内容,导入re模块,使用正则匹配后遍历输出.

<!DOCTYPE html>
<html>
<head>
    <title>Python 正则表达式实例</title>
</head>
<body>
    <h2>常用网站链接</h2>
    <ul>
        <li><a href="https://www.python.org">Python官方网站</a></li>
        <li><a href="https://www.djangoproject.com">Django官方网站</a></li>
        <li><a href="https://www.baidu.com">百度搜索引擎</a></li>
        <li><a href="https://blog.csdn.net">CSDN官方网站</a></li>
        <li><a href="https://edu.csdn.net/">CSDN学院</a></li>
    </ul>
</body>
</html>

实现代码:

import re
f = open("./index.html","r",encoding='UTF-8')
content = f.read()
f.close()

#print(content)
# .*? 任意字符一次或者多次,禁止贪婪
title = re.search("<title>(.*?)</title>",content)
if title:
    print(title)
    print("标题:"+title.group(1))
# .*?   任意字符一次或者多次,禁止贪婪
alist = re.findall('<a href="(.*?)">(.*?)</a>',content)  

for ov in alist:
    print(ov[1]+":"+ov[0])

在这里插入图片描述

2. 正则表达式在JavaScript中的使用–表单验证

案例要求:参考下图,使用JavaScript语言实现页面中表单的验证功能。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>JavaScript--实例</title>
    </head>
    <body>
        <h3 id="hid">JavaScript实例--表单事件</h3>
        <form action="my.html" name="myform" method="post" onsubmit="return doSubmit()">
            账号:<input type="text" name="uname"/> 8-16位的有效字符<br/><br/>
            密码:<input type="password" name="upass"/> 6-18<br/><br/>
            邮箱:<input type="text" name="email"/> <br/><br/>
            <input type="submit" value="提交"/>
        </form>
      <script type="text/javascript">
         //表单提交事件处理
         function doSubmit(){
            //验证账号
            var name = document.myform.uname.value;
            if(name.match(/^\w{8,16}$/)==null){
                alert("账号必须为8-16的有效字符!");
                return false;
            }
            //验证密码
            var pass = document.myform.upass.value;
            if(pass.match(/^.{6,18}$/)==null){
                alert("密码必须为6-18位!");
                return false;
            }
            //验证邮箱
            var email = document.myform.email.value;
            if(email.match(/^\w+@\w+(\.\w+){1,2}$/)==null){
                alert("请输入正确的Email地址!");
                return false;
            }
            return true;
         }
      </script>
    </body>
</html>

在这里插入图片描述

3. 正则表达式在MySQL数据库中的使用–数据查询
MariaDB [mydb]> select * from stu;
+----+----------+-----+-----+----------+
| id | name     | age | sex | classid  |
+----+----------+-----+-----+----------+
|  1 | zhangsan |  22 | m   | python03 |
|  2 | lisi     |  25 | w   | python04 |
|  3 | wangwu   |  20 | m   | python03 |
|  4 | zhaoliu  |  19 | w   | python04 |
|  5 | qq01     |  20 | m   | python03 |
|  6 | qqmn     |  21 | w   | python04 |
|  7 | qq03     |  20 | m   | python05 |
|  8 | uu01     |  21 | w   | python04 |
|  9 | uu02     |  20 | m   | python05 |
| 10 | aa       |  29 | w   | python03 |
| 11 | bb       |  20 | m   | python04 |
| 16 | abc      |  25 | m   | python05 |
+----+----------+-----+-----+----------+
12 rows in set (0.00 sec)

– 使用正则查询姓名是使用任意两位小写字母构成的数据信息

MariaDB [mydb]> select * from stu where name regexp '^[a-z]{2}$';
+----+------+-----+-----+----------+
| id | name | age | sex | classid  |
+----+------+-----+-----+----------+
| 10 | aa   |  29 | w   | python03 |
| 11 | bb   |  20 | m   | python04 |
+----+------+-----+-----+----------+
2 rows in set (0.00 sec)

--查询name的值为2~4位的小写字母
MariaDB [mydb]> select * from stu where name regexp '^[a-z]{2,4}$';
+----+------+-----+-----+----------+
| id | name | age | sex | classid  |
+----+------+-----+-----+----------+
|  2 | lisi |  25 | w   | python04 |
|  6 | qqmn |  21 | w   | python04 |
| 10 | aa   |  29 | w   | python03 |
| 11 | bb   |  20 | m   | python04 |
| 16 | abc  |  25 | m   | python05 |
+----+------+-----+-----+----------+
5 rows in set (0.00 sec)

-- 查询name字段值是由两位字母加两位数字构成的数据信息
MariaDB [mydb]> select * from stu where name regexp '^[a-z]{2}[0-9]{2}$';
+----+------+-----+-----+----------+
| id | name | age | sex | classid  |
+----+------+-----+-----+----------+
|  5 | qq01 |  20 | m   | python03 |
|  7 | qq03 |  20 | m   | python05 |
|  8 | uu01 |  21 | w   | python04 |
|  9 | uu02 |  20 | m   | python05 |
+----+------+-----+-----+----------+
4 rows in set (0.00 sec)

MariaDB [mydb]>
4.正则表达式练习题:

1、 匹配一段文本中的每行的邮箱
y=‘123@qq.comaaa@163.combbb@126.comasdfasfs33333@adfcom’
2、 匹配一段文本中的每行的时间字符串,比如:‘1990-07-12’
time=‘asfasf1990-07-12asdfAAAbbbb434241’
3、 匹配一段文本中所有的身份证数字
a=‘sfafsf,34234234234,1231313132,154785625475896587,sdefgr54184785ds85,4864465asf86845’
4、匹配qq号。(腾讯QQ号从10000开始) [1,9][0,9]{4,}
q=‘3344,88888,7778957,10000,99999,414,4,867287672’
5、 匹配出所有整数
a=‘1,-3,a,-2.5,7.7,asdf’

1、 匹配一段文本中的每行的邮箱
y='123@qq.comaaa@163.combbb@126.comasdfasfs33333@adfcom'
import re
ret=re.findall('\w+@(?:qq|163|126).com',y)
print(ret)
2、 匹配一段文本中的每行的时间字符串,比如:‘1990-07-12’;
time='asfasf1990-07-12asdfAAAbbbb434241'
import re
ret=re.search(r'(?P<year>19[09]\d)-(?P<month>\d+)-(?P<days>\d+)',time)
print(ret.group('year'))
print(ret.group('month'))
print(ret.group('days'))
3、 匹配一段文本中所有的身份证数字。
a='sfafsf,34234234234,1231313132,154785625475896587,sdefgr54184785ds85,4864465asf86845'
import re
ret=re.findall('\d{18}',a)
print(ret)
4、 匹配qq号。(腾讯QQ号从10000开始)1,9[0,9]{4,}
q='3344,88888,7778957,10000,99999,414,4,867287672'
import re
ret=re.findall('[1-9][0-9]{4,}',q)
print(ret)
5、 匹配出所有整数
a='1,-3,a,-2.5,7.7,asdf'
import re
ret=re.findall(r"'(-?\d+)'",str(re.split(',',a)))
print(ret)

在这里插入图片描述

四.解析库的使用–xpath:

xpath(XML Path Language)是一门在XML文档中查找信息的语言。
xpath可用来在XML文档中对元素和属性进行遍历。
官方网址 :http://lxml.de
官方文档 : http://lxml.de/api/index.html
教程网站 : https://www.w3school.com.cn/xpath/index.asp
注:XQuery 是用于 XML 数据查询的语言(类似SQL查询数据库中的数据)
注:XPointer 由统一资源定位地址(URL)中#号之后的描述组成,类似于HTML中的锚点链接
python中如何安装使用XPath:
①: 安装 lxml pip install lxml
②: from lxml import etree
③: Selector = etree.HTML(网页源代码)
④: Selector.xpath(一段神奇的符号)
在这里插入图片描述

在这里插入图片描述

1.解析案例:

首先创建一个html文件:my.html 用于测试xpath的解析效果

<!DOCTYPE html>
<html>
<head>
    <title>我的网页</title>
</head>
<body>
    <h3 id="hid">我的常用链接</h3>
    <ul>
        <li class="item-0"><a href="http://www.baidu.com">百度</a></li>
        <li class="item-1 shop"><a href="http://www.jd.com">京东</a></li>
        <li class="item-2"><a href="http://www.sohu.com">搜狐</a></li>
        <li class="item-3"><a href="http://www.sina.com">新浪</a></li>
        <li class="item-4 shop"><a href="http://www.taobao.com">淘宝</a></li>
    </ul>
</body>
</html>

使用XPath解析说明
# 导入模块
from lxml import etree
# 读取html文件信息(在真实代码中是爬取的网页信息)
f = open("./my.html",'r',encoding="utf-8")
content = f.read()
f.close()

# 解析HTML文档,返回根节点对象
html = etree.HTML(content)
#print(html)  # <Element html at 0x103534c88>

# 获取网页中所有标签并遍历输出标签名
result = html.xpath("//*")
for t in result:
    print(t.tag,end=" ")
#[html head title body h3 ul li a li a ... ... td]
print()
# 获取节点
result = html.xpath("//li") # 获取所有li节点
result = html.xpath("//li/a") # 获取所有li节点下的所有直接a子节点
result = html.xpath("//ul//a") # 效果同上(ul下所有子孙节点)
result = html.xpath("//a/..") #获取所有a节点的父节点
print(result)
# 获取属性和文本内容
result = html.xpath("//li/a/@href") #获取所有li下所有直接子a节点的href属性值
result = html.xpath("//li/a/text()") #获取所有li下所有直接子a节点内的文本内容
print(result) #['百度', '京东', '搜狐', '新浪', '淘宝']
result = html.xpath("//li/a[@class]/text()") #获取所有li下所有直接含有class属性子a节点内的文本内容
print(result) #['百度', '搜狐', '新浪']
#获取所有li下所有直接含有class属性值为aa的子a节点内的文本内容
result = html.xpath("//li/a[@class='aa']/text()") 
print(result) #['搜狐', '新浪'
#获取class属性值中含有shop的li节点下所有直接a子节点内的文本内容
result = html.xpath("//li[contains(@class,'shop')]/a/text()") 
print(result) #['搜狐', '新浪'
# 按序选择
result = html.xpath("//li[1]/a/text()") # 获取每组li中的第一个li节点里面的a的文本
result = html.xpath("//li[last()]/a/text()") # 获取每组li中最后一个li节点里面的a的文本
result = html.xpath("//li[position()<3]/a/text()") # 获取每组li中前两个li节点里面的a的文本
result = html.xpath("//li[last()-2]/a/text()") # 获取每组li中倒数第三个li节点里面的a的文本
print(result) 	

print("--"*30)
# 节点轴选择
result = html.xpath("//li[1]/ancestor::*") # 获取li的所有祖先节点
result = html.xpath("//li[1]/ancestor::ul") # 获取li的所有祖先中的ul节点
result = html.xpath("//li[1]/a/attribute::*") # 获取li中a节点的所有属性值
result = html.xpath("//li/child::a[@href='http://www.sohu.com']") #获取li子节点中属性href值的a节点
result = html.xpath("//body/descendant::a") # 获取body中的所有子孙节点a
print(result) 

result = html.xpath("//li[3]") #获取li中的第三个节点    
result = html.xpath("//li[3]/following::li") #获取第三个li节点之后所有li节点
result = html.xpath("//li[3]/following-sibling::*") #获取第三个li节点之后所有同级li节点
for v in result:
    print(v.find("a").text)

解析案例

# 导入模块
from lxml import etree

# 读取html文件信息(在真实代码中是爬取的网页信息)
f = open("./my.html",'r')
content = f.read()
f.close()

# 解析HTML文档,返回根节点对象
html = etree.HTML(content)

# 1. 获取id属性为hid的h3节点中的文本内容
print(html.xpath("//h3[@id='hid']/text()")) #['我的常用链接']


# 2. 获取li中所有超级链接a的信息
result = html.xpath("//li/a")
for t in result:
    # 通过xapth()二次解析结果
    #print(t.xpath("text()")[0], ':', t.xpath("@href")[0])

    # 效果同上,使用节点对象属性方法解析
    print(t.text, ':', t.get("href"))

'''
#结果:
百度 : http://www.baidu.com
京东 : http://www.jd.com
搜狐 : http://www.sohu.com
新浪 : http://www.sina.com
淘宝 : http://www.taobao.com
'''

'''
HTML元素的属性:
    tag:元素标签名
    text:标签中间的文本
HTML元素的方法:
    find()    查找一个匹配的元素
    findall() 查找所有匹配的元素    
    get(key, default=None) 获取指定属性值
    items()获取元素属性,作为序列返回
    keys()获取属性名称列表
    value是()将元素属性值作为字符串序列
'''

在这里插入图片描述

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨安尧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值