Python网络爬虫与信息提取

Python网络爬虫与信息提取

  • 掌握定向网络数据爬取和网页解析的基本能力

  • 几个部分:

    • Requests库的介绍,通过这个库克以自动爬取HTML页面,在网络上自动提交相关请求
    • robots.txt协议,网络爬虫的规则,网络爬虫排除标准
    • Beautiful Soup库,解析HTML页面提取相关信息
    • 实战项目Projects:A/B,了解库以及相关操作
    • Re正则表达式库:提取关键信息
    • Sctapy:专业网络爬虫的框架,第三方库,中规模速度更快的。

常用的PythonIDE工具

  • 文本工具类
    • IDLE
      • 自带的、默认的、常用的、入门级工具
      • 包含两种交互式和文件式
    • Sublime Text
      • 专门为程序员开发的第三方专用编程工具
      • 工具非注册免费使用
  • 集成工具类
    • wing
      • 公司委会,工具售给
      • 调试功能丰富
      • 版本控制,版本同步
      • 多人共同开发
    • Visual Studio & PTVS
      • 微软公司维护
      • win环境为主
      • 调试功能丰富
    • Eclipse & PyDev
      • 开源IDE开发工具
      • 需要有一定开发经验
    • PyCharm
      • 社区版免费
      • 加单,集成度高
      • 适合较复杂较大的开发
    • Canopy(科学计算数学分析)
      • 公司委会,工具收费
      • 支持近500个第三方库
      • 适合科学计算领域应用开发
    • Anaconda(科学计算数学分析)
      • 开源免费
      • 支持近800个第三方库

网络爬虫

一、Requests库入门

  • 特点:简单简洁,一行代码就可以获得相关信息

requests的安装方法

1.管理员权限启动cmd
2.输入pip install requests

requests库的七个主要方法

方法 说明
requests.request() 构造一个骑牛,支持一下各种方法的基础方法
requests.get() 获取HTML网页的主要方法,对应于HTTP的GET
requests.head() 获取HTML网页头信息的方法,对应于HTTP的HEAD
requests.post() 向HTML网页提交POST请求的方法,对应于HEEP的POST
requests.put() 向HTML网页提交PUT请求的方法,对应于HTTP的PUT
requests.patch() 向HTML网页提交局部修改请求,对应于HTTP的PATCH
requests.delete() 向HTML页面提交删除请求,对应于HEEP的DELETE

requests库中的get方法

1.通过r = requests.get(url)
Request对象:构造一个向服务器请求资源的Request对象(Requests库内部生成的)
Response对象:然后返回一个包含服务器资源的Response对象
2.r = requests.get(url,params=Node,** kwargs)
url:获取页面的url链接

params:url中的额外参数,字典或字节流格式,可选

** kwargs:12个控制访问的参数

3.Response对象的属性

属性 说明
r.status_code HTTP请求的返回状态,200表示连接成果,404表示连接失败
r.text HTTP相应内容的字符串形式,即url对应的页面内容
r.encoding 从HTTP header中猜测的响应内容编码方式
r.apparent_encoding 从内容中分析出的响应内容编码方式(备选编码方式)
r.content HTTP相应内容的二进制形式

r.encoding:如果header中不存在charset,自认为编码为ISO-8859-1

r.apparent_encoding:根据网页内容分析出的编码方式

Requests库的异常

异常 说明
requests.ConnectionError 网络连接错误异常,如DNS查询失败、拒绝连接
requests.HTTPError HTTP错误异常
requests.URLRequired URL缺失异常
requests.TooManyRedirects 超过最大重定向次数,产生重定向异常
requests.ConnectTimeout 连接远程服务器超时异常
requests.Timeout 请求URL超时,产生超时异常
requests.raise_for_status() 如果不是200,产生异常requests.HTTPError

HTTP协议以及Requests库方法

  • HTTP协议
    • HTTP,Hypertext Transfer Protocol,超文本传输协议,HTTP是一种基于“请求与响应”模式的、无状态的应用层协议。
      • 简单讲:用户发送请求,服务器返回响应。
      • 无状态:第一次与第二次之间没有关联
      • 应用层:该协议工作于HTP协议之上
    • HTTP协议采用URL作为网络资源的标识
    • URL格式:http://host[:post]_[path]
      • host:合法的Internet主机域名或IP地址
      • port:端口号,缺省端口为80
      • path:请求资源的路径
    • HTTP URL实例:http://www.bit.edu.cn
    • HTTP URL的理解:URL是ton过HTTP协议存取资源的一个Internet路径,一个URL对应一个数据资源
  • HTTP协议对资源的操作
