Resquests库入门

Resquests库的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 = requrests.get(url,params=None,**kwargs)

url:要获取的网页url链接地址

Params: url中的额外参数,字典或者字节流格式

**kwargs:12个控制访问的参数

r = requests.get(url)

第一步,构造一个向服务器请求资源的Request对象

第二步,返回一个包含服务器 资源的Response对象

type(r) --> r是Response格式

Response对象包含服务器返回的所有信息,也包含请求的Request信息

属性 说明
r.status_code HTTP请求的返回状态,200表示连接成功,404表示失败
r.text HTTP响应内容的字符串形式,即url对应的页面内容
r.encoding 从HTTP header中猜测的响应内容编码方式,这个编码不一定准确,若header中没有charset字段则默认为ISO-8859-1编码模式,则无法解析中文
r.apparent_encoding 从内容中分析出的响应内容编码方式(备选编码方式)
r.content HTTP响应内容的二进制形式

Requests库的异常

异常 说明
requests.ConnectionError 网络链接错误
requests.HTTPError HTTP错误异常
requests.URLRequired URL缺失异常
requests.TooManyRedirects 重定向次数超过最大次数,产生重定向异常
requests.ConnectTimeout 与远程服务器链接超时异常
requests.Timeout 请求URL超时,也就是URL从请求到获取请求内容这个过程超过预定时间,超时异常

Response异常

r.raise_for_status() 判断r.status_code是否等于200,如果不是200,产生HTTPError异常

爬取网页的通用代码框架

import requests
import ssl


ssl._create_default_https_context = ssl._create_unverified_context  # 全局取消证书验证
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))

Requests库方法和http协议

  • http协议:Hypertext Transfer Protocol,超文本传输协议

  • HTTP是一个基于“请求与响应”模式的、无状态的应用层协议

  • HTTP协议采用URL作为定位网络资源的标识

  • URL格式如下:http://host[:port][path]

    Host:合法的Internet主机域名或者IP地址

    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,没有提交的字段将会被删除

patch的最主要的好吃就是节省网络带宽

http协议和requests库

http协议get、head、post、put、patch、delete与requests库中的方法:requests.get()、requests.head()、requests.post()、requests.put()、requests.patch()、requests.delete()的功能是一致的

requests库head()用法

import requests


r = requests.head('http://httpbin.org/get')
print(r.headers)

-> {'Date': 'Fri, 10 Dec 2021 03:12:50 GMT', 'Content-Type': 'application/json', 'Content-Length': '308', 'Connection': 'keep-alive', 'Server': 'gunicorn/19.9.0', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true'}

requests库post()用法

import requests
"""post用法"""

payload = {
    'key1': 'value1',
    'key2': 'value2'
}
r = requests.post('http://httpbin.org/post', data=payload)
print(r.text)

->{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "key1": "value1", 
    "key2": "value2"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "23", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.26.0", 
    "X-Amzn-Trace-Id": "Root=1-61b2c6ce-73fa4750611789b955b64336"
  }, 
  "json": null, 
  "origin": "223.104.151.124", 
  "url": "http://httpbin.org/post"
}
  • 发现通过post提交的字典都自动编码为form
import requests
"""post用法"""

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.26.0", 
    "X-Amzn-Trace-Id": "Root=1-61b2c8dc-1d8157a4005e944f1209fa6b"
  }, 
  "json": null, 
  "origin": "223.104.151.100", 
  "url": "http://httpbin.org/post"
}
  • 通过POST向URL传送一个字符串被自动编码为data

requests库put()用法

import requests
"""put用法"""

payload = {
    'key3': 'value11',
    'key4': 'value22'
}
r = requests.put('http://httpbin.org/put', data=payload)
print(r.text)

->{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "key3": "value11", 
    "key4": "value22"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "25", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.26.0", 
    "X-Amzn-Trace-Id": "Root=1-61b2c9db-51a867c810e2faa17dc237c9"
  }, 
  "json": null, 
  "origin": "223.104.151.124", 
  "url": "http://httpbin.org/put"
}
  • 发现通过put向URL传递一个字典后,会覆盖原有在form下的数据

Requests库主要方法解析

requests.request()

