『第一周』网络爬虫之规则
中国大学MOOC课程笔记
【第一周】网络爬虫之规则
单元1:Requests库入门
安装
win+R cmd
pip install requsets
测试安装成功
import requests
get()方法
r = requests.get(url)#获得网页
#返回一个包含服务器资源的response对象
#构造一个向服务器请求资源的request对象
完整使用方法:
request.get(url,params=None,**kwargs)
#url:拟获取页面的url链接
#params:Url中的额外参数,字典或字节流格式,可选
#**kwargs:12个控制访问的参数
Response对象的属性
属性 | 说明 | 具体说明 |
---|---|---|
r.status_code | Http请求的返回状态,200表示连接成功,404表示失败 | 只有返回200,response其他属性才可用;404或其他某些原因出错将产生异常 |
r.text | Http响应内容的字符串形式,即,url对应的页面内容 | |
r.encoding | 从HTTP header中猜测的响应内容编码方式 | 如果header中不存在charset,则认为编码为ISO-8859-1 |
r.apparent_encoding | 从内容中分析出的相应内容编码方式(备选编码方式) | 根据网页内容分析出的编码方式,更准确 |
r.content | Http响应内容的二进制形式 |
爬取网页的通用代码框架
理解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 "error"
if name == "main":
url = "http://www.baidu.com"
print(getHTMLText(url))
HTTP协议及Requests库方法
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 |
Http协议与request库
HTTP协议方法 | Requests库方法 | 功能一致性 |
---|---|---|
GET | requests.get() | 一致 |
HEAD | requests.head() | 一致 |
POST | requests.post() | 一致 |
PUT | requests.put() | 一致 |
PATCH | requests.patch() | 一致 |
DELETE | requests.delete() | 一致 |
head()方法
>>>r=requests.head('http://httpbin.org/get')
>>>r.headers
{'Content-Length':'238','Access-Control-Allow-Origin':'*',
'Access-control-Allow-Credentials':'true',
'Content-Type':'application/json',
'Server':‘nginx','Connection':‘keep-alive',
'Date':'Sat,18 Feb 2017 12:07:44GMT'}
>>>r.text
..
post()方法
#向URL POST一个字典自动编码为form(表单)
>>>payload={'key1':'value1','key2':'value2'}
>>>r=requests.post("http://httpbin.org/post',data=payload)
>>>print(r.text)
{..
"form":{
"key2":"value2",
"key1":"value1"
},
}
#向URL POST一个字符串自动编码为data
>>>r=requests.post('http://httpbin.org/post',data='ABC')
>>>print(r.text)
{...
"data":"ABC"
"form":{},
}
put()方法
>>>payload={'key1':'value1','key2':'value2'} }
>>>r=requests.put('http://httpbin.org/put',data= payload)
>>>print(r.text)
{...
"form":{
"key2":"value2",
"key1":"value1"
},
}
Requests库主要方法解析
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 |
1.
requests.request(method,url,**kwargs)
#method:请求方式,对应get/put/post等7种
#url:拟获取页面的url链接
#**kwargs:控制访问的参数,共13个
#params:字典或字节序列,作为参数增加到url中
#data:字典、字节序列或文件对象,作为request的内容
#json:JSON格式的数据,作为Request的内容
#headers:字典,HTTP定制头
#cookies:字典或CookieJar,Request中的cookie
#auth:元组,支持HTTP认证功能
#files:字典类型,传输文件
#timeout:设定超时时间,单位为s
#防止对爬虫对逆追踪
#proxies:字典类型,设定访问代理服务器,可以增加登录认证
#高级功能
#allow_redirects:True/False,默认True,重定向开关
#stream:True/False,默认True,获取内容立即下载开关
#verify:True/False,默认True,认证SSL证书开关
#cert:本地SSL证书路径
2.
requests.get(url,params=None,**kwargs)
#url:拟获取页面的url链接
#params:url中的额外参数,字典或字节流格式,可选
#**kwargs:12个控制访问的参数
3.
requests.head(url,**kwargs)
#url:拟获取页面的url链接
#**kwargs:13个控制访问的参数
4.
requests.post(url,data=None,json=None,**kwargs)
#url:拟获取页面的url链接
#data:字典、字节序列或文件,Request的内容
#json:JSON格式的数据,Request的内容
#**kwargs:11个控制访问的参数
5.
requests.put(url,data=None,**kwargs)
#url:拟获取页面的url链接
#data:字典、字节序列或文件,Request的内容
#**kwargs:12个控制访问的参数
6.
requests.patch(url,data=None,**kwargs)
#url:拟获取页面的url链接
#data:字典、字节序列或文件,Request的内容
#**kwargs:12个控制访问的参数
7.
requests.delete(url,**kwargs)
#url:拟获取页面的url链接
#**kwargs:13个控制访问的参数
PS:不常用字段放在可选字段中
单元小结
网络连接有风险,异常处理很重要
单元2:网络爬虫的“盗亦有道”
网络爬虫引发的问题
网络爬虫的限制
- 来源审查:判断User-Agent进行限制
- 检查来访HTTP协议头的User-Agent域,只响应浏览器或友好爬虫的访问。
- 发布公告:Robots协议
- 告知所有爬虫网站的爬取策略,要求爬虫遵守。
Robots协议
以京东(www.jd.com)为例访问其robots协议:www.jd.com/robots.txt
Robots协议基本语法
“#” 表示注释,“*”代表所有,“/”代表根目录
Robots协议的遵守方式
Robots协议的使用
- 网络爬虫:自动或人工识别robots.txt,再进行内容爬取。
- 约束性:Robots协议是建议但非约束性,网络爬虫可以不遵守,但存在法律风险。
对Robots协议的理解
1 | 2 | 3 |
---|---|---|
访问量很小:可以遵守 | 非商业且偶尔:建议遵守 | 必须遵守 |
访问量较大:建议遵守 | 商业利益:必须遵守 | 必须遵守 |
爬取网页 玩转网页 | 爬取网站 爬取系列网站 | 爬取全网 |
单元3:Requests库网络爬虫实战(5个实例)
实例1:京东商品页面的爬取
import requests
url = "https://item.jd.com/6449103.html"
try:
r = requests.get(url, timeout = 30)
r.raise_for_status()#如果状态不是200,引发HTTPError异常
r.encoding = r.apparent_encoding print(r.text[:1000])
except:
print("error")
实例2:亚马逊商品页面的爬取
#初写代码
import requests
url = "https://www.amazon.cn/dp/B07CM2DX6J/ref=sr_1_2?ie=UTF8&qid=1549169407&sr=8-2&keywords=%E7%B4%A2%E5%B0%BC6300%E5%BE%AE%E5%8D%95"
r = requests.get(url)
r.raise_for_status
'''
out:
<bound method Response.raise_for_status of <Response [503]>>
'''
#在加上两行代码
r.encoding = r.apparent_encoding
r.request.headers
'''
out:
{'User-Agent': 'python-requests/2.14.2', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
!!!!!'User-Agent': 'python-requests/2.14.2'!!!!!
'''
#完整代码
import requests
url = "https://www.amazon.cn/dp/B07CM2DX6J/ref=sr_1_2?ie=UTF8&qid=1549169407&sr=8-2&keywords=%E7%B4%A2%E5%B0%BC6300%E5%BE%AE%E5%8D%95"
try:
kv = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
r = requests.get(url,headers = kv)
r.raise_for_status()#如果状态不是200,引发HTTPError异常
r.encoding = r.apparent_encoding print(r.text[:2000])
except:
print("error")
实例3:百度/360搜索关键词提交
搜索引擎关键词提交接口
百度的关键词接口:http://www.baidu.com/s?wd=keyword
360的关键词接口:http://www.so.com/s?q=keyword
#初写代码
import requests
kv = {'wd':'python'}#构造键值对
url = "http://www.baidu.com/s"
r = requests.get(url,params = kv)
r.status_code
#Out[1]:200
r.request.url
#Out[2]:'http:www.baidu.com/s?wd=python'
len(r.text)
#Out[3]:430022 #430K左右
#完整代码
import requests
keyword = "Python"
try:
kv = {'wd':keyword}
url = "http://www.baidu.com/s"
r = requests.get(url,params = kv)
print(r.request.url)
r.raise_for_status()
print(len(r.text))
except:
print("error")
实例4:网络图片对爬取和存储
#初写代码
import requests
path = "F:/7IT/JupyterNotebook/requests小实例/photo/abc.jpg"
url = "http://image.nationalgeographic.com.cn/2017/0211/20170211061910157.jpg"
r = requests.get(url)
r.raise_for_status
#二进制存储
with open(path, 'wb') as f:
f.write(r.content)
f.close()
#完整代码
import requests
import os
url = "http://image.nationalgeographic.com.cn/2017/0211/20170211061910157.jpg"
root = "F://7IT//JupyterNotebook//requests小实例//photo//"
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("sucessfully save!")
else: print("file exits")
except:
print("error")
实例5:IP地址归属地的自动查询
#初写代码
import requests
url = "http://www.ip138.com/ips138.asp?ip="
r = requests.get(url + '202.204.80.112')
r.status_code
r.encoding = r.apparent_encoding
r.text[-500:]#检测数据时若无限制,会导致无效,尽量对text有所限制
#完整代码
import requests
url = "http://www.ip138.com/ips138.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("errror")