方法 说明
GET 请求获取URL位置的资源
HEAD 请求花去URL位置资源额响应消息报告,即获得非自愿的头部信息
POST 请求向URL位置的资源后附加新的数据
PUT 请求向URL位置存储一个资源,覆盖原URL位置的资源
PATCH 请求局部更新URL位置的资源,即改变该处位置的资源
DELETE 请求删除URL位置存储的资源

理解PATCH和PUT的区别

假设URL位置有一组数据UserInfo,包括UserID、UserName等20个字段。

需求:用户修改了UserName,其他不变

1.采用PATCH,进向URL提交UserName的局部更新请求

2.采用PUT,必须将所有20个字段一并提交到URL,未提交字段被删除

PATCH优点:节省网络带宽

  • HTTP协议与Requests库的方法是一致的

  • Requests库的head()方法

r = requests.head('http://httpbin.org/get')
r.headers
#会有返回的信息,当执行
r.text
#没有返回信息,因为我们只获得了头部信息
  • Requests库的post()方法
payload = {
     "key1":"vlaue1","key2":"value2"}
r = requests.post('http://httpbin.org/post',data=payload)
print(r.text)
#结果
{
     ...
 "form":{
     
   	"key2":"value2",
    "key1":"value1" 
 }, 
}
#向URL POST一个字典(或者键值对)自动编码为form(表单)
#如果提交一个字符串就会自动编码为data
r = requests.post('http://httpbin.org/post',data='ABC')
print(r.text)
#结果
{
     ...
    "data":"ABC"
 	"form":{
     },
}
  • Requests库中的put()方法

与post()方法效果不同,但是编码结果一样

