[网络爬虫基础] 1. Request库
文章目录
Requests库的七个主要方法
方法 | 说明 |
---|---|
requests.request() | 构造一个请求,支撑以下各方法的基础方法 |
requests.get() | 获取HTML网页的主要方法,对应于HTTP的GET |
requests.head() | 获取HTML网页头信息的方法,对应于HTTP的HEAD |
requests.post() | 向HTML网页提交POST请求的方法,对应于HTTP的POST |
requests.put() | 向HTML网页提交PUT请求的方法,对应于HTTP的PUT |
requests.patch() | 向HTML网页提交局部修改请求,对应于HTTP的PATCH |
requests.delete() | 向HTML页面提交删除请求,对应于HTTP的DELETE |
一、Request库的get()方法
r = requests.get(url)
,r
表示返回一个包含服务器资源的Response
对象,requests.get(url)
会构造一个向服务器请求资源的Request
对象。
完整格式是 r = requests.get(url, params = None, **kwargs)
,后面两个为选填参数,其中params
表示字典或者字节流格式,**kwargs
表示12个控制的参数。
打开源码可知,get
方法是调用requests
方法封装的,实际上7个方法中,其余6个都是由request
方法封装的。
Request库的Response对象
Response对象包含爬虫返回的内容。
>>> import requests
>>> r=requests.get("http://www.baidu.com")
>>> r.status_code
200
>>> type(r)
<class 'requests.models.Response'>
>>> r.headers
{'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Sun, 23 Feb 2020 15:22:06 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:28:11 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': }
Response对象包含服务器返回的所有信息,也包含请求的Request信息。
1. Response对象的属性
属性 | 说明 |
---|---|
r.status_code | HTTP请求的返回状态,200表示连接成功,404表示失败 |
r.text | HTTP响应内容的字符串形式,即,url对应的页面内容 |
r.encoding | 从HTTP header中猜测的响应内容编码方式 |
r.apparent_encoding | 从内容中分析出的响应内容编码方式(备选编码方式) |
r.content | HTTP响应内容的二进制形式 |
2. 理解Response的编码
r.encoding
会从HTTP header中猜测的响应内容编码方式,如果header中不存在charset,则认为编码为ISO-8859-1apparent_encoding
是根据网页内容分析出的编码方式可以看作是r.encoding的备选。r.text
根据r.encoding显示网页内容,所以一般处理的时候会让r.encoding=r.apparent_encoding
>>> r=requests.get("http://www.baidu.com")
>>> r.status_code
200
>>> r.text
>'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8>
<meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer>
<link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>ç\x99¾åº¦ä¸\x80ä¸\x8bï¼\x8cä½\xa0å°±ç\x9f¥é\x81\x93</title>
>>> r.encoding
'ISO-8859-1'
>>> r.apparent_encoding
'utf-8'
>>> r.encoding = "utf-8"
>>> r.text
'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8>
<meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer>
<link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css>
<title>百度一下,你就知道</title>
第一次r.text
返回的是title是乱码,而第二次我们设置了正确的编码方式,于是中文被正确的显示。
二、爬取网页的通用代码框架
1. 理解Request库的异常
异常 | 说明 |
---|---|
requests.ConnectionError | 网络连接错误异常,如DNS查询失败、拒绝连接等 |
requests.HTTPError | HTTP错误异常 |
requests.URLRequired | URL缺失异常 |
requests.TooManyRedirects | 超过最大重定向次数,产生重定向异常 |
requests.ConnectTimeout | 连接远程服务器超时异常 |
requests.Timeout | 请求URL超时,产生超时异常 |
r.raise_for_status()
在方法内部判断r.status_code
是否等于200,不需要增加则外的if语句,这样便于利用try-except
进行异常处理。
2. 爬取网页的通用代码框架
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))
三、HTTP协议及Request库方法
HTTP,Hypertext Transfer Protocol,超文本传输协议,是一个基于“请求与响应”模式的、无状态的应用层协议。
HTTP协议采用URL作为定位网络资源的标识,URL格式为:http://host[:port][path]
,其中host是合法的Internet主机域名或IP地址;port:是端口号,缺省端口为80;path:是请求资源的路径。
HTTP URL的理解:URL是通过HTTP协议存取资源的Internet路径,一个URL对应一个数据资源
1. Http协议对资源的操作
方法 | 说明 |
---|---|
GET | 请求获取URL位置的资源 |
HEAD | 请求获取URL位置资源的响应消息报告,即获得该资源的头部信息 |
POST | 请求向URL位置的资源后附加新的数据 |
PUT | 请求向URL位置存储一个资源,覆盖原URL位置的资源 |
PATCH | 请求局部更新URL位置的资源,即改变该处资源的部分内容 |
DELETE | 请求删除URL位置存储的资源 |
理解PATCH和PUT的区别:
假设URL位置有一组数据UserInfo,包括UserID、UserName等20个字段
需求:用户修改了UserName,其他不变
- 采用PATCH,仅向URL提交UserName的局部更新请求
- 采用PUT,必须将所有20个字段一并提交到URL,未提交字段被删除
PATCH的最主要好处:节省网络带宽
Http协议与Requests库功能是一致的
2. Requests库主要方法解析
Requests库方法 | 说明 |
---|---|
requests.request() | 构造一个请求,支撑以下各方法的基础方法 |
requests.get() | 获取HTML网页的主要方法,对应于HTTP的GET |
requests.head() | 获取HTML网页头信息的方法,对应于HTTP的HEAD |
requests.post() | 向HTML网页提交POST请求的方法,对应于HTTP的POST |
requests.put() | 向HTML网页提交PUT请求的方法,对应于HTTP的PUT |
requests.patch() | 向HTML网页提交局部修改请求,对应于HTTP的PATCH |
requests.delete() | 向HTML页面提交删除请求,对应于HTTP的DELETE |
requests.request(method, url, **kwargs)
method
: 请求方式,对应get/put/post等7种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)
url
: 拟获取页面的url链接**kwargs
: 控制访问的参数,共13个,均为可选项。- params : 字典或字节序列,作为参数增加到url中
- data : 字典、字节序列或文件对象,作为Request的内容,主要在向服务器提交资源时使用(POST)
- json : JSON格式的数据,作为Request的内容,也是常用于POST请求
- headers : 字典,用来定制访问某url的HTTP的协议头
- cookies : 字典或CookieJar,Request中的cookie
- auth : 元组,支持HTTP认证功能
- files : 字典类型,向服务器传输文件时使用
- timeout : 设定超时时间,以秒为单位
- proxies : 字典类型,设定访问代理服务器,隐藏用户源IP信息,防止对爬虫的逆追踪
- allow_redirects : True/False,默认为True,重定向开关
- stream : True/False,默认为True,获取内容立即下载开关
- verify : True/False,默认为True,认证SSL证书开关
- cert : 本地SSL证书路径
>>> import requests
>>> kv = {'key1': 'value1', 'key2': 'value2'}
#构造url链接
>>> r = requests.request('GET', 'http://python123.io/ws', params=kv)
>>> r.url
'https://python123.io/ws?key1=value1&key2=value2'
#向服务器提交字典、字符串、JSON类型的数据
>>> r = requests.request('POST', 'http://python123.io/ws', data=kv)
>>> body = '主体内容'
>>> r = requests.request('POST', 'http://python123.io/ws', data=body)
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-3: Body ('主体内容') is not valid Latin-1.
Use body.encode('utf-8') if you want to send it encoded in UTF-8.
>>> r = requests.request('POST', 'http://python123.io/ws', json=kv)
# 构造Http头
>>> hd = {'user‐agent': 'Chrome/10'}
>>> r = requests.request('POST', 'http://python123.io/ws', headers=hd)
UnicodeEncodeError: 'ascii' codec can't encode character '\u2010' in position 4: ordinal not in range(128)
#上传本地文件
>>> fs = {'file': open('data.xls', 'rb')}
>>> r = requests.request('POST', 'http://python123.io/ws', files=fs)
#设置超时时间为10s
>>> r = requests.request('GET', 'http://www.baidu.com', timeout=10)
#设定两个代理,一个是http访问时使用的代理,设置需要输入用户名与密码
#增加https的代理服务器,使访问百度时,所使用的ip地址就是代理服务器的ip地址
>>> pxs = { 'http': 'http://user:pass@10.10.10.1:1234' 'https': 'https://10.10.10.1:4321' }
>>> r = requests.request('GET', 'http://www.baidu.com', proxies=pxs)
在使用后六个方法时,把它们常用的参数作为显式定义的参数量放到了函数的声明里,而不常用的参数就放到了函数的可选参数中
requests.get(url, params=None, **kwargs)
requests.head(url, **kwargs)
requests.post(url, data=None, json=None, **kwargs)
requests.put(url, data=None, **kwargs)
requests.patch(url, data=None, **kwargs)
requests.delete(url, **kwargs)
# 向URL POST一个字典 自动编码为form(表单)
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post('http://httpbin.org/post', data = payload)
>>> print(r.text)
{
...
"form": {
"key1": "value1",
"key2": "value2"
},
...
}
# 向URL POST一个字符串 自动编码为data
>>> r = requests.post('http://httpbin.org/post', data = 'ABC')
>>> print(r.text)
{
"args": {},
"data": "ABC",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "3",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0",
"X-Amzn-Trace-Id": "Root=1-5e52abfc-82539a607b8f68e00dac3c58"
},
"json": null,
"origin": "120.210.190.211",
"url": "http://httpbin.org/post"
}
四、Robots协议
网页对网络爬虫的限制主要有两种:
- 来源审查:判断User‐Agent进行限制,检查来访HTTP协议头的User‐Agent域,只响应浏览器或友好爬虫的访问。
- 发布公告:Robots协议,告知所有爬虫网站的爬取策略,要求爬虫遵守
Robots Exclusion Standard,网络爬虫排除标准
- 作用:网站告知网络爬虫哪些页面可以抓取,哪些不行
- 形式:在网站根目录下的robots.txt文件
Robots协议基本语法:*
代表所有,/
代表根目录,具体形式为:
User‐agent: *
Disallow: /
分析京东的robots协议
User-agent: *
Disallow: /?*
Disallow: /pop/*.html
Disallow: /pinpai/*.html?*
(意思是对于任何爬虫,均不能访问后缀为/?,/pop/.html,/pinpai/.html? 的网页)
User-agent: EtaoSpider
Disallow: /
User-agent: HuihuiSpider
Disallow: /
User-agent: GwdangSpider
Disallow: /
User-agent: WochachaSpider
Disallow: /
(意思是EtaoSpider,HuihuiSpider,GwdangSpider,WochachaSpider这几个网络爬虫不能访问京东的任何页面。)
实战系列
一、网络图片的爬取与存储
import requests
import os
url="http://image.nationalgeographic.com.cn/2017/0211/20170211061910157.jpg"
root = "D://pics//"
path = root + url.split('/')[-1]
try:
#这一步是防止目标路径不存在
if not os.path.exists(root):
os.mkdir(root)
#判断路径下是否有该张图片
if not os.path.exists(path):
r=requests.get(url)
with open(path,'wb') as f:
f.write(r.content)
f.close()
print("文件保存成功")
else:
print("文件已存在")
except:
print("爬取失败")
二、IP地址归属地的自动查询
可以查询ip归属地的网站:IP地址在线查询
import requests
url="http://m.ip138.com/ip.asp?ip="
try:
r=requests.get(url+'202.204.80.112')
r.raise_for_status()
r.encoding=r.apparent_encoding
print(r.text[-500:])
except:
print("爬取失败")
嵩天老师提供的程序返回了爬取失败,应该是网站对爬虫的来源进行审查,添加了hd = {'user‐agent': 'Chrome/10'}
也没成功,于是使用了真实的header头伪装成浏览器访问,爬取成功。
python爬虫请求头
import requests
url="http://m.ip138.com/ip.asp?ip="
try:
kv = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'}
r=requests.get(url+'202.204.80.112',headers = kv)
r.raise_for_status()
r.encoding=r.apparent_encoding
print(r.text[-500:])
except:
print("爬取失败")
alue="查询" class="form-btn" />
</form>
</div>
<div class="query-hd">ip138.com IP查询(搜索IP地址的地理位置)</div>
<h1 class="query">您查询的IP:202.204.80.112</h1><p class="result">本站主数据:北京市海淀区 北京理工大学 教育网</p><p class="result">参考数据一:北京理工大学 网络中心</p>
</div>
</div>
<div class="footer">
<a href="http://www.miitbeian.gov.cn/" rel="nofollow" target="_blank">沪ICP备10013467号-1</a>
</div>
</div>
<script type="text/javascript" src="/script/common.js"></script></body>
</html>