1 正则表达式
1.1 正则表达式语法
regular expression 、 regex 或 RE 正则表达式是用来简洁表达一组字符串的表达式,最主要用在字符串匹配中 由字符和操作符构成 常用操作符
操作符 | 说明 | 实例 |
---|
. | 表示任何单个字符 | | [ ] | 字符集,对单个字符给出取值范围 | [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 | {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_] | |
匹配IP地址的正则表达式: IP地址分4段,每段0-255 0-99范围的表示:[1-9]?\d 100-199范围的表示:1\d{2} 200-249范围的表示:2[0-4]\d 250-255范围的表示:25[0-5] 所以0-255表示为([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]) IP地址的表达式:(([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])
1.2经典正则表达式
由26个字母组成的字符串:^[A-Za-z]+$ 由26个字母和数字组成的字符串:^[A-Za-z0-9]+$ 整数形式的字符串:^-?\d+$ 正整数形式的字符串:^[0-9]*[1-9][0-9]*$ 中国境内邮政编码6位:[1-9]\d{5} 匹配中文字符:[\u4e00-\u9fa5] 国内电话号码:\d{3}-\d{8}|d{4}-\d{7}
2 RE库
2.1 基本使用
import re re库采用raw string类型表示正则表达式,表示为 r’text’ raw string是不包含对转义符再次转义的字符串 re库也可以采用string类型表示,但是繁琐,且需要转义转义符
2.2 主要功能函数
函数 | 说明 |
---|
re.search() | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 | re.match() | 从一个字符串的开始位置起匹配正则表达式,返回match对象 | re.findall() | 搜索字符串,以列表类型返回全部能匹配的子串 | re.split() | 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型 | re.finditer() | 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是mtach对象 | re.sub() | 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串 |
1)re.search(pattern, string, flags=0) 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 pattern:正则表达式的字符串或原生字符串表示 string:待匹配字符串 flags: 正则表达式使用时的控制标记
常用标记 | 说明 |
---|
re.I re.IGNORECASE | 忽略正则表达式的大小写,[A-Z]能够匹配小写字符 | re.M re.MULTILINE | 正则表达式中的^操作符能够将给定字符串的每行当作匹配开始 | re.S re.DOTALL | 正则表达式中的.操作符能够匹配所有字符,默认匹配除换行符外的所有字符 |
import re
match = re.compile(r'[1-9]\d{5}')
srt = match.search('BIT 100081')
if srt:
print(srt.group(0))
2)re.match(pattern, string, flags=0) 从一个字符串的开始位置起匹配正则表达式返回match对象
import re
match = re.compile(r'[1-9]\d{5}')
srt = match.match('100081 BIT ')
if srt:
print(srt.group(0))
3)re.findall(pattern, string, flags=0) 搜索字符串,以列表类型返回全部能匹配的子串
import re
match = re.compile(r'[1-9]\d{5}')
srt = match.findall('BIT100081 TSU100084')
if srt:
print(srt)
4)re.split(pattern, string, maxsplit=0, flags=0) 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型 maxsplit:最大分割数,剩余部分作为最后一个元素输出 如下例,他就只会切割第一项
import re
match = re.compile(r'[1-9]\d{5}')
srt = match.split('BIT100081 TSU100084', maxsplit=1)
if srt:
print(srt)
5)re.finditer(pattern, string, flags=0) 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是mtach对象
import re
match = re.compile(r'[1-9]\d{5}')
for m in match.finditer('BIT100081 TSU100084'):
if m:
print(m.group(0))
6)re.sub(pattern, repl, string, count=0, flags=0) 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串 repl:替换匹配字符串的字符串 count:匹配的最大替换次数
sub = match.sub(':zipcode', 'BIT100081 TSU100084')
print(sub)
7)regex=re.compile(pattern, flags=0) 将正则表达式的字符串形式编译成正则表达式对象 这是re库的另一种等价用法-面向对象用法:编译后多次操作 如:
pat = re.compile(r'[1-9]\d{5}')
rst = pat.search('BIT 100081')
2.3 re库的Match对象
Match对象是一次匹配的结果,包含匹配的很多信息
Match对象的属性
属性 | 说明 |
---|
.string | 待匹配的文本 | .re | 匹配时使用的patter对象(正则表达式) | .pos | 正则表达式搜索文本的开始位置 | .endpos | 正则表达式搜索文本的结束位置 |
Match对象的方法
方法 | 说明 |
---|
.group(0) | 获得匹配后的字符串 | .start() | 匹配字符串在原始字符串的开始位置 | .end() | 匹配字符串在原始字符串的结束位置 | .span() | 返回(.start(), .end()) |
对于空变量,调取group是错误的,所以要加if语句判断是不是空的。 Re库的贪婪匹配和最小匹配 Re库默认采用贪婪匹配,即输出匹配最长的子串
最小匹配操作符
操作符 | 说明 |
---|
*? | 前一个字符0次或无限次扩展,最小匹配 | +? | 前一个字符1次或无限次扩展,最小匹配 | ?? | 前一个字符0次或1次扩展,最小匹配 | {m,n}? | 扩展前一个字符m至n次(含n),最小匹配 |
只要长度输出可能不同,都可以通过在操作符后增加?变成最小匹配
3 实例:淘宝商品信息定向爬虫
3.1 准备
3.1.1功能描述
留到下一次学吧,教程信息过时了,第一步就要解决登陆问题。
4 股票数据定向爬虫
4.1 准备
功能描述: 目标:获取上交所和深交所所有的股票名称和交易信息 输出:保存到文件中 技术路线:requests-bs4-re 新浪股票:https://finance.sina.com.cn/stock/ 好家伙还是JavaScript 这两个题先留着吧,等我学到后边,再来完成这两个题。
不过有一个东西可以记一下,不换行打印,’\r’ ,表示将光标提到这一行的前边,然后输出,并将这一行内容覆盖。同时print函数在输出每一次后都会有换行,因此可以将这个禁掉,end=' '
5 Scrapy库
5.1 基本知识
5.1.1 爬虫框架解析
爬虫框架,是实现爬虫功能的一个软件结构和功能组件集合,能够帮助用户实现专业网络爬虫。 5+2结构,其中五个部分是框架的主体部分,另外包含两个中间键 ENGINE模块、SCHEDULER模块、ITEM PIPELINES模块、SPIDERS模块和DOWNLOADER模块 在ENGINE模块和SPIDERS模块、ENGINE模块和DOWNLOADER模块 中间包含了中间键。downloader MIDDLEWARE中间键——实现engine scheduler和downloader之间的数据流进行用户可配置的控制。通过对中间键的修改、丢弃、新增请求或响应 sipder middleware中间键——对请求和爬取项的再处理。功能包括修改、丢弃、新增请求或爬取项 可以编写配置代码
包含主要的3条数据流路径: 1)从spiders模块经过engine到达schedur模块,engine从spiders的地方获取了爬取用户的请求-request,理解为一个url,请求通过spiders到达engine之后,engine将这个爬取请求,转发给schedur模块——负责对爬取请求进行调度。 2)从schedur模块通过engine到达downloader模块,最终数据返回到spiders,首先engine从schedur模块获得下一个要爬取的网络请求,这时候的网络请求是真实的要去网络上爬取的请求,那么engine获得这样的请求后,通过中间键发送给downloader模块,然后downloader模块拿到请求后,真实地连接互联网,并且爬取相关网页,爬取到网页后,downloader模块将爬取地内容形成一个对象,这个对象叫响应——response,将所有的内容封装成一个response之后,将这个响应再通过中间键engine最终发送给spiders,在这条路径中一个真实的爬取url的请求经过schedur downloader最终返回了相关内容到达spiders。 3)从spiders结果经过engine到达item pipelines模块,首先spiders处理从downloader获得的响应,处理之后产生了两个数据类型,一个数据类型叫爬取项,scrapty item,也叫item,另外一个数据类型是新的爬取请求,也就是说我们从网络上获取一个网页后,如果这个网页中有其他的链接,也是我们需要的,可以在spiders中增加相关的功能,对新的链接发起再次爬取;spiders生成这两个数据类型后,将其发送给engine模块,engine模块收到两类数据后,将其中的items发送给item pipelines,将其中的request发送给schedur进行调度,从而为后期的数据处理以及再次启动网络爬虫请求提供新的数据来源。
入口为spiders,出口为item pipelines;engine、scheduler和downloader都是已有实现的功能,用户不需要编辑,用户需要编写的是spiders和item pipelines模块,只是按照框架进行编写,称之为配置
模块解析 1)engin模块 不需要用户修改 控制所有模块之间的数据流 根据条件触发事件 2)downloader模块 根据请求来下载网页 3)scheduler模块是对所有爬取请求进行调度管理的模块 4)spiders模块 解析downloader返回的响应-response 产生爬取项-scraped item 产生额外的爬取请求-request 5)item pipelines 以流水线方式处理spiders产生的爬取项 由一组操作顺序组成,类似流水线,每个操作是一个item pipeline类型
5.1.2 requests库和scrapy爬虫比较
这两者都没有处理js、提交表单、应对验证码等功能。 不同之处
requests | scrapy |
---|
页面级爬虫 | 网站级爬虫 | 功能库 | 框架 | 并发性考虑不足,性能较差 | 并发性好,性能较高 | 重点在于页面下载 | 重点在于爬虫结构 | 定制灵活 | 一般定制灵活,深度定制困难 |
如何挑选: 比较小的请求就用requests库 持续的或不间断的,或者是周期性的,希望数据积累形成自己的爬虫库,建议使用scrapy 定制程度高,自搭框架,requests>scrapy
5.1.3 常用命令
命令提示符中运行scrapy -h 就可以看到scrapy命令行 命令行格式:>scrapy<command>[options][args] 具体命令在command中, 常用命令
命令 | 说明 | 格式 |
---|
start project | 创建一个新工程 | scrapy startproject <name>[dir] | genspider | 创建一个爬虫 | scrapy genspider [options] <name> <domain> | settings | 获取爬虫配置信息 | scrapy settings [options] | crawl | 运行一个爬虫 | scrapy crawl <spider> | list | 列出工程中所有爬虫 | scrapy list | shell | 启动URL调试命令行 | scrapy shell [url] |
命令行更容易自动化,适合脚本控制
5.2 实例一:爬取一个简单网页
html地址:http://python123.io/ws/demo.html 文件名称:hemo.html 看起来有点强, 1)首先我们需要先创建一个爬虫工程 选取目录,我是选的D:\exfile\pyfile\pycode> ,在cmd中操作,从c盘到d盘,直接输入d: 即可,而要到子目录中则输入cd exfile 即可进入子目录,显示当前目录用dir 命令即可。成功后会在该路径生成一个目录,目录中的文件有__init__.py、items.py、middlewares.py、pipelines.py、settings.py这些文件。 生成的工程目录 生成外层目录: python123demo/ 这一目录中包含配置文件: scrapy.cfg,为部署scrapy爬虫使用的,部署的概念是将该爬虫放在特定的服务器上,并在服务器配置好相关的操作接口 子目录:python123demo/,是指scrapy框架的用户自定义python代码 __init__.py:是初始化脚本,用户不需要编写 items.py:对应items类的代码模板,需要继承scrapy库提供的item的类(继承类) middlewares.py:指的是middlewares代码模板,(继承类) pipelines.py:pipelines.py代码模板(继承类) settings.py:对应scrapy爬虫的配置文件,优化爬虫功能 再下一级子目录: spiders/,是spiders代码模板目录(继承类) 内部包括__init__.py和__pycache__/为缓存目录,均无需修改
2)在工程中产生一个scrapy爬虫 只需要一条命令:用户给出爬虫的名字和所爬取的网站 scrapy genspider demo python123.io 生成一个名为demo的spider,就会在spider目录下生成一个demo的py文件,该文件也可手工来生成。 会提示:Created spider 'demo' using template 'basic' in module: python123demo.spiders.demo demo.py文件
import scrapy
class DemoSpider(scrapy.Spider):
name = 'demo'
allowed_domains = ['python123.io']
start_urls = ['http://python123.io/']
def parse(self, response):
pass
parse()用于处理响应,解析内容形成字典,发现新的URL爬取请求。
3)配置产生的spider爬虫 去修改demo.py文件 response相当于从网络中返回内容所存储的或对应的对象,我们需要将response的内容写到html文件中。修改url:start_urls = ['http://python123.io/ws/demo.html'] 定义文件的名字:
def parse(self, response):
fname = response.url.split('/')[-1]
with open(fname,'wb') as f:
f.write(response.body)
self.log('Saved file %s.' % fname)
4)运行爬虫,获取网页 在cmd中运行scrapy crawl demo
5.3 yield关键字的使用
与生成器这一概念有关 生成器是一个不断产生值的函数 包含yield语句的函数是一个生成器 生成器每次产生一个值(yield语句),函数被冻结,被唤醒后再产生一个值。 通常与for循环搭配使用 相对于普通写法,通常在迭代次数循环次数很大时能节省资源和存储空间。
5.4 scrapy爬虫的数据类型
1)request类 class scrapy.http.Request() 代表一个request对象——表示一个HTTP请求 由spider生成,由downloader执行
包含六个常用的属性和方法:
属性或方法 | 说明 |
---|
.url | Request对应的请求URL地址 | .method | 对应的请求方法,'GET ''POST’等 | .headers | 字典类型风格的请求头 | .body | 请求内容主体,字符串类型 | .meta | 用户添加的扩展信息,在scrapy内部模块间传递信息使用 | .copy() | 复制该请求 |
2)response类 class scrapy.http.Response() 表示一个HTTP响应 由downloader生成,由spider处理 七个常用属性和方法
属性或方法 | 说明 |
---|
.url | Response对应的URL地址 | .status | HTTP状态码,默认是200 | .headers | Response对应的头部信息 | .body | Response对应的内容信息,字符串类型 | .flag | 一组标记 | .reques | 产生Response类型对应的Request对象 | .copy() | 复制该请求 |
3)item类 class scrapy.item.Item() Item对象表示一个从HTML页面中提取的信息内容 由spider生成,由Item Pipline处理 以字典类型来定义的,,其实是一个类字典类型,但是可以按照字典类型操作
5.5 信息提取方法
scrapy爬虫支持多种HTML信息提取方法: Beautiful Soup Ixml re XPath Selector CSS Selector 基本使用:
\<HTML>.css('a::attr(href)').extract()
a是标签名称,attr(href)是标签属性 先学到这草草结尾吧! 我需要实践 项目实践,一个个来! 后边继续学吧
|