Requests库主要方法解析

  • requests(method,url,**kwargs)方法

    • 是所有方法的基础方法

    • method:请求方式;对应get/put/post等7种

      • requests.request(‘GET’,url,**kwargs)

      • requests.request(‘HEAD’,url,**kwargs)

      • requests.request(‘POST’,url,**kwargs)

      • requests.request(‘PUT’,url,**kwargs)

      • requests.request(‘PATCH’,url,**kwargs)

      • requests.request(‘DELETE’,url,**kwargs)

      • requests.request(‘OPTIONS’,url,**kwargs),向服务器获取服务器和客户端打交道的参数,与获取资源并不直接相关。

    • url:获取页面的url链接

    • **kwargs:控制访问参数,13个

      • **开头表示可选的
      • params字典或字节序列,作为参数增加到url中
      kv = {
               "key1":"value1","key2":"value2"}
      r = requests.request('GET','http://python123.io/ws',params=kv)
      print(r.url)
      #结果
      http://python123.io/ws?key1=value1&key2=value2
      • data:字典、字节序列或文件对象,作为Request的内容,主要是向服务器提交资源时使用
      kv = {
               "key1":"value1","key2":"value2"}
      r = requests.request('POST','http://python123.io/ws',data=kv)
      body="主体内容"
      r = requests.request('POST','http://python123.io/ws',data=body)
      #结果并不是放在url链接里面而是放在url链接对应位置的地方作为数据来存储
      • json:JSON格式的数据作为Request的内容
      kv = {
               "key1":"value1"}
      r = requests.request('POST','http://python123.io/ws',json=kv)
      • headers:字典,HTTP定制头
      hd={
               'user-agent':Chrome/10}
      r = requests.request('POST','http://python123.io/ws',headers=hd)
      • cookies:字典或者CookieJar,Request中的cookie
      • auth:元组,支持HTTP认证功能
      • files:字典类型,传输文件
      fs = {
               'file':open("data.xls","rb")}
      r = requests.request("POST",http://python123.io/ws,files=fs)
      • timeout:设定的超时时间,以秒为单位
      r = requests.request("GET",'http://www.baidu.com',timeout=10)
      #在设定时间之内没有返回回来那么就会出现异常
      • proxies:字典类型,设定访问代理服务器,可以增加登录认证,防止对爬虫的你追踪,更换IP地址
      pxs = {
               'http':'http://user:[email protected]:1234','https':'https://10.10.10.1:431'}
      r = requests.request("GET",'http://www.baidu.com',proxies=pxs)
      • allow_redirects:True/False,默认为True,重定向开关,表示允不允许对URL进行重定向
      • stream:True/False,默认为True,是否对获取内容立即下载
      • verify:True/False,默认为True,认证SSL证书开关
      • cert:本地SSL证书路径
    • requests.get(url,params=None,**kwargs)

      • url:获取页面的URL连接
      • params:url中的额外参数,字典或字节流格式,可选
      • **kwargs:12个控制访问的参数
    • request.head(url,**kwargs)

    • request.post(url,data=None,json=None,**kwargs)

    • request.put(url,data=None,**kwargs)

    • request.patch(url,data=None,**kwargs)

    • request.delete(url,**kwargs)

    • request.get(url,params=None,**kwargs)

单元小结

  • request入门

    • requests.request()
    • requests.get():常用
    • requests.head():常用

    由于网络安全的限制以下方法很难实行

    • requests.post()
    • requests.put()
    • requests.patch()
    • requests.delete()
  • 爬取网页的通用代码框架

二、网络爬虫盗亦有道

网络爬虫引发的问题

  • 网络爬虫的尺寸
小规模,数据量小爬取速度不敏感Requests库(占比90+%) 中规模,数据规模较大,爬取速度敏感,Scrapy库 大规模,搜索引擎爬取速度关键,定制开发
爬取网页,玩转网页 爬取网站爬取系列网站 爬取全网
  • 网络爬虫的“骚扰”

web服务器默认只接受人类的访问,爬虫速度快(百倍)获取资源。

受限于编写水平和目的,网络爬虫将会为web服务器带来巨大的资源开销。

  • 法律风险

服务器上的数据有产权归属

网络爬虫获取数据后牟利将带来法律风险

  • 网络爬虫泄露隐私

网络爬虫可能具备突破简单访问控制的能力,获得被保护数据从而泄露个人隐私

  • 网络爬虫的限制
    • 来源审查:判断User-Agent进行限制(对网站的开发人员有一定的技术要求)
      • 检查来访HTTP协议头的User-Agent域,只响应浏览器或友好爬虫的访问
    • 发布公告:Robots协议(是否遵守有网络爬虫决定)
      • 告知所有爬虫网站的爬取策略,要求爬虫遵守。

Robots协议

  • Robots Exclusion Standard 网络爬虫排除标准
  • 作用:网站告知网络爬虫哪些页面可以抓取,那些不行
  • 形式:在网站的根目录下放置robots.txt文件(写了哪些可以爬那些不可以爬)
  • 例子:京东的网络爬虫协议
    User-agent: * 表示所有的爬虫都要遵循以下协议
    Disallow: /?* 不允许访问以问号开头的路径
    Disallow: /pop/.html 不允许访问/pop/.html
    Disallow: /pinpai/.html? 符合这个通配符的也是不允许访问的
    User-agent: EtaoSpider
    Disallow: / 不允许爬取任何资源
    User-agent: HuihuiSpider
    Disallow: /
    User-agent: GwdangSpider
    Disallow: /
    User-agent: WochachaSpider
    Disallow: /

Robots协议的遵守方式

  • Robots协议的使用
    • 网络爬虫:自动或人工识别robots.txt,在进行内容爬取。
    • Robots协议是建议单非约束性,网络爬虫可以不遵守,但是存在法律风险
  • 对Robots协议的理解
访问量很小:可以遵守,访问量很大:建议遵守 非商业且偶尔:建议遵守,商业利益:必须遵守 必须遵守
爬取网页,玩转网页 爬取网站爬取系列网站 爬取全网
  • 小程序,类似人类行为,可以不参考Robots协议,(访问次数少,访问量少)

三、Requests库爬取实例

实例1:京东商品页面的爬取

>>>import requests
>>> r = requests.get("https://item.jd.com/100012545852.html")
>>> r.status_code
>>> 200
>>> r.encoding
>>> 'UTF-8'
>>> r.text
>>> "undefined"

实例二 亚马逊商品页面的爬取

>>> kv = {
     'user-agent':'Mozilla/5,0'}
>>> url = "https://www.amazon.cn/dp/B003L9T0YY/ref=s9_acsd_hps_bw_c2_x_1_t?pf_rd_m=A1U5RCOVU0NYF2&pf_rd_s=merchandised-search-2&pf_rd_r=YTFCRRW6DCAZD4XRW329&pf_rd_t=101&pf_rd_p=4ac46f0a-16da-4ce2-ac3b-60fc19884e37&pf_rd_i=2328555071"
>>> r = requests.get(url,headers=kv)
>>> r.status_code
200
>>> r.request.headers
{
     'user-agent': 'Mozilla/5,0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
>>> r.text[:1000]
#结果

实例三百度/360搜索关键词提交

  • 百度关键词接口:http://www.baidu.com/s?wd=keyword
  • 360的关键词接口:http://www.so.com/s?q=keyword
>>> import requests
>>> kv ={
     'wd':'python'}
>>> r = requests.get("http://www.baidu.com/s",params = kv)
>>> r.status_code
200
>>>r.text
#结果

实例四:网络图片的爬取和存储

  • 网络图片链接的格式:http://www.example.com/picture.jpg
  • 右键属性获得图片的真实地址
>>> import requests
>>> path = "D:/abc.jpg"
>>> url="http://pic.sc.chinaz.com/files/pic/pic9/202005/zzpic24970.jpg"
>>> r = requests.get(url)
>>> r.status_code
200
>>> with open(path,"wb") as f:
	f.write(r.content)

	
78178
>>> f.close()

实例五:IP地址归属地的自动查询

em…这个例子要用到ip138的功能,然而好像有防爬取措施,所以导致例子不能用…

四、Beautiful soup 库

Beautiful soup库的安装

pip install beautifulsoup4

小例子

demo = r.text
from bs4 import BeautifulSoup
soup = BeautifulSoup(demo,"html.parser")
print(soup.prettify())

Beautiful Soup库的基本元素

  • Beautiful Soup库是解析、遍历、维护“标签树”的功能库

  • Beautiful Soup的引用:

    • from bs4 import BeautifulSoup
    • import bs4
  • HTML文档—标签树—BeautifulSoup类:一 一对应

    • BeautifulSoup对应一个HTML、XML文档的全部内容

Beautiful Soup库解析器

解析器 使用方法 条件
bs4的HTML解析器 BeautifulSoup(mk,“html.parser”) 安装bs4库
lxml的HTML的解析器 BeautifulSoup(mk,’lxml‘) pip install lxml
lxml的XML的解析器 BeautifulSoup(mk,’xml‘) pip install lxml
html5lib的解析器 BeautifulSoup(mk,’html5lib‘) pip install html5lib

Beautiful Soup类的基本元素

基本元素 说明
Tag 标签,最基本的信息组织单元,分别用<>和标明开头和结尾
Name 标签的名字,

的名字的’p‘,格式:.name
Attributrs 标签的属性,字典形式组织,格式:.attrs
NavigableString 标签内非属性字符串,<>…,格式:.string
Comment 标签内字符串的注释部分,一种特殊的Comment类型

Beautiful Soup库的理解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iBcrGZol-1589700353604)(C:\Users\60917\AppData\Roaming\Typora\typora-user-images\1589452938575.png)]

