python | 爬虫笔记(三)- 基本库使用

本节内容为基础库的使用,内容涵盖:Urllib库基本使用,Requests库基本使用以及正则表达式基础。html

3.1 Urllib

内置http请求库
request请求模块,error异常处理模块,parse工具模块,robotparser 识别网站robots.txt,识别哪些能够爬

3.1.1 发送请求

1- urlopen
urllib.request 模块提供了最基本的构造 HTTP 请求的方法,利用它能够模拟浏览器的一个请求发起过程,同时它还带有处理authenticaton(受权验证),redirections(重定向),cookies(浏览器Cookies)以及其它内容。
经过输出结果能够发现它是一个 HTTPResposne 类型的对象,它主要包含的方法有 read()、readinto()、getheader(name)、getheaders()、fileno() 等方法和 msg、version、status、reason、debuglevel、closed 等属性。
 urlopen详解
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
1)data(附加数据)
可添加form信息
2)timeout(超时时间)
能够经过设置这个超时时间来控制一个网页若是长时间未响应就跳过它的抓取,利用 try except 语句就能够实现这样的操做

还有 context 参数,它必须是 ssl.SSLContext 类型,用来指定 SSL 设置。
cafile 和 capath 两个参数是指定 CA 证书和它的路径,这个在请求 HTTPS 连接时会有用。
 
2- Request
urlopen() 方法能够实现最基本请求的发起,但这几个简单的参数并不足以构建一个完整的请求,若是请求中须要加入 Headers 等信息
 
详解Request
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
· headers参数是一个字典,Request Headers,经常使用于修改User-Agent来假装浏览器如:
Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11

可直接设置,也能够经过实例req add_header()来设置python

· method为请求方法:get,post,put等

3- 高级用法
Handler 各类处理器,有专门处理登陆验证的,有处理 Cookies 的,有处理代理设置的,利用它们咱们几乎能够作到任何 HTTP 请求中全部的事情。
 
大致流程
先根据需求,用不一样方法,构建(设置)出不一样处理器(handler)
而后利用handler构造一个opener = build_opener(xx_handler),以后发送请求
 
BaseHandler类,全部Handler的父类。提供了最基本的 Handler 的方法,例如 default_open()、protocol_request() 方法等。
OpenerDirector,咱们能够称之为 Opener,相似于urlopen()
 
认证、代理、Cookies

 

3.1.2 处理异常

Urllib 的 error 模块定义了由 request 模块产生的异常
 
1- URLError
URLError 类来自 Urllib 库的 error 模块,它继承自 OSError 类,是 error 异常模块的基类,由 request 模块生的异常均可以经过捕获这个类来处理。
具备一个属性reason
 
2- HttpError
它是 URLError 的子类,专门用来处理 HTTP 请求错误,好比认证请求失败等等。
它有三个属性。
· code,返回 HTTP Status Code,即状态码,好比 404 网页不存在,500 服务器内部错误等等。
· reason,同父类同样,返回错误的缘由。
· headers,返回 Request Headers。
 
由于 URLError 是 HTTPError 的父类,因此咱们能够先选择捕获子类的错误,再去捕获父类的错误,因此上述代码更好的写法以下:

from urllib import request, error

try:
    response = request.urlopen('http://cuiqingcai.com/index.htm')
except error.HTTPError as e:
    print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
    print(e.reason)
else:
    print('Request Successfully')
这样咱们就能够作到先捕获 HTTPError,获取它的错误状态码、缘由、Headers 等详细信息。若是非 HTTPError,再捕获 URLError 异常,输出错误缘由。最后用 else 来处理正常的逻辑,这是一个较好的异常处理写法。

3.1.3 解析连接

parse模块,定义处理URL的标准接口。例如实现 URL 各部分的抽取,合并以及连接转换。
1- urlparse() 解析网址
返回结果是一个 ParseResult 类型的对象,它包含了六个部分,分别是 scheme、netloc、path、params、query、fragment。

 API:正则表达式

urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
网址,协议,片断
2- urlunparse() 构造
3- urlsplit()
和urlparse相似,返回一个元组
4- urlunsplit() 拼接
5- urljoin()
前面提到的urlunparse和unsplit等能够连接合并,不过前提要有特定长度的对象
另一个办法是利用 urljoin() 方法。咱们能够提供一个 base_url(基础连接),新的连接做为第二个参数,方法会分析 base_url 的 scheme、netloc、path 这三个内容对新连接缺失的部分进行补充,做为结果返回。
#更方便,易操做
6- urlencode()
将构造好的参数字典,转化为URL的参数
7- parse_qs()
和6对应,实现序列参数转化成字典
8- parse_qsl()
参数转化为元组列表
9- quote()
将内容转化为 URL 编码的格式
10- unquote() 还原

3.1.4 分析robots协议

利用 Urllib 的 robotparser 模块咱们能够实现网站 Robots 协议的分析
1- Robots协议
爬虫协议,网络爬虫排除标准
用来告诉爬虫和搜索引擎哪些页面能够抓取,哪些不能够抓取。它一般是一个叫作 robots.txt 的文本文件,放在网站的根目录下。
User-agent: *
Disallow: /
Allow: /public/
2- robotparser
使用RobotFileParser解析 robots.txt
urllib.robotparser.RobotFileParser(url='')
先建立一个robofileparser对象,而后经过set_url()方法设置 robots.txt连接。
下一步利用can_fetch()方法判断王爷是否能够被抓取
也能够利用parser() 方法读取和分析

