一、正则表达式
目录
1.1正则表达式简介和match函数
1.2预定义字符集
1.3元字符
1.4重复匹配
1.5贪婪匹配和非贪婪匹配
1.6re模块介绍
1.7模块分组
二、xpath使用
2.1xpath简介
2.2xpath语法说明
2.3模块的使用
三、Beautifulsoup
目录
3.1 bs4对象
3.2 bs4的使用
3.3 遍历子节点
3.4 遍历父节点和兄弟节点
3.5搜索树
3.6 find和find_all方法
1.1正则表达式简介和match函数
首先使用pip install re 下载re模块
一、正则表达式
官方解释呢是对字符串的操作的逻辑公式,用事先定义好的字符串以及特定的组合对数据筛选的一种逻辑结构。用大白话来说就是用一些指定的字符串去匹配你想要得到的数据而,正则表达式就是教你如何使用正确的字符串取匹配
二、match函数
match函数是作为新手来了解正则表达式的入门函数
使用方法为:
re.match((pattern,string,flags=0))
第一个参数是匹配的正则表达式,如果匹配成功就会返回一个match对象如果不成功则返回一个none对象
第二个参数是需要匹配的字符串
第三个参数是匹配的字符串需不需要特殊处理列如:“需不需要大小写”(往后的内容会涉及如何正确使用)
例子如下
import re
s = 'python and java'
pattern = 'python'
result = re.match(pattern,s)
# print(result.group())
if result:
print(result.group())
print(result.start())
print(result.end())
print(result.span())
else:
print('none')
match函数有四种返回方式
result.group() 返回的是爬取的数据
result.start() 返回的是爬取数据开始的位置
result.end() 返回的是爬取数据结束的位置
result.span() 返回的是爬取数据的长度
match函数只能从匹配数据的前方查找不能在匹配数据的后方中查找
1.2预定义字符集
表达式 | 匹配 |
---|---|
\d | 表示0-9中的一个数字 |
\w | 表示字母、数字中的一个列如 A-Z a-z 0-9 中的任意一个 |
\s | 空格、制表符、换页符其中一个 |
\S | \s的反集 |
\D | \d的反集 |
\S | \s的反集 |
1.3元字符
元字符定义:
正则表达式中运用一些特殊的元字符来表示一些特殊的含义
元字符 | 对应的含义 |
---|---|
[ ] | 匹配字符集中的一个字符 |
- | 匹配某一范围内的某一元素 列如a-z就是取a-z的一个字符 |
\ | 转义字符 |
. | 小数点可以匹配除换行符之后的任意一个字符 |
[^] | 对字符集求反,也就是取反字符集中的一个元素 |
| | 逻辑或操作符 |
() | 对表达式进行分组,将圆括号的内容看作一个整体 |
例子如下
小数点可以匹配除换行符之外的任意一个字符
列如
import re
result = re.match('a.c','abc')
print(result.group()) 返回的值是abc
2. | 逻辑或操作符
import re
result = re.match('a|c','abc')
print(result.group())
返回a
3. [ ]匹配字符集中的一个字符
import re
result = re.match('[abc]2','a2')
print(result.group()返回的值是a2
4.[ ^] 对字符集求反
import re
result = re.match('速度与激情[^12345678]','速度与激情9')
print(result.group())返回的值是速度与激情9
5.- 定义[ ]里的一个字符区间 列如[a-z]
import re
result = re.match('速度与激情[1-8]','速度与激情2')
print(result.group())
6. \ 对紧跟其后的一个字符进行转义
import re
result = re.match('速度.与激情[1-8]','速度a与激情2')
print(result.group())
如果不使用/则返回的值是速度a与激情2
import re
#result = re.match('a.c','abc')
result = re.match('速度\.与激情[1-8]','速度.与激情2')
print(result)使用\返回的是速度.与激情2
拓展一些常见的转义字符
转义字符 | 匹配 |
---|---|
\r.\n | 匹配回车和换行符 |
\t | 匹配制表符 |
\ | 匹配反斜杠\ |
\^ \% | 匹配 ^和%字符 |
\. | 匹配小数点 |
1.4重复匹配
直接使用代码来展现
1.{n}表示前面的表达式重复n次
import re
result = re.match(r'\d{3}','1234')
print(result.group())
2.{m,n}表示前面的表达式至少重复m次最多重复n次
import re
result = re.match(r'\d{3,5}','1234abc')
print(result.group())
3.{m,}表示前面的表达式至少重复m次
import re
result = re.match(r'\d{3,}\w{3,}','1234abc')
print(result.group())
4 ?表示表达式至少重复0次或1次
import re
result = re.match(r'[1-9]?','1234abc')
print(result.group()) 最后的值只返回1
5.+表示表达式只能重复1-n次
import re
result = re.match(r'[1-9]+','1234abc')
print(result.group())
6.*表示表达式可以重复0-n次
* import re
result = re.match(r'[1-9]*','abc')
print(result.group())
1.5贪婪匹配和非贪婪匹配
贪婪匹配定义
表示通过正则表达式尽可能多的获取与条件相对应的数据,而非贪婪表达式则与之相反,获取一个相对应的数据
代码实例如下
import re
s = '<div>abc<div><div>bcd<div>'
#贪婪匹配
result = re.match(r'<div>.*<div>',s)
print(result.group())
#非贪婪匹配
result1 = re.match(r'<div>.*?<div>',s)
print(result1.group())
1.6 re模块介绍
1.6.1 compile
compile类似于正则表达式的一个加工厂,可以将字符串表示的正则表达式变成一个对象 举个例子
import re
res = re.compile(r'abc')
print(res.match('abc1234').group())
返回的是abc
1.6.2 search函数
search函数类似于match函数都是匹配字符的函数,但是search函数可以匹配到后面的数据,而match函数只可以匹配前面的数据。
列如
print(re.search(r’abc’,‘123abc’))可以匹配到abc,但是match函数则会报错。
1.6.3 findall函数
findall函数可以匹配到所有符合条件的字符,并返回一个列表类型。
例如:re.findall(r’abc’,‘123abc123abc’) 可以返回两个abc
1.6.4 split函数
split函数用来切割一个表达式 ,切割后以列表形式返回。
split函数中传入的第一个参数是切割某一表达式的条件,第二个参数是所切割的表达式,第三个参数可加也可不加maxsplit=n 表示切割的次数。
例如:
w = '8*3+2/2'
res = re.split(r'[\+\*\/]',w,maxsplit=2)
print(res),返回的值是[8,3,2/2]
1.6.5 sub函数
类似于字符串的replace函数用来替换对应的字符
w = 'i am a boy i have a girlfriend i donot like play'
res = re.sub(r'i','I',w)
print(res)
表示将w中的所有i替换成I
1.7模块分组
import re
text = 'apple is $99,banana is $88'
res=re.search(r'.+(\$\d+).+(\$\d+)',text)
print(res.group())
print(res.group(1))
print(res.group(2))
print(res.groups())
返回结果依次如下
apple is $99,banana is $88
$99
$88
('$99', '$88')
group表示返回匹配分组
group(1)表示匹配第一个分组
group(2)表示匹配第二个分组
groups()表示返回两个分组
二、xpath
2.1 xpath简介
1.xpath是xml的一种查询语言,可以在xml中查询相应的节点信息通过元素和属性进行导航。
2.xml是标志类文本语言和html类似,可以通过lxml模块将html解析为xml语言
xpath分为子节点和父节点还有兄弟节点
表达式 | 匹配 |
---|---|
nodetime | 选取此节点所有节点 |
\ | 从根节点开始选取 |
\\ | 表示从当前节点开始选取 |
. | 表示当前节点 |
… | 表示上一层节点 |
@ | 表示选取当前属性 |
2.2 xpath语法说明
查找某个特定节点或者包含某个指定值的节点。
列如:
- /bookstore/book[1] 选取属于bookstore元素下的第一个book元素。
- /bookstore/book[last()]选取book元素下的最后一个bookstore元素
- /bookstore/book[last()-1] 选取bookstore元素下的倒数第二个book元素
- /bookstore/book[postion() < 3]选取前两个属于bookstore的book元素
- //title[@lang]选取属性为lang的title元素
2.3 xpath模块的使用
1.首先使用xpath语法要先将得到的数据变成一个对象。HTML和xml数据利用etree.element方法将字符串转化为lement对象
2.etree作用
可以将html转化为element对象
element又可以转化为字符串或者二进制数据
3.etree作用
首先将得到的网页源码来创建一个对象使用 element = etree.HTML(网页源码)
第二步可以将网页源码打印出来 res = etree.torsting(element)得到一个字节流数据第三步将字节流数据转化为字符串数据 result = res.decode()
第四步选取数据时使用xpath语法 html = element.xpath()来选取数据(返回一个列表类型) 使用/text来选取标签下的文本数据
4.xpath爬取豆瓣实例
xpath爬取豆瓣前十页内容
三、 bs4
3.1 bs4对象
1.tag 标签
2.element 注释
3.Beautifulsoup bs4对象
4.NavigableString 可导航的字符串
3.2 bs4的使用
Bs4与xpath相同都是要先定义一个对象,然后使用对象.属性来调用叫做标签法来获得想要的数据
通过代码来形象的表示
import requests
from bs4 import BeautifulSoup
url = "https://movie.douban.com/top250?start=25&filter="
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
}
res=requests.get(url,headers=headers)
res.encoding='utf-8'
re=res.text
soup = BeautifulSoup(re,'lxml')
print(soup.title)#选择第一个是title的标签
print(soup.title.name)#获取标签的名字
print(soup.title.string)#获取标签的内容
print(soup.find('title'))#获取第一个title标签
print(len(soup.find_all('title')))#获取所有的title标签
soup.find_all返回的是一个列表类型因此调用需要通过遍历来实现,
re=soup.find_all('a')
for res in re:#由于返回的是列表类型因此需要遍历输出
print(res.get('href'))
当要得到某个标签下的某个属性时需要调用get方法
使用对象.标签[‘属性’]来获取一个属性的值
3.3遍历子节点
- contents返回的是一个列表
2.Children 返回的是一个迭代器,通过这个迭代器可以进行迭代
3.descendants 返回的是一个生成器白能力子子孙孙
通过代码来形象表达
from bs4 import BeautifulSoup
element = '''<!DOCTYPE html>
<html lang="zh-CN" class="ua-windows ua-webkit">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="renderer" content="webkit">
<meta name="referrer" content="always">
<meta name="google-site-verification" content="ok0wCgT20tBBgo9_zat2iAcimtN4Ftf5ccsh092Xeyw" />
<title>
豆瓣电影 Top 250
</title>
'''
#contents返回爬取数据的所有内容以列表形式返回
soup = BeautifulSoup(element,'lxml')
#link = soup.contents
#print(link)
#children返回的是迭代其子孙节点
link = soup.head.children#同样以列表形式返回,对象.父节点.children(子孙)
for li in link:
print(li)
#descendantas 返回一个生成器遍历子孙
# link = soup.descendants
# for li in link:
# print('____')
# print(li)
# link = soup.strings
# for lin in link:
# print(lin)
其中string表示返回标签里的内容(字符串)
strings表示返回标签内所有的内容
stripped_strings 也同样表示返回标签内所有的内容,但是删除所有空格。
3.4遍历父节点和兄弟节点
1.parent表示获得父节点
2.parents 表示获得所有父节点
3.next_sibling 下一个兄弟节点
4.previous_sibling上一个兄弟节点
5.next_siblings 下一个所有兄弟节点
6.previous_siblings 上一个所有兄弟节点
实例代码如下
from bs4 import BeautifulSoup
element = '''<!DOCTYPE html>
<html lang="zh-CN" class="ua-windows ua-webkit">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="renderer" content="webkit">
<meta name="referrer" content="always">
<meta name="google-site-verification" content="ok0wCgT20tBBgo9_zat2iAcimtN4Ftf5ccsh092Xeyw" />
<title>
豆瓣电影 Top 250
</title>
'''
soup = BeautifulSoup(element,'lxml')
#for pa in soup.meta.parents:#遍历meta所有的父节点
#print(pa)
html = soup.find(content="ok0wCgT20tBBgo9_zat2iAcimtN4Ftf5ccsh092Xeyw")
for x in html.previous_siblings:
print(x)
3.5搜索树
from bs4 import BeautifulSoup
import re
element = '''<!DOCTYPE html>
<html lang="zh-CN" class="ua-windows ua-webkit">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="renderer" content="webkit">
<meta name="referrer" content="always">
<meta name="google-site-verification" content="ok0wCgT20tBBgo9_zat2iAcimtN4Ftf5ccsh092Xeyw" />
<title>
豆瓣电影 Top 250
</title>
'''
soup = BeautifulSoup(element,'lxml')
#字符串过滤器
#print(soup.find_all('title'))
#正则表达式过滤器 compile方法 re.compile是创建一个对象
#print(soup.find_all(re.compile('t')))
#列表过滤器列表中可以传入多个字符串(查询的标签)
#print(soup.find_all(['meta','title']))
#方法过滤器
# def fn(tag):
# return tag.has_attr('content')#传入的是一个属性
# print(soup.find_all(fn))
# print(soup.get('name="referrer"'))
3.6 find和find_all方法
首先find和find_all方法均是通过查找标签和属性来定位数据所在位置并提取出对应条件的数据,但是find方法只能提取出第一个符合条件的数据
find_all格式:soup.find_all(tag(标签),attr(属性),recursive(是否递归text(文本内容),limit(限制返回条数),kwargs(关键词参数))
``代码示例如下
from bs4 import BeautifulSoup
import re
element = '''<div id="csdn-toolbar" class="csdn-toolbar tb_disnone "> </div>
<div class="container row center-block " id="csdn_container_tool"> </div>
<ul class="pull-left left-menu clearfix" id="nav-left-menu">
<li class="app-control app-app">
<a href="https://www.csdn.net" title="CSDN首页" class=""><img src="//csdnimg.cn/cdn/content-toolbar/csdn-logo.png?v=20200416.1" class="csdn-logo"></a> <div class="appControl"> <span> <img src="https://csdnimg.cn/public/common/toolbar/images/csdnqr@2x.png"> <em>CSDN</em> </span> </div> </li> <li class="sub-menu-box" data-sub-menu-type="blog" data-report-click="{"mod":"popu_336","dest":"https://blog.csdn.net/","extend1":"博客"}"> <a href="//blog.csdn.net/" class="toolbar_to_feed" title="博客">博客</a> <div class="sub-menu"><a target="_blank" content="创作中心" href="//mp.csdn.net?utm_medium=fe.tool_bar_second.blog.creative_center" data-report-click="{"mod":"1593505904_001"}">创作中心</a></div></li> <li data-report-click="{"mod":"popu_336","dest":"https://edu.csdn.net","extend1":"学院"}" class="app-control app-edu"><a class="link-title" href="//edu.csdn.net" title="学院">学院</a>
<div class="appControl"> <span class="eduwx">
<img src="https://csdnimg.cn/public/common/toolbar/images/eduwxfix.png">
<em>CSDN学院</em> </span> </div> </li>
<li
'''
soup = BeautifulSoup(element,'lxml')
#soup.find_all(tags,attr(标签属性),kwargs(关键参数),recursive(是否递归搜索),text(文本内容),limli(限制条数))
#a_tags = soup.find_all('meta')
#b_tags = soup.find_all(id='csdn_container_tool') 传入关键字
#c_tags = soup.find_all('div','container row center-block')
#d_tags = soup.find_all('div',limit=1)表示虽然有两条div标签,但是只返回一条
#E_tags = soup.find_all('div',recursive=True)是否递归处理
#E_tags = soup.find_all('div',recursive=False)
print(E_tags)
拓展
find_parents :选取所有父亲节点
find_parent 选取下面一个父亲节点
find_next_sibling选取下面单个兄弟节点
find_next_siblings 选取所有的兄弟节点
find _previous_siblings() 向上搜索所有的兄弟
find _previous_sibling () 向上搜索单个兄弟
find_all_next() 往下搜索所有元素
find_next()往下查找单个元素