基于bs4库的HTML内容遍历方法

  • HTML基本格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eU3kAsEi-1589700353608)(C:\Users\60917\AppData\Roaming\Typora\typora-user-images\1589453166432.png)]

  • 标签树的下行遍历
属性 说明
.contents 子节点的列表,将所有儿子节点存入列表
.children 子节点的迭代类型,与.contents类似,用于循环遍历儿子节点
.descendants 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历

​ 遍历所有子孙节点

for child in soup.body.children:
    print(child)
#遍历所有的子节点
for child in soup.body.descendants:
    print(child)
#遍历所有的子孙节点
  • 标签树的上行遍历
属性 说明
.parent 节点的父亲标签
.parents 节点先辈标签的迭代类型,用于循环遍历先辈节点
  • 标签树的平行遍历
    • 条件:平行遍历发生在同一个父节点下的各节点间。
属性 说明
.next_sibling 返回按照HTML文本顺序的下一个平行节点的标签
.previous_sibling 返回按照HTML文本顺序的上一个平行节点的标签
.next_siblings 迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
.previous_siblings 迭代类型,返回按照HTML文本顺序的前序所有平行节点标签

​ 标签树的平行遍历

for sibling in soup.a.next_siblings:
    print(sibling)
#遍历后续节点    
for sibling in soup.a.previous_sibliings:
    pring(sibling)
  • 小结:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bAXtGOgb-1589700353613)(C:\Users\60917\AppData\Roaming\Typora\typora-user-images\1589455735542.png)]

基于bs4库的HTML格式输出

  • 如何让内容更加“友好”的显示

    for bs4 import BeautifulSoup
    soup = BeautifulSoup(demo,"html.parser")
    soup.prettify()
    #这样就可以变得友好
  • 编码:utf-8编码