3.2 Request

在前面一节咱们了解了 Urllib 的基本用法,可是其中确实有不方便的地方。好比处理网页验证、处理 Cookies 等等,须要写 Opener、Handler 来进行处理。为了更加方便地实现这些操做,在这里就有了更为强大的库 Requests,有了它,Cookies、登陆验证、代理设置等等操做简单

3.2.1 基本使用

import requests

r = requests.get('https://www.baidu.com/')
print(type(r))
print(r.status_code)
print(type(r.text))
print(r.text)
print(r.cookies)
get() 方法便可实现和 urlopen() 相同的操做,获得一个 Response 对象,而后分别输出了 Response 的类型,Status Code,Response Body 的类型、内容还有 Cookies。
 
· GET请求
params 添加参数
调用r.json() 能够将返回结果转换为字典格式
· POST请求
import requests
data = {'name': 'germey', 'age': '22'}
r = requests.post("http://httpbin.org/post", data=data)
print(r.text)
返回中,form部分就是提交的数据
· Response
发送 Request 以后,获得的天然就是 Response,在上面的实例中咱们使用了 text 和 content 获取了 Response 内容,不过还有不少属性和方法能够获取其余的信息,好比状态码 Status Code、Headers、Cookies 等信息。
statuscode 有好多,如200成功,404notfound

3.2.2 高级用法 (需重点掌握)

文件上传,代理设置,Cookies 设置
1- 文件上传
requests 设置files
2- Cookies设置
3- 会话维持
在 Requests 中,咱们若是直接利用 get() 或 post() 等方法的确能够作到模拟网页的请求。可是这其实是至关于不一样的会话,即不一样的 Session,也就是说至关于你用了两个浏览器打开了不一样的页面。
requests.get('http://httpbin.org/cookies/set/number/123456789')
r = requests.get('http://httpbin.org/cookies')
->
s = requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456789')
r = s.get('http://httpbin.org/cookies')
利用 Session 咱们能够作到模拟同一个会话,并且不用担忧 Cookies 的问题,一般用于模拟登陆成功以后再进行下一步的操做。
能够用于模拟在一个浏览器中打开同一站点的不一样页面,
4- SSL证书验证
Requests 提供了证书验证的功能,当发送 HTTP 请求的时候,它会检查 SSL 证书,咱们可使用 verify 这个参数来控制是否检查此证书,其实若是不加的话默认是 True,会自动验证。
5- 代理设置
某些网站大规模爬取是会封IP
request里的proxies参数
6- 超时设置 timeout() 参数
7- 身份认证
8- Prepared Request**
在前面介绍 Urllib 时咱们能够将 Request 表示为一个数据结构,Request 的各个参数均可以经过一个 Request 对象来表示,在 Requests 里面一样能够作到,这个数据结构就叫 Prepared Request。

from requests import Request, Session

url = 'http://httpbin.org/post'
data = {
    'name': 'germey'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36'
}
s = Session()
req = Request('POST', url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)
有了 Request 这个对象,咱们就能够将一个个请求当作一个独立的对象来看待,这样在进行队列调度的时候会很是方便。

3.3 正则表达式

3.3.1 基本使用

实现字符串的检索、替换、匹配验证
URL: [a-zA-z]+://[^\s]*

 

3.3.2- re库

3.3.3- match() 开头匹配

非贪婪策略不适用于字符串结尾内容的匹配
 
修饰符
遇到换行符,须要加在match()中,第三个参数re.S

 

总结:尽可能使用泛匹配;使用括号获得匹配目标;尽可能使用非贪婪模式;有换行符就用re.S

3.3.4- search() 查询匹配

match从头开始查,不匹配返回none
result = re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>', html, re.S)
if result:
    print(result.group(1), result.group(2))
因为绝大部分的 HTML 文本都包含了换行符,因此经过上面的例子,咱们尽可能都须要加上 re.S 修饰符,以避免出现匹配不到的问题。
为了匹配方便,能用search就不用match

3.3.5- findall()

search() 能够返回匹配正则表达式的第一个内容,但若是想得到匹配的全部内容,须要findall()
仍是上面的 HTML 文本,若是咱们想获取全部 a 节点的超连接、歌手和歌名,就能够将 search() 方法换成 findall() 方法。若是有返回结果的话就是列表类型,因此咱们须要遍历一下来获依次获取每组内容。

3.3.6- sub() 修改文本

想获取全部li节点全部歌名,直接正则比较麻烦,能够先用sub把a节点去掉,只留下文本,再利用findall提取
html = re.sub('<a.*?>|</a>', '', html)
print(html)
results = re.findall('<li.*?>(.*?)</li>', html, re.S)
for result in results:
    print(result.strip())

3.3.7-compile()

将字符串编译成正则表达式对象
给正则表达式作了一层封装,以便于咱们更好地复用。
 

##本系列内容为《python3爬虫开发实战》学习笔记。本系列博客列表以下:json

(零)学习路线浏览器

(一)开发环境配置服务器

(二)爬虫基础cookie

(三)基本库使用网络

(四)解析库使用数据结构

(五)数据存储工具

(六)Ajax数据爬取

(七)动态渲染页面爬取Selenium

持续更新...

对应代码请见:..