requests.request(method, url, **kwargs)

  • Method :请求方式,应对get/put/post等七种

  • url:要获取页面的url链接

  • **kwargs:控制访问的参数,总共13个。

    • params:字典或者字节序列,作为参数增加到url中
    import requests
    
    
    dic = {
        'key1': 'value1',
        'key2': 'value2'
    }
    r = requests.request('Get', 'http://httpbin.org/get', params=dic)
    print(r.url)
    
    ->http://httpbin.org/get?key1=value1&key2=value2
    # 字典当中的内容附加到url后面了
    
    • data:字典、字节序列或者文件对象,作为Request内容
    import requests
    
    
    dic = {
        'key1': 'value1',
        'key2': 'value2'
    }
    r = requests.request('POST', 'http://httpbin.org/post', data=dic)
    print(r.text)
    -------------------------------------
    {
      "args": {}, 
      "data": "", 
      "files": {}, 
      "form": {
        "key1": "value1", 
        "key2": "value2"
      }, 
      "headers": {
        "Accept": "*/*", 
        "Accept-Encoding": "gzip, deflate", 
        "Content-Length": "23", 
        "Content-Type": "application/x-www-form-urlencoded", 
        "Host": "httpbin.org", 
        "User-Agent": "python-requests/2.26.0", 
        "X-Amzn-Trace-Id": "Root=1-61b2fbe5-59a8d6916ef7981471d4afde"
      }, 
      "json": null, 
      "origin": "223.104.151.50", 
      "url": "http://httpbin.org/post"
    }
    
    
    import requests
    
    
    d = 'body'
    r = requests.request('POST', 'http://httpbin.org/post', data=d)
    print(r.text)
    ---------------------------------
    {
      "args": {}, 
      "data": "body", 
      "files": {}, 
      "form": {}, 
      "headers": {
        "Accept": "*/*", 
        "Accept-Encoding": "gzip, deflate", 
        "Content-Length": "4", 
        "Host": "httpbin.org", 
        "User-Agent": "python-requests/2.26.0", 
        "X-Amzn-Trace-Id": "Root=1-61b2fc2b-7f33c33014341c80049d902f"
      }, 
      "json": null, 
      "origin": "223.104.151.50", 
      "url": "http://httpbin.org/post"
    }
    
    • json:json格式数据,作为Request内容
    import requests
    
    dic = {
        'key1': 'value1',
        'key2': 'value2'
    }
    r = requests.request('POST', 'http://httpbin.org/post', json=dic)
    
    • headers:字典,http定制头
    import requests
    
    hd = {'user-agent':'Chorme/10'}
    r = requests.request('POST', 'http://httpbin.org/post', headers=hd)
    
    • auth:元组,支持HTTP认证功能
    • files:字典类型,传输文件
    import requests
    
    fs = {'file':open('data.xlsx', 'rb')}
    r = requests.request('POST', 'http://httpbin.org/post', files=fs)
    
    • timeout:设定超时时间,以秒为单位
    import requests
    
    r = requests.request('GET', 'http://httpbin.org/get', timeout=10)
    
    • proxies:字典类型,设定代理服务器,可以增加登录认证
    >>>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)
    
    • allow_redirects:True/False,默认为True,设定重定向的开关
    • stream:True/False,默认为True,获取内容立即下载开关
    • verify:True/False,默认为True,认证SSL证书开关
    • cert:本地SSL证书路径
  • 劫持session。如果使用requests的post方法登录了某个网站,再想获取登陆后自己的信息,就需要再使用requests的get方式去请求个人信息页面,这相当于打开了两个浏览器,是两个独立的操作,对应两个完全不想关的session,想要获取到自己登录的信息是不可能的。但是给两次请求加上同一个cookie的方法太繁琐,劫持session的方法会更加简便

    """劫持session"""
    import requests
    
    
    s = requests.Session()
    s.get('https://httpbin.org/cookies/set/number/123456789')
    r = requests.get('https://httpbin.org/cookies')
    print(r.text)
    
    ----------------------------
    {
      "cookies": {"number": "123456789"}
    }
    

这个程序的运行结果中含有cookie

requests.get(url, params=None, **kwargs)

url:要获取页面的URL链接

params:URL中额外参数,字典或者字节流

**kwargs:12个requests.request控制访问的参数

requests.head(url, **kwargs)

url:要获取页面的URL链接

**kwargs:12个requests.request控制访问的参数

requests.post(url, data=None, json=None, **kwargs)

url:要获取页面的URL链接

data:字典、字节序列或者文件对象,作为Request内容

json:json格式数据,作为Request内容

**kwargs:12个requests.request控制访问的参数

requests.put(url, data=None, **kwargs)

url:要获取页面的URL链接

data:字典、字节序列或者文件对象,作为Request内容

**kwargs:12个requests.request控制访问的参数

requests.patch(url, data=None, **kwargs)

url:要获取页面的URL链接

data:字典、字节序列或者文件对象,作为Request内容

**kwargs:12个requests.request控制访问的参数

requests.delete(url, **kwargs)

url:要删除页面的URL链接

**kwargs:12个requests.request控制访问的参数

requests.get(url, params=None, **kwargs)

url:要删除页面的URL链接

params:URL中额外参数,字典或者字节流

**kwargs:12个requests.request控制访问的参数

requests.request()与相对应的requests.get()等方法功能相同

爬虫的法律风险

服务器上的数据有产权归属,网络爬虫获取数据牟利将带来法律风险

网络爬虫的限制

  • 来源审查:判断User-Agent进行限制,检查来访HTTP协议头的User-Agent域,只响应浏览器友好爬虫的访问

  • 发布公告:robots协议

    告知全网爬虫网站的爬取策略,要求爬虫遵守

robots协议

  • 在网站根目录下

robots协议的使用

自动或者人工识别robots.txt,再进行爬取

对robots协议的理解

类人行为可以不参考robots协议(就是和人类访问行为类似的爬虫行为,如一天只访问一两次)

练习

"""爬取网站图片"""
import requests
import os


root_path = '/Users/dreamer/Desktop/python_learn/'
url = 'http://img0.dili360.com/pic/2020/12/23/5fe2b719eaff77q20149174_t.jpg@!rw9'
file_path = root_path + url.split('/')[-1] + '.jpg'
hd = {'User-Agent': 'Mozilla/5.0'}
try:
    if not os.path.exists(root_path):
        os.mkdir(root_path)
    if not os.path.exists(file_path):
        r = requests.get(url, headers=hd)
        with open(file_path, 'wb') as f:
            f.write(r.content)   # 因为图片是二进制格式,所以使用r.content存储二进制
            f.close()
            print('文件保存成功')
    else:
        print('文件已经存在')
except:
    print('爬取失败')
import requests

ip = input('输入你要查询的ip地址: ')
pa = 'ip=' + ip + '&action=2'
url = 'https://www.ip138.com/iplookup.asp'
hd = {'User-Agent': 'Mozilla/5.0'}

try:
    r = requests.get(url, params=pa, headers=hd)
    r.raise_for_status()
    r.encoding = r.apparent_encoding  # 确保编码正确
    print(r.text)
except:
    print('查询失败')
posted @ 2021-12-13 10:04  写代码的小灰  阅读(308)  评论(0)    收藏  举报