Beautiful Soup库入门总结

  • bs4库的基本元素
    • Tag
    • Name
    • Attributes
    • NavigableString
    • Comment
  • bs4库的遍历功能
    • .contents:子节点(列表)
    • .children:循环遍历
    • .descendants:循环遍历
    • .parent
    • .parents
    • .next_sibling
    • .previous_sibling
    • .next_siblings
    • .previous_siblings

信息标记的三种形式

  • 信息标记:理解信息内容。

  • HTML的信息标记

    • HTML是WWW(World Wide Web)的信息组织方式

    • 将超文本信息嵌入到文本之中

    • HTML通过预定义的<>…标签形式组织不同类型的信息

  • 信息标记的三种形式

    • XML(扩展标记语言)

      • 标签Tag为主来表达信息
      • <>…和在中间没有内容的时候可以替换
      • 基于HTML的发展的一种通用的信息表达方式。
    • JSON:javaScript Object Notation

      • 有类型的键值对key:value
      • “key”:“value”
      • “key”:[“value1”,“value2”]
      • “key”:{“subkey”:“subvalue”}
    • YAML:YAML Ain’t Markup Language

      • 无类型的键值对

      • name:山东大学

      • name:(从属关系)

        ​ newname:山东大学

        ​ oldname:山东大学堂

      • name:(并列关系)

        ​ -山东大学

        ​ -山东大学堂

      • |表示整块数据 #表示注释

三种信息标记形式的比较

  • XML:一种用尖括号表达信息的方式

    • 实例:
    <person>
        <firestname>旋涡firestname>
        <lastname>鸣人lastname>
        <address>
            <streetAddr>某某街道某某号streetAddr>
        	<city>火忍村city>
            <zipcode>22222zipcode>
        address>
        <prof>忍者prof><prof>火影prof>
    person>
  • JSON:一种拥有类型键值对表达信息的方式

    • 实例
    {
           
        "firstname":"旋涡"
        "lastname":"鸣人"
        "address":{
           
    				"streetAddr":"某某"
        			"city":"火忍村"
        			"zipcode":"22222"
    				},
    	"prof"	:	["忍者","火影"]
    }
  • YAML:一种无类型的键值对表达信息的方式

    • 实例:
    firstname:旋涡
    lastname鸣人
    address:
    	streetAddr:某某
    	city:火忍村
    	zipcode:22222
    prof:
    	-火影
    	-忍者
    
  • 三种信息标记形式的比较

    • XML 最早的通用信息标记语言,可扩展性号,但是繁琐。
    • JSON 信息有类型,适合程序处理(JS),比XML简介
    • YANL信息无类型,文本信息比例最高,可读性好。
    • Internet上主要采用的是XML格式
    • JSON移动应用云端和节点的信息通信,(缺陷)无注释。(程序对接口处理的地方)
    • YAML 各类系统的配置文件,有注释易读

信息提取的一般方法

  • 方法一:完整解析信息的标记形式,再提取关键信息。

    • 用标记解析器解析XML、JSON、YAML格式,将其中所需要的信息提取出来。
    • 例如:bs4库的标签树遍历
    • 优点:信息解析准确
    • 缺点:提取过程繁琐,速度慢
  • 方法二:无视标记形式,所搜关键信息

    • 对信息的文本查找函数即可
    • 优点:提取过程简介,速度较快
    • 缺点:提取结果准确性与信息内容相关
  • 方法三:融合方法结合形式解析与搜索方法,提取关键信息

    • XML JSON YANL搜索
    • 需要表及解析器和文本查找函数

例子:

import requests
demo="网址"
r = requests.get(demo)
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
for link in soup.find_all('a'):
    pring(link.get('href'))

基于bs4库的HTML内容查找方法

  • <>.fand_all(name,attrs,recursive,string,**kwargs)方法

    • 返回值类型是一个列表存储查找结果

    • name:对标签名称的检索字符串

      • soup.find_all([‘a’,‘b’])
      • soup.find_all(True) 显示所有标签信息
      • 需求:查找以b开头的标签
      import re
      for tag in soup.find_all(re.compile('b')):
          print(tag.name)
    • attrs:对标签属性值得检索字符串,可标注属性检索

    • recursive:是否对子孙全部检索,默认True。

    • string:<>…中字符串区域的检索字符串

    • (…)等价于.find_all(…)

    • soup(…)等价于soup.find_all(…)

