【python】python爬虫requests库详解

1.安装:pip install requests

简介:Requests是一个优雅而简单的Python HTTP库,与之前的urllibPython的标准库相比,Requests的使用方式非常的简单、直观、人性化,Requests的官方文档非常的完善详尽,文档地址查看:中文官方文档&&英文官方文档。

2.Requests请求

Requests请求的构造的直接传入需要的参数即可

源码:
def request(method, url,
params=None, 
data=None, 
headers=None, 
cookies=None,
timeout=None, 
allow_redirects=True, 
proxies=None,
verify=None,  
json=None):

参数详解:

(1)请求方法method:

(2)统一资源定位符url

(3)传递url参数params

传递URL参数也不用再像urllib中那样需要去拼接URL,而是简单的,构造一个字典,并在请求时将其传递给params参数:

import requests
params = {'key1': 'value1', 'key2': 'value2'}
resp = requests.get("http://xxx/get", params=params)
print(resp.url)

结果为:http://xxx/get?key1=value1&key2=value2

提示:
  有时候我们会遇到相同的url参数名,但有不同的值,而python的字典又不支持键的重名,那么我们可以把键的值用列表表示:

import requests
params = {'key1': 'value1', 'key2': ['value2', 'value3']}
resp = requests.get("http://xxx/get", params=params)
print(resp.url)
————————————————
结果为:http://xxx/get?key1=value1&key2=value2&key2=value3

 (4)传递form表单数据——data

将放进data的数据转换为form表单数据,同时不能传json数据,json数据为null。注意:json和data二者只能同时存在其一

   import requests    
   data = {'key1': 'value1', 'key2': ['value2', 'value3']}
    url = 'http://httpbin.org/post'
    resp = requests.post(url=url, data=data)
    print(resp.text)

返回结果:
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "key1": "value1", 
    "key2": [
      "value2", 
      "value3"
    ]
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "35", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.26.0", 
    "X-Amzn-Trace-Id": "Root=1-61e96267-22db06944c159ee745a4c2fa"
  }, 
  "json": null, 
  "origin": "180.156.244.218", 
  "url": "http://httpbin.org/post"
}


Process finished with exit code 0

(5)传递json数据——json

  将json对应的数据放进json参数里。

   import requests    
   json = {'key1': 'value1', 'key2': ['value2', 'value3']}
    url = 'http://httpbin.org/post'
    resp = requests.post(url=url, json=json)
    print(resp.text)

(6)自定义headers

如果想自定义请求的Headers,同样的将字典数据传递给headers参数。

(7)自定义cookies

import requests
from fake_useragent import UserAgent

r = requests.get('https://www.baidu.com',headers = {'User-Agent': UserAgent().random})
print(r.cookies)

print('*'*25)
print(r.cookies.items())
print('*'*25)

for key,value in r.cookies.items():
    print(key + "=" + value)

在这里插入图片描述

此处我们首先调用cookies属性即可成功得到cookies,可以发现他是个RequestsCookieJar类型。然后用items()方法将其转化为元组组成的列表,遍历输出每一个Cookie的名称和值,实现Cookie的遍历解析。

#另一种方法,使用requests.utils.dict_from_cookiejar把cookiejar对象转化为字典。

import requests
from fake_useragent import UserAgent

url = 'http://www.baidu.com'
response = requests.get(url=url, headers ={'user-agent': UserAgent().random})
cookie = requests.utils.dict_from_cookiejar(response.cookies)
print(cookie)

"""
输出:
{'BAIDUID_BFESS': '52EB4182E0877DFD9DBA8E0793772027:FG=1', 'H_PS_PSSID': '33802_34222_31254_33848_34112_34107_26350_34093', 'BDSVRTM': '0', 'BD_HOME': '1'}
"""

 使用Cookie维持登录状态的两种方法:

import requests

headers = {
    'cookie': '此处换为你自己的Cookie即可!',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'
}

r = requests.get('https://user.qzone.qq.com/这里写上要登录的QQ号/infocenter', headers=headers)
print(r.text)



通过cookies参数来设置,直接将cookies构造字典传入即可!
cookies={"cookies":"xxxx"}
r = requests.get(url,cookies=cookies)

