单元1:Requests库入门
Requests库安装
命令提示符,pip安装
Requests库的7个主要方法
方法 | 说明 |
---|---|
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库的get()方法
r=requests.get(url)
构造一个向服务器请求资源的Requests对象,返回一个包含服务器资源的Response对象。
完整方法为
requests.get(url, params = None, **kwargs)
- url:获取页面的url链接
- params:url中的额外参数,字典或字节流格式,可选
- **kwargs:12个控制访问的参数
调用.requests()方法实现
2个重要对象:Response和Requests
Response对象包含爬虫返回的内容
Response对象的属性
属性 | 说明 |
---|---|
r.status_code |
HTTP请求的返回状态,200表示连接成功,404表示失败 |
r.text |
HTTP响应内容的字符串形式,即,url对应的页面内容 |
r.encoding |
从HTTP header中猜测的响应内容编码方式 |
r.apparent_encoding |
从内容中分析出的响应内容编码方式(备用编码方式) |
r.content |
HTTP响应内容的二进制形式 |
爬取网页的通用代码框架
网络连接有危险,异常处理很重要。
理解Requests的异常
异常 | 说明 |
---|---|
requests.ConnectionError |
网络连接错误异常,如DNS查询失败、拒绝连接等 |
requests.HTTPError |
HTTP错误异常 |
requests.URLRequired |
HRL缺失异常 |
requests.TooManyRedirects |
超过最大重定向次数,产生重定向异常 |
requests.ConnectTimeout |
连接远程服务器超时异常 |
requests.Timeout |
请求URL超时,产生超时异常 |
理解Requests库的异常
异常 | 说明 |
---|---|
r.raise_for_status() |
如果不是200,产生异常requests.HTTPError |
爬取网页的通用代码框架
def getHTMLText(url):
try:
r = requests.get(url, timeout = 30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "产生异常"
使用该框架,例如:
if __name__ == "__main__":
url = "http://www.baidu.com"
print(getHTMLText(url))
HTTP协议及Requests库方法
Requests有7个主要方法
理解HTTP协议:
- 超文本传输协议
- 基于请求与响应模式的、无状态的应用层协议
- 采用URL作为定位网络资源的标识
http://host[:port][path]
,host:合法的Internet主机域名或地址;port:端口号,默认80;path:请求资源的路径 - URL:通过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。
- 采用PATCH,仅向URL提交UserName的局部更新请求
- 采用PUT,必须将所有20个字段一并提交到URL,未提交字段被删除
与Requests库方法一一对应
head()方法
- 用很少流量获取网络资源概要信息
post()方法
- 向URL POST一个字典,自动编码为form(表单)
- POST一个字符串,自动编码为data
put()方法:
- 与post()方法类似,将原数据覆盖掉
Requests库主要方法解析
7个主要方法
requests.request(method, url, **kwargs)
- method:请求方式,对应get/put/post等7种
- **kwargs:控制访问的参数,13种:
params:字典或字节序列,作为参数增加到url中
data:字典、字节序列或文件对象,作为Request的内容
json:JSON格式的数据,作为Requests的内容
headers:字典,HTTP定制头
cookies:字典或CookieJar,Request中的cookie
auth:元组,支持HTTP认证功能
files:字典类型,传输文件
timeout:设定超时时间,秒为单位
proxies:字典类型,设定访问代理服务器,可以增加登录认证
allow_redirects:True/False,默认为True,重定向开关
stream:True/False,默认为True,获取内容立即下载开关
verify:True/False,默认为True,认证SSL证书开关
cert:本地SSL证书路径
requests.get(url, params = None, **kwargs)
- params:url中的额外参数,字典或字节流格式,可选
- **kwargs:12个控制访问的参数
requests.head(url, **kwargs)
- **kwargs:13个控制访问参数
requests.post(url, data = None, json = None, **kwargs)
- data:字典、字节序列或文件,Request的内容
- json:JSON格式的数据,Request的内容
- **kwargs:11个控制访问参数
requests.put(url, data = None, **kwargs)
- data:字典、字节序列或文件,Request的内容
- **kwargs:12个控制访问参数
requests.patch(url, data = None, **kwargs)
- data:字典、字节序列或文件,Request的内容
- **kwargs:12个控制访问参数
requests.delete(url, **kwargs)
- **kwargs:13个控制访问参数
由于网络安全限制,最常用的是get()方法
单元2:网络爬虫的“盗亦有道”
网络爬虫引发的问题
网络爬虫尺寸:
- 爬取网页,玩转网页:小规模,数据量小,爬取速度不敏感,Requests库
- 爬取网站,爬取系列网站:中规模,数据规模较大,爬取速度敏感,Scrapy库
- 爬取全网:大规模,搜索引擎,爬取速度关键,定制开发
网络爬虫的“骚扰”
受限于编写水平和目的,网络爬虫会对Web服务器带来巨大的资源开销。
网络爬虫的法律风险
服务器上的数据有产权归属。
网络爬虫获取数据后牟利将带来法律风险。
网络爬虫泄露隐私
网络爬虫可能具备突破简单访问控制的能力,获得被保护数据从而泄露个人隐私。
限制网络爬虫
来源审查:判断User-Agent进行限制
- 只响应浏览器或友好爬虫的访问
发布公告:Robots协议
- 告知所有爬虫网站的爬取策略,需要爬虫遵守
Robots协议
Robots Exclusion Standard 网络爬虫排除标准
作用:告知网络爬虫哪些页面可以抓取,哪些不行。
形式:在网站根目录下的robots.txt文件
例如:京东的Robots协议:https://www.jd.com/robots.txt
User-agent: *
Disallow: /?*
Disallow: /pop/.html
Disallow: /pinpai/.html?*
User-agent: EtaoSpider
Disallow: /
User-agent: HuihuiSpider
Disallow: /
User-agent: GwdangSpider
Disallow: /
User-agent: WochachaSpider
Disallow: /
Robots协议基本语法
# 注释,*代表所有,/代表根目录
User-agent: *
Disallow: /
Robots协议的遵守方式
Robots协议的使用
网络爬虫:自动或人工识别robots.txt文件,再进行内容爬取。
约束性:Robots协议是建议但非约束性,如果不遵守可能存在法律风险。
类人行为可以不参考Robots协议。
单元3:Requests网络爬虫实战
实例1:京东商品页面的爬取
爬取商品:https://item.jd.com/100002716279.html
>>> import requests
>>> r = requests.get("https://item.jd.com/100002716279.html")
>>> r.status_code
200
>>> r.encoding
'gbk'
>>> r.text[:1000]
'<!DOCTYPE HTML>\n<html lang="zh-CN">\n<head>\n <!-- shouji -->\n <meta http-equiv="Content-Type" content="text/html; charset=gbk" />\n <title>【AppleiPad mini】Apple iPad mini 5 2019年新款平板电脑 7.9英寸(64G WLAN版/A12芯片/MUQW2CH/A)深空灰色【行情 报价 价格 评测】-京东</title>\n <meta name="keywords" content="AppleiPad mini,AppleiPad mini,AppleiPad mini报价,AppleiPad mini报价"/>\n <meta name="description" content="【AppleiPad mini】京东JD.COM提供AppleiPad mini正品行货,并包括AppleiPad mini网购指南,以及AppleiPad mini图片、iPad mini参数、iPad mini评论、iPad mini心得、iPad mini技巧等信息,网购AppleiPad mini上京东,放心又轻松" />\n <meta name="format-detection" content="telephone=no">\n <meta http-equiv="mobile-agent" content="format=xhtml; url=//item.m.jd.com/product/100002716279.html">\n <meta http-equiv="mobile-agent" content="format=html5; url=//item.m.jd.com/product/100002716279.html">\n <meta http-equiv="X-UA-Compatible" content="IE=Edge">\n <link rel="canonical" href="//item.jd.com/100002716279.html"/>\n <link rel="dns-prefetch" href="//mi'
说明页面返回信息,全部代码为:
import requests
url = "https://item.jd.com/100002716279.html"
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[:1000])
except:
print("爬取失败")
实例2:亚马逊商品页面的爬取
>>> import requests
>>> r = requests.get("https://www.amazon.cn/dp/B005T63BEM/ref=lp_1559274071_1_1?s=electronics&ie=UTF8&qid=1569760137&sr=1-1")
>>> r.status_code
200
>>> r.encoding
'UTF-8'
>>> r.text[:1000]
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n\n\n\n\n\n\n\n \n\n \n\n\n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n \n\n\n\n\n\n \n \n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n <!doctype html><html class="a-no-js" data-19ax5a9jf="dingo">\n <head><script>var aPageStart = (new Date()).getTime();</script><meta charset="utf-8">\n\n \n\n\n\n <link rel="dns-prefetch" href="//images-cn.ssl-images-amazon.com">\n\n\n\n\n \n\n\n\n\n \n\n\n\n\n\n\n \n \n\n\n\n\n\n\n\n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n\n\n \n \n\n\n\n\n\n\n\n\n\n\n\n\n<script type="text/javascript">\nvar iUrl = "https://images-cn.ssl-images-amazon.com/images/I/415tpDfFbTL._SX300_QL70_.jpg";\n(function(){var i=new Image; i.src = iUrl;})();\n</script>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n \n \n\n\n\n\n\n\n\n<!-- -->\n<link rel="stylesheet" href="https://images-cn.ssl-images-amazon.com/images/I/21kpNOwB5dL._RC|71IGFd-taTL.css,11WnO6PP7GL.css,31ltTjVHNDL.css,21SfF47-e2L.css,31lx9mSsVLL.css,11g4B3l0OAL.css,312fqnjyyJL.c'
>>> r.request.headers
{'User-Agent': 'python-requests/2.22.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
User-Agent为'python-requests/2.22.0,如果被拒绝,可以更改头部信息的User-Agent为其他浏览器。
>>> kv = {'User-Agent':'Mozilla/5.0'}
>>> url = 'https://www.amazon.cn/dp/B005T63BEM/ref=lp_1559274071_1_1?s=electronics&ie=UTF8&qid=1569760137&sr=1-1'
>>> 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]
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n\n\n\n\n\n\n\n \n\n \n\n\n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n <!doctype html><html class="a-no-js" data-19ax5a9jf="dingo">\n <head>\n<script type="text/javascript">var ue_t0=ue_t0||+new Date();</script>\n<script type="text/javascript">\nwindow.ue_ihb = (window.ue_ihb || window.ueinit || 0) + 1;\nif (window.ue_ihb === 1) {\nvar ue_hob=+new Date();\nvar ue_id=\'E5W4931DMCTPC168HBBY\',\nue_csm = window,\nue_err_chan = \'jserr-rw\',\nue = {};\n(function(d){var e=d.ue=d.ue||{},f=Date.now||function(){return+new Date};e.d=function(b){return f()-(b?0:d.ue_t0)};e.stub=function(b,a){if(!b[a]){var c=[];b[a]=function(){c.push([c.slice.call(arguments),e.d(),d.ue_id])};b[a].replay=function(b){for(var a;a=c.shift();)b(a[0],a[1],a[2])};b[a].isStub=1}};e.exec=function(b,a){return function(){try{return b.apply(this,arguments)}catch(c){ueLogError(c,{attribution:a||"undefined",logLevel:"WARN"})}}}})(ue_csm);\n\nue.stub(ue,"log");ue.stub(ue,"onunload");ue.stub(ue,"onflu'
全部代码
import requests
url = 'https://www.amazon.cn/dp/B005T63BEM/ref=lp_1559274071_1_1?s=electronics&ie=UTF8&qid=1569760137&sr=1-1'
try:
kv = {'User-Agent':'Mozilla/5.0'}
r = requsts.get(url, headers = kv)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[1000:2000])
except:
print('爬取失败')
实例3:百度/360搜索关键词提交
自动提交关键词并获得结果。
搜索引起关键词提交接口
百度关键词接口:http://www.baidu.com/s?wd=keyword
360关键词接口:http://www.so.com/s?q=keyword
使用params
>>> import requests
>>> kv = {'wd':'Python'}
>>> r = requests.get('http://www.baidu.com/s', params = kv)
>>> r.status_code
200
>>> r.request.url
'http://www.baidu.com/s?wd=Python'
>>> len(r.text)
358258
完整代码
import requests
keyword = 'Python'
try:
kv = {'wd':keyword}
r = requests.get('http://www.baidu.com/s', params = kv)
print(r.request.url)
r.raise_for_status()
print(len(r.text))
except:
print('爬取失败')
360的方法类似,代码为
import requests
keyword = 'Python'
try:
kv = {'q':keyword}
r = requests.get('http://www.so.com/s', params = kv)
print(r.request.url)
r.raise_for_status()
print(len(r.text))
except:
print('爬取失败')
实例4:网路图片的爬取和存储
网络图片链接的格式:
http://www.example.com/picture.jpg
图片网址为:https://www.nationalgeographic.com/content/dam/expeditions/landing-pages/North-America/hero-national-parks2.adapt.1900.1.jpg
保存为C盘abc.jpg
>>> import requests
>>> path = 'C:/abc.jpg'
>>> url = 'https://www.nationalgeographic.com/content/dam/expeditions/landing-pages/North-America/hero-national-parks2.adapt.1900.1.jpg'
>>> r = requests.get(url)
>>> r.status_code
200
>>> with open(path, 'wb') as f:
f.write(r.content)
300340
>>> f.close()
完整代码为
import requests
import os
url = 'https://www.nationalgeographic.com/content/dam/expeditions/landing-pages/North-America/hero-national-parks2.adapt.1900.1.jpg'
root = "C://"
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('爬取失败')
考虑出现的问题,并对相应的异常进行处理。
修改代码,可以获取不同的资源。
实例5:IP地址归属地的自动查询
通过ip138网站提交ip地址后,链接变为:
http://m.ip138.com/ip.asp?ip=ipaddress
>>> f.close()
>>> import requests
>>> url = 'http://m.ip138.com/ip.asp?ip='
>>> r = requests.get(url + '202.204.80.112')
>>> r.status_code
200
>>> r.text[-500:]
'value="查询" class="form-btn" />\r\n\t\t\t\t\t</form>\r\n\t\t\t\t</div>\r\n\t\t\t\t<div class="query-hd">ip138.com IP查询(搜索IP地址的地理位置)</div>\r\n\t\t\t\t<h1 class="query">您查询的IP:202.204.80.112</h1><p class="result">本站主数据:北京市海淀区 北京理工大学 教育网</p><p class="result">参考数据一:北京市 北京理工大学</p>\r\n\r\n\t\t\t</div>\r\n\t\t</div>\r\n\r\n\t\t<div class="footer">\r\n\t\t\t<a href="http://www.miitbeian.gov.cn/" rel="nofollow" target="_blank">沪ICP备10013467号-1</a>\r\n\t\t</div>\r\n\t</div>\r\n\r\n\t<script type="text/javascript" src="/script/common.js"></script></body>\r\n</html>\r\n'
完整代码
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('爬取失败')
许多网站人机交互都是以链接的方式提交,知道提交的链接形式可以用Python模拟提交。