方法 说明
<>.find() 搜索且只返回一个结果,字符串类型,同.find_all()参数
<>.find_parents() 在先辈节点中搜索,返回列表类型,同.find_all()参数
<>.find_parent() 在先辈节点中返回一个结果,字符串类型,同.find()参数
<>.find_next_siblings() 在后续平行节点中搜索,返回列表类型,同.find_all()参数
<>.find_next_sibling() 在后续平行节点中返回一个结果,字符串类型,同.find()参数
<>.find_previous_siblings() 在前序平行节点中搜索,返回列表类型,同.find_all()参数
<>.find_previous_sibling() 在前序平行节点中返回一个结果,字符串类型,同.find()参数

单元小结

  • 信息标记与提取方法
    • XML <>…
    • JSON 有类型key:value
    • YAML 无类型key:value
  • 信息提取的一般方法
  • 缩写形式

“中国大学排名定向爬虫”实例介绍

  • 思路:
    • 1.首先要获取页面信息
    • 2.然后找到自己需要的信息内容,把他放到一个数据结构中
    • 3.最后用数据结构将他们打印出来
import requests
from bs4 import BeautifulSoup
import bs4
def getHTMLText(url):
    try:
        r = requests.get(url)
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return " "
def fillUnivList(ulist,html):
    soup = BeautifulSoup(html , "html.parser")
    for tr in soup.find('tbody').children:
        if isinstance(tr , bs4.element.Tag):#作用是排除string中的tr
            tds = tr('td')    
            ulist.append([tds[0].string,tds[1].string,tds[4].string]) 

def printUnivList(ulist,num):
    tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"#用第三个来进行填充
    print(tplt.format("排名","学校名称","分数",chr(12288)))#chr(12288)中文空格
    for i in range(num):
        u = ulist[i]
        print(tplt.format(u[0],u[1],u[2],chr(12288)))
        
def main():
    uinfo = []
    url = "http://www.zuihaodaxue.com/zuihaodaxuepaiming2020.html"
    html = getHTMLText(url)
    fillUnivList(uinfo,html)
    printUnivList(uinfo,20)
    
main()

五、正则表达式

正则表达式的简介

正则表达式 regular expression regex RE

正则表达式是用来简洁表达一组字符串的表达式

  • 表达

’PN‘

’PYN‘ 正则表达式:

’PYTN‘ 等价于 P(Y|YT|YTH|YTHO)?N

‘PYTHN‘

’PYTHON‘

  • 表达无穷字符串组

‘PY’

‘PYY’ 等价于PY+

‘PYYY…’

  • ’PY‘开头

后续存在不多于10个字符

后续字符不能是’P‘或’Y‘ 等价于PY[^PY]{0,10}

  • 正则表达式

    • 通用的字符串表达框架
    • 简洁表达一组字符串的表达式
    • 针对字符串表达“简洁”和“特征”思想的工具
    • 判断某字符串的特征归属
  • 正则表达式在文本处理中十分常用

    • 表达文本类型的特征(病毒、入侵)
    • 同时查找或替换一组字符串
    • 匹配字符串的全部或者部分(主要)
  • 正则表达式的使用

    • 编译:将符合正则表达是语法的字符串转换成正则表达式特征

正则表达式的语法

  • 正则表达式是由字符和操作符组成