(8)设置代理proxies

  1. 什么是代理?
    代理IP是一个ip ,指的是一个代理服务器。

  2. 要晓得正向代理和反向代理是啥?
    知不知道服务器的地址做为判断标准:知道就是正向代理,不知道就是反向代理。

  3. 代理ip的分类(常见有两大分类依据:匿名度&&协议)
      ①匿名度:
       透明代理 :目标服务器可以通过代理找到你的ip;
       匿名代理 :两者之间;
       高匿代理 :在爬虫中经常使用,目标服务器无法获取你的ip。
      ②协议:(根据网站使用的协议不同,需要使用响应的协议代理服务)
       http代理:目标的url为http协议;
       https代理:目标url为https协议;
       socks代理 :只是简单的传递数据包,不关心是何种协议,比http和HTTPS代理消耗小, 可以转发http和https的请求。

    为何使用代理?
    (1)让服务器以为不是同一个客户端在请求;
    (2)防止我们的真实地址被泄露,防止被追究。

  4. 用法:当我们需要使用代理时,同样构造代理字典,传递给proxies参数
    通过proxies参数来设置,直接将cookies构造字典传入即可!
    proxies={"http":"xxxx","https":"xxxx"}
    r = requests.get(url,proxies=proxies)

(9)重定向allow_redirects

  在网络请求中,我们常常会遇到状态码是3开头的重定向问题,在Requests中是默认开启允许重定向的,即遇到重定向时,会自动继续访问。

(10)禁止证书验证vertify
 有时候我们使用了抓包工具,这个时候由于抓包工具提供的证书并不是由受信任的数字证书颁发机构颁发的(比如,之前12306的整数就没有被官方CA机构信任,就会出现证书验证错误的结果!),所以证书的验证会失败,这时我们就需要关闭证书验证。

  解决方法:在请求的时候把verify参数设置为False就可以关闭证书验证了。


小拓展:
  但是关闭验证后,会有一个比较烦人的warning,它建议我们给它指定证书。我们可以通过设置忽略警告的方式来屏蔽它:

(11)设置超时timeout
  
为了防止由于服务器不能及时响应而报错,而设置一个超时时间,即超过了这个时间还没有得到响应,那就报错!
  设置访问超时——设置timeout参数即可。(这个时间的计算是发出请求到服务器返回响应的时间)
  实际上:请求分为两个阶段,即连接(connect)和读取(read)。下面设置的timeout将用作连接和读取这二者的timeout总合。如果分别指定,就可以传入一个元组:timeout=(5,11,30)。

在这里插入图片描述

实际上,我们在多数爬虫开发中——超时参数timeout是和retrying模块(刷新)一起使用的!

  1. 使用retrying模块提供的retry方法
  2. 通过装饰器的方式,让被装饰的函数反复执行
  3. retry中可以传入参数 stop_max_attempt_number,让函数报错后继续重新执行,达到最大执行次数的上限,如果每次都报错,整个函数报错,如果中间有一个成功,程序继续往后执行

import requests
from retrying import retry

headers = {"User-Agent":"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Chrome/4.0.222.3 "}

@retry(stop_max_attempt_number=3)   # stop_max_attempt_number=3最大执行3次,还不成功就报错
def _parse_url(url):                                            # 前面加_代表此函数,其他地方不可调用
    print("*"*100)
    response = requests.get(url, headers=headers, timeout=3)    # timeout=3超时参数,3s内
    assert response.status_code == 200                          # assert断言,此处断言状态码是200,不是则报错
    return response.content.decode()


def parse_url(url):
    try:
        html_str = _parse_url(url)
    except Exception as e:
        print(e)
        html_str = None
    return html_str

if __name__ == '__main__':
    # url = "www.baidu.com"         # 这样是会报错的!
    url = "http://www.baidu.com"
    print(parse_url(url))

(12)文件上传

import requests

files = {'file': open('1.jpg','rb')}
r = requests.post("http://httpbin.org/post", files=files)
print(r.text)

 这个网站会返回响应,里面包含files这个字段,而form字段是空的,这证明文件上传部分会单独有个files字段来标识。

13)Prepared Request

  我们知道在urllib中可以将请求表示为数据结构,其中各个参数都可以通过一个Request对象来表示。这在requests中同样可以做到,这个数据结构叫做Prepared Request。如下:

from requests import Request,Session

url = 'http://httpbin.org/post'
data = {
    'name':'peter'
}
headers = {
    'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.29 Safari/525.13'
}

s = Session()
req = Request('POST', url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)

先用url,data,headers参数构造了一个Request对象,这时需要再调用Session的prepare_request()方法将其转换为一个Prepared Request对象,然后调用send()方法发送即可!

使用较少,但是这样使用的好处是:有了Request这个对象,就可以将请求当作独立的对象来看待,这样在进行队列调度时会非常方便! 

import requests

# res=requests.get("http://httpbin.org/get")       #功能:发起完整的网络请求

