程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

模块(0)

标准库(0)

标签  

标准库模块(0)

字符串(0)

日期归档  

[网络爬虫基础] 1. Request库

发布于2020-02-25 16:23     阅读(474)     评论(0)     点赞(23)     收藏(1)


[网络爬虫基础] 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': }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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-1
  • apparent_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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

第一次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))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

三、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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在使用后六个方法时,把它们常用的参数作为显式定义的参数量放到了函数的声明里,而不常用的参数就放到了函数的可选参数中

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"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

四、Robots协议

网页对网络爬虫的限制主要有两种:

  1. 来源审查:判断User‐Agent进行限制,检查来访HTTP协议头的User‐Agent域,只响应浏览器或友好爬虫的访问。
  2. 发布公告:Robots协议,告知所有爬虫网站的爬取策略,要求爬虫遵守

Robots Exclusion Standard,网络爬虫排除标准

  • 作用:网站告知网络爬虫哪些页面可以抓取,哪些不行
  • 形式:在网站根目录下的robots.txt文件

Robots协议基本语法:* 代表所有,/代表根目录,具体形式为:

User‐agent: *
Disallow: /
  • 1
  • 2

分析京东的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这几个网络爬虫不能访问京东的任何页面。)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

实战系列

一、网络图片的爬取与存储

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("爬取失败")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

二、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("爬取失败")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

嵩天老师提供的程序返回了爬取失败,应该是网站对爬虫的来源进行审查,添加了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("爬取失败")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
发布了108 篇原创文章 · 获赞 14 · 访问量 7159


所属网站分类: 技术文章 > 博客

作者:追梦骚年

链接:https://www.pythonheidong.com/blog/article/233495/598ada9609f0610977a8/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

23 0
收藏该文
已收藏

评论内容:(最多支持255个字符)