操作符 说明 实例
. 表示任何单字符
[] 字符集,对单个字符给出取值范围 [abc]表示a、b、c,[a-z]表示a到z单个字符
[^] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
* 前一个字符0次或无限次扩展 abc*表示ab、abc、abcc、abccc等
+ 前一个字符1次或无限次扩展 abc+表示abc、abcc、abccc等
? 前一个字符0次或1次扩展 abc?表示ab、abc
| 左右表达式任意一个 abc|def表示abc、def
{m} 扩展前一个字符m次 ab{2}c表示abbc
{m,n} 扩展前一个字符m至n次(含n) ab{1,2}c表示abc、abbc
^ 匹配字符串开头 ^abc表示abc且在一个字符串的开头
$ 匹配字符串结尾 abc$表示abc且在一个字符串的结尾
() 分组标记,内部只能使用|操作符 (abc)表示abc,(abc|def)表示abc,def
\d 数字等价于[0-9]
\w 单词制度等价于[A-Za-z0-9_]
正则表达式 对应字符串
P(Y|YT|YTH|YTHO)?N ’PN‘、’PYN‘、’PYTN‘、‘PYTHN’、’PYTHON‘
PYTHON+ ’PYTHON‘、’PYTHON…‘
PY[TH]ON ‘PYTON’、’PYHON‘
PY[’’^'TH]?ON(没有引号) ’PYON‘、’PYaON‘…
PY{:3}N ‘PN’、’PYYYN‘
  • 经典的正则表达式
正则表达式 对应字符串
1+$ 由26个字母组成的字符串
2+$ 由26个字母和数字的字符串整数形式的字符串整数形式的字符串
^-?\d+$ 整数形式的字符串
3* [1-9]’’[0-9] *$(没有引号) 正整数形式的字符串
[1-9]\d{5} 中国境内邮政编码
[\u4e00-\u9fa5] 匹配中文字符
\d{3}-\d{8}|\d{4}-\d{7} 国内电话号码
  • 匹配IP地址的正则表达式

\d+.\d+.\d+.\d

\d{1:3}.\d{1:3}.\d{1:3}.\d{1:3}

精确版

(([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]).){3}([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])

RE库的基本使用

  • Python的标准库,主要用于字符匹配

  • 调用方法 import re

  • 正则表达式的表示类型

    • raw string 类型(原生字符串类型)
      • r’text‘形式:r’[1-9]\d{5}‘
      • 不包含转义符的字符串
    • string类型,更繁琐
      • r’[1-9]\d{5}‘=’[1-9]\\d{5}’(两个斜杠)
函数 说明
re.serach() 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象简单讲:就是搜索找到第一个一样的地方
re.match() 从一个字符串的开始位置起匹配正则表达式,返回match对象
re.findall() 搜索字符串,以列表类型返回全部能匹配的子串
re.split() 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型
re.finditer() 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象
re.sub() 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串
  • re.search(pattern,string,flags=0)
    • 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象
      • pattern:正则表达式的字符串或原生字符串表示
      • string:待匹配字符串
      • flags:正则表达式使用时的控制标记
常用标记 说明
re.I re.IGNORECASE 忽略正则表达式的大小写,[A-Z]能够匹配小写字符
re.M re.MULTILINE 正则表达式中的^操作符能够将给定字符串的每行当做匹配开始
re.S re.DOTALL 正则表达式中的.操作符能够匹配所有字符,默认匹配除换行外的所有字符
  • re.match(pattern,string,flags=0)

    • 从一个字符串开始位置起匹配正则表达式,返回match对象。
      • pattern:正则表达式的字符串或原生字符串表示
      • string:待匹配字符串
      • flags:正则表达式使用时的控制标记
  • re.findall(pattern,string,flags=0)

    • 搜索字符串,以列表类型返回全部能匹配的子串。
      • pattern:正则表达式的字符串或原生字符串表示
      • string:待匹配字符串
      • flags:正则表达式使用时的控制标记
  • re.split(pattern,string,maxsplit=0,flags=0)

    • 将一个字符串按照正则表法师匹配结果进行分割,返回列表类型
      • pattern:正则表达式的字符串或原生字符串表示
      • string:待匹配字符串
      • maxsplit:最大分隔数,剩余元素作为最后一个元素输出
      • flags:正则表达式使用时的控制标记
  • re.finditer(pattern,string,flags=0)

    • 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象
      • pattern:正则表达式的字符串或原生字符串表示
      • string:待匹配字符串
      • flags:正则表达式使用时的控制标记
  • re.sub(pattern,repl,string,count=0,flags=0)

    • 在一个字符串中替换搜有匹配正则表达式的子串,返回替换后的字符串。
      • pattern:正则表达式的字符串或原生字符串表示
      • repl:替换匹配字符串的字符串
      • string:待匹配字符串
      • count:最大替换次数
      • flags:正则表达式使用时的控制标记
  • regex = re.compile(pattern,falgs=0)

    • 将正则表达式的字符串形式编译成正则表达式对象。
      • pattern:正则表达式的字符串或原生字符串表示
      • flags:正则表达式使用时的控制标记

Re库的match对象

  • 一次匹配的结果,包含了很多匹配的相关信息。
  • match对象的属性
属性 说明
.string 待匹配的文本
.re 匹配时的正则表达式
.pos 正则表达式搜索文本的开始位置
.endpos 正则表达式搜索文本的结束位置
  • match对象的方法
方法 说明
.group(0) 获得匹配后的字符串
.start() 匹配字符串在原始字符串的开始位置
.end() 匹配字符串在原始位置的结束位置
.span() 返回(.start(),.end())

Re库的贪婪匹配和最小匹配

match = re.search(r'PY.*N','PYASDASNSAN')
match.group(0)

返回结果? Re库默认采用贪婪匹配的方式

  • 贪婪匹配

Re库默认采用贪婪匹配,即输出匹配最长的子串

最小匹配?怎么办?

match = re.search(r'PY.*?N','PYANASDAAN')
match.group(0)

这样的返回结果就是

’PYAN‘

操作符 说明
*? 前一个字符0次或无限次扩展,最小匹配
+? 前一个字符1次或无限次扩展,最小匹配
?? 前一个字符0次或1次扩展,最小匹配·
{m,n}? 扩展前一个字符m至n(含n),最小匹配

单元小结

  • 正则表达式是用来简洁表达一组字符串的表达式

  • 正则表达式六个函数

实例淘宝商品比价定向爬虫

  • 目标:获取淘宝搜索页面的信息,提取其中商品的名称和价格
  • 理解:
    • 获得淘宝的搜索接口
    • 翻页的处理
import requests
import re

def getHTMLText(url):
    kv = {
     'cookie':'':'Mozilla/5,0'}
    #缺少cookie可以看我的另一篇博客
    try:
        r = requests.get(url,headers=kv,timeout=30)
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ""

def parsePage(ilt,html):
    try:
        plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)
        tlt = re.findall(r'\"raw_title\"\:\".*?\"',html)
        for i in range(len(plt)):
            price = eval(plt[i].split(':')[1])
            title = eval(tlt[i].split(':')[1])
            ilt.append([price,title])
    except:
        print("")

