第一周:网路爬虫之规则
单元1:Requests库入门
1.Requests库综述
表1.1 Requests库的7个主要方法
方法 | 说明 |
request() | 构造一个请求,支撑以下各方法的基础方法 |
get() | 获取HTML网页的主要方法,对应于HTTP的GET |
head() | 获取HTML网页头的主要方法,对应于HTTP的HEAD |
post() | 向HTML网页提交POST请求的方法,对应于HTTP的POST |
put() | 向HTML网页提交PUT请求的方法,对应于HTTP的PUT |
patch() | 向HTML网页提交局部修改请求,对应于HTTP的PATCH |
delete() | 向HTML页面提交删除请求,对应于HTTP的DELETE |
2.Requests库的get()方法
最简单的获取网址的方式是:
r= requests.get("http://www.yushuai.me")
这之中,requests是构造了一个向服务器请求资源的Request对象,r是返回一个包含服务器资源的Response对象。get完全的使用方法是:
requests.get(url,params=None,**kwargs)
其中,url是拟获取页面的url链接;params是url中的额外参数,字典或字节流格式,可选;**kwargs是13个控制参数。
表1.2 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,所以header中编码不一定正确。
r.apparent_encoding:根据网页内容分析出的编码方式。
2.爬取网页的通用代码框架
表1.3 Requests库的异常
异常 | 说明 |
requests.ConnectionError | 网络连接错误异常,如DNS查询失败、拒绝连接等 |
requests.HTTPError | HTTP错误异常 |
requests.URLRequired | URL缺失异常 |
requests.TooManyRedirects | 超过最大重定向次数,产生重定向异常 |
requests.ConnectTimeout | 连接远程服务器超时异常 |
requests.Timeout | 请求URL超时,产生超时异常 |
r.raise_for_status() | 如果不是200,产生异常requests.HTTPError |
爬取网页的通用代码框架如下所示:
import requests def getHTMLText(url): try: r=requests.get(url,timeout=30) r.raise_for_status()#如果状态不是200,引发HTTPError异常 r.encoding = r.apparent_encoding return r.text except: return "产生异常" if __name__ =="__main__": url = "http://www.baidu.com" print(getHTMLText(url))
3.HTTP协议及Requests库方法
表1.4 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,未提及的字段会被删除。
4.Requests库主要方法解析
(1)requests.request(method,url,**kwargs)
其中,method是请求方式;url是拟获取页面的url链接;**kwargs是控制访问的参数,共13个。
method请求方式包括:
①r=requests.request(‘GET’,url,**kwargs)
②r=requests.request(‘HEAD’,url,**kwargs)
③r=requests.request(‘POST’,url,**kwargs)
④r=requests.request(‘PUT’,url,**kwargs)
⑤r=requests.request(‘PATCH’,url,**kwargs)
⑥r=requests.request(‘delete’,url,**kwargs)
⑦r=requests.request(‘OPTIONS’,url,**kwargs)向服务器获取服务器和客户端通信的参数。
**kwargs参数如表1.5所示。
表1.5 参数表
参数 | 说明 |
params | 字典或字节序列,作为参数增加到url中。 |
data | 字典、字节序列或文件对象,作为Request的内容。 |
json | JSON格式的数据,作为Request的内容。 |
headers | 字典,HTTP定制头。 |
cookies | 字典或CookieJar,Request中的cookie。 |
auth | 元组,支持HTTP认证功能。 |
files | 字典类型,传输文件。 |
timeout | 设定超时时间,秒为单位。 |
proxies | 字典类型,设计访问代理服务器,可以增加登录认证。 |
allow_redirects | 默认为True,重定向开关。 |
stream | 默认为True,获取内容立即下载开关。 |
verify | 默认True,认证SSL证书开关。 |
cert | 本地SSL证书路径。 |
(2)requests.get(url,params=None, **kwargs)
url:拟获取页面的url链接。
params:url的额外参数,字典或字节流格式,可选。
**kwargs:12个控制访问参数(上一个中除了params)。
(3)requets.head(url,**kwargs)
**kwargs与request一样,不再累述。
(4)requests.post(url,data=None,json=None,**kwargs)
和request一样,不再累述。
其它也一样,不再累述。
5.例:Requests库的爬取性能分析
import timeimport requests def getHTMLText(url): try: r=requests.get(url,timeout=30) r.raise_for_status()#如果状态不是200,引发HTTPError异常 r.encoding = r.apparent_encoding return r.text except: return "产生异常" if __name__ =="__main__": url = "http://www.baidu.com/" start_time =time.time() for i in range(100): getHTMLText(url) end_time = time.time() dur_time = end_time - start_time print("爬取100次网页所需时间:{:.3f}s".format(dur_time))
单元2:网络爬虫的“盗亦有道”
1.网络爬虫规模及问题
网络爬虫的尺寸主要分为下面三类:
(1)爬取网页:小规模,数据量小,爬取速度不敏感,使用Requests库。
(2)爬取网站:中规模,数据规模较大,爬取速度敏感,使用Scrapy库。
(3)爬取全网:大规模,搜索引擎爬取速度关键,定制开发。
网络爬虫带来的问题:
骚扰问题、法律风险、泄漏问题。
2.Robots协议
告知爬虫哪些可以爬取,哪些不可以爬取。
单元3:实践
1.向百度搜索提交搜索内容
代码:
import requestskeyword = 'Python'try: kv = {'wd':'keyword'} r= requests.get("http://www.baidu.com/s",params=kv) print(r.raise_for_status) print(r.request.url) print(len(r.text))except:print("爬取失败")
结果:
<bound method Response.raise_for_status of <Response [200]>>
http://www.baidu.com/s?wd=keyword
245051
(注意:原来字典的'wd':'keyword',在连接的时候修改为了wd=keyword)
2.网络图片的爬取和存储
代码:
import requestsimport osimport timeroot = "D://pics//"url = "http://image.nationalgeographic.com.cn/2018/0327/20180327031900693.jpg"path = root +url.split('/')[-1]start_time = time.time()try: if not os.path.exists(root): os.mkdir(root) if not os.path.exists(path): r= requests.get(url) big = len(r.text) with open(path,'wb') as f: f.write(r.content) f.close() print("文件保存成功") else: print("文件已经存在")except: print("爬取失败")end_time = time.time()dur_time = end_time-start_timeprint("保存图片用时{0:.3f}s,图片大小为{1}".format(dur_time,big))
结果:
图片得到保存,且输出:
文件保存成功
保存图片用时14.035s,图片大小为682413
实例5:IP地址归属地的自动查询
import requests url = "http://m.ip138.com/ip.asp?ip="try: r=requests.get(url+'113.133.219.95') r.raise_for_status() r.encoding = r.apparent_encoding print(r.text[-500:])except: print("爬取失败")