'''
源码:
def request(method, url,params=None, data=None, headers=None, cookies=None,
    timeout=None, allow_redirects=True, proxies=None,verify=None,  json=None):
'''

#1.method
# res=requests.post("http://httpbin.org")
# res=requests.delete("http://httpbin.org")

# url  字符串  统一资源定位符

# params    将放进params里的字典数据变为url的请求参数(如果是中文会自动编码)
# test_url="http://httpbin.org/get"
# params={"name":"allen","name2":"哈哈"}
# res=requests.get(url=test_url,params=params)
# print(res.text)

# data   将放进data的数据转换为form表单数据,同时不能传json数据,json数据为null
# test_url="http://httpbin.org/post"            #post提交数据
# data={"stu":"丸子","worker":"鲸落"}
# res=requests.post(url=test_url,data=data)
# print(res.text)

# json      将json对应的数据放进json数据里
# test_url="http://httpbin.org/post"               #post提交数据
# json={"name":"selffly"}    #'{"name":"selffly"}' json串形式也可以传,字典也可以传
# res=requests.post(url=test_url,json=json)
# print(res.text)

# 添加头部信息headers       添加cookies     添加timeout     设置代理proxies=None      verify=False安全验证(为False是忽略证书)
# test_url="http://httpbin.org/get"
# headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"}
# cookies={"sessionid":"dfsdaaagdgagdf"}
# proxies={'http':"127.0.0.1:8888"}           #这个代理胡写的,不可用
# res=requests.get(url=test_url,headers=headers,cookies=cookies,timeout=10,proxies=proxies)
# print(res.text)

# 测试重定向allow_redirects    如果为True就可以进行重定向;反之不可以
# res_bd=requests.get("http://www.baidu.com",allow_redirects=False)
# print(res_bd.text)

参考连接:(22条消息) 两万字博文教你python爬虫requests库【详解篇】_孤寒者的博客-CSDN博客_pythonrequests库https://gu-han-zhe.blog.csdn.net/article/details/118667559

下面看一下源码: 

def get(url, params=None, **kwargs):
    kwargs.setdefault('allow_redirects', True)
    return request('get', url, params=params, **kwargs) #返回一个request对象

# request对象,另外,method参数就是修改http方法
def request(method, url, **kwargs):
    with sessions.Session() as session:
        return session.request(method=method, url=url, **kwargs)
        
class Session(SessionRedirectMixin):
....
    # session的reqeust方法
    def request(self, method, url,
        params=None,
        data=None,
        headers=None,
        cookies=None,
        files=None,
        auth=None,
        timeout=None,
        allow_redirects=True,
        proxies=None,
        hooks=None,
        stream=None,
        verify=None,
        cert=None,
        json=None):
        # 构造一个Request对象.
        req = Request(
            method = method.upper(),
            url = url,
            headers = headers,
            files = files,
            data = data or {},
            json = json,
            params = params or {},
            auth = auth,
            cookies = cookies,
            hooks = hooks,
        )
        prep = self.prepare_request(req)

        proxies = proxies or {}

        settings = self.merge_environment_settings(
            prep.url, proxies, stream, verify, cert
        )

        # Send the request.
        send_kwargs = {
            'timeout': timeout,
            'allow_redirects': allow_redirects,
        }
        send_kwargs.update(settings)
        resp = self.send(prep, **send_kwargs)

        return resp

Requests中两个重要的对象

r=request.get(url,params=None,**kwargs)

params:url中的额外的参数,字典或字节流格式,可选
**kwargs: 12个控制访问的参数

列出几个重要的属性:

属性 说明
r.status_code HTTP请求返回状态码,200表示成功
r.text HTTP响应的字符串形式,即,url对应的页面内容
r.encoding 从HTTP header中猜测的响应内容的编码方式
r.apparent_encoding 从内容中分析响应内容的编码方式(备选编码方式)
r.content HTTP响应内容的二进制形式

理解Response编码
r.encoding:如果header中不存在charset,则认为编码是ISO-8859-1,r.text根据r.encoding显示网页内容
r.apparent_encoding:根据网页内容分析处的编码方式可以看做是r.encoding的备选

response = requests.get('http://www.jianshu.com/')
# 获取响应状态码
print(type(response.status_code),response.status_code)
# 获取响应头信息
print(type(response.headers),response.headers)
# 获取响应头中的cookies
print(type(response.cookies),response.cookies)
# 获取访问的url
print(type(response.url),response.url)
# 获取访问的历史记录
print(type(response.history),response.history)

 

你可能感兴趣的:(Python,python,爬虫,pycharm)