def printGoodsList(ilt):
    tplt = "\t{:^4}{:^8}\t{:^16}" 
    count = 0
    print(tplt.format("序号",'价格','名称'))
    for i in ilt:
        count = count + 1
        print(tplt.format(count,i[0],i[1]))
        
def main():
    goods='书包'
    depth = 2
    infoilt = []
    start_url = 'https://s.taobao.com/search?q='+goods
    for i in range(depth):
        try:
            url = start_url + '&s=' + str(44*i)
            html = getHTMLText(url)
            parsePage(infoilt,html)
        except:
            continue
    printGoodsList(infoilt)
    
main()    

实例股票数据定向爬虫

目的:获得上交所和深交所所有股票的名称和交易信息。

程序设计步骤

步骤一:从东方财富网获取股票列表

步骤二:根据股票列表逐个到百度股票获取个股信息

步骤三:将结果存储到文件

import requests
from bs4 import BeautifulSoup
import traceback
import re
def getHTMLText(url):
    try:
        r = requests.get(url,timeout=30)
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ""
def getStockList(lst,stockURL):
    html = getHTMLText(stockURL)
    soup = BeautifulSoup(html,'html.parser')
    a = soup.find_all('a')
    for i in a:
        try:
            href = i.attrs['href']
            temp = re.findall(r'[1]\d{6}',href)[0]
            if temp not in lst:
                lst.append(temp)
        except:
            continue
    
        
def getStockInfo(lst,stockURL,fpath):
    for stock in lst:
        url = stockURL + stock +'.html'
        html = getHTMLText(url)
        try:
            if html =="":
                continue
            infoDict = {
     }
            soup = BeautifulSoup(html,'html.parser')
            stockInfo = soup.find('div',attrs={
     'class':'relate_stock clearfix'})

            info = stockInfo.find('script')
            str1 = info.string.replace(" ","")
            infolist = re.findall(r'.*\:\'.*\'',str1)
            for i in infolist:
                try:
                    key,value=str(i).split(':')
                    infoDict[key]=eval(value)
                except:
                    continue
            with open(fpath,'a',encoding='utf-8') as f:
                f.write(str(infoDict)+'\n')
            
        except:
            traceback.print_exc()
            continue

def main():
    stock_list_url = "http://quotes.money.163.com/data/caibao/yjyg_00.html"
    stock_info_url = "http://quotes.money.163.com/"
    output_file = 'D://gubiao.txt'
    slist = []
    getStockList(slist,stock_list_url)
    getStockInfo(slist,stock_info_url,output_file)
   
main()

实例优化

  • 已知网页编码
def getHTMLText(url,code='utf-8'):
    try:
        r = requests.get(url,timeout=30)
        r.encoding = code
        return r.text
    except:
        return ""

  1. A-Za-z ↩︎

  2. A-Za-z0-9 ↩︎

  3. 0-9 ↩︎

你可能感兴趣的:(Python,python,正则表达式)