爬蟲-requests模塊介紹

一 : requests模塊的請求方法
各種請求方式:常用的就是requests.get()和requests.post()

r = requests.get(‘https://api.github.com/events’)
r = requests.post(‘http://httpbin.org/post’, data = {‘key’:‘value’})
r = requests.put(‘http://httpbin.org/put’, data = {‘key’:‘value’})
r = requests.delete(‘http://httpbin.org/delete’)
r = requests.head(‘http://httpbin.org/get’)
r = requests.options(‘http://httpbin.org/get’)

requests.get('url')
requests.post(url='url',data={'xxx':'yyy'})

二: 關於requests中的GET請求相關
1 . requests 的基本請求

import requests
response=requests.get('url')
print(response.text)
  1. 帶參數的GET請求->params
#方法一:在請求頭內將自己僞裝成瀏覽器,否則百度不會正常返回頁面內容, 所以在請求頭中要添加headers
import requests
response=requests.get('https://www.baidu.com/s?wd=python&pn=1',
                      headers={
                        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36',
                      })
print(response.text)


#如果查詢關鍵詞是中文或者有其他特殊符號,則不得不進行url編碼
from urllib.parse import urlencode
wd='美女洗浴' #參數中帶有中文,需要將中文編碼
encode_res=urlencode({'k':wd},encoding='utf-8')
keyword=encode_res.split('=')[1]
# print(keyword)

# 然後拼接成url
url='https://www.baidu.com/s?wd=%s&pn=1' %keyword

response=requests.get(url,
                      headers={
                        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36',
                      })
res1=response.text



#方法二:上述操作可以用requests模塊的一個params參數搞定,本質還是調用urlencode,params中直接將參數以鍵值對的方式放入其中。
from urllib.parse import urlencode
wd='美女洗浴'
pn=1

response=requests.get('https://www.baidu.com/s',
                      params={
                          'wd':wd,
                          'pn':pn
                      },
                      headers={
                        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36',
                      })
res2=response.text

3、帶參數的GET請求->headers

	#通常我們在發送請求時都需要帶上請求頭,請求頭是將自身僞裝成瀏覽器的關鍵,常見的有用的請求頭如下
	Host
	Referer #大型網站通常都會根據該參數判斷請求的來源
	User-Agent #客戶端
	Cookie #Cookie信息雖然包含在請求頭裏,但requests模塊有單獨的參數來處理他,headers={}內就不要放它了
#添加headers(瀏覽器會識別請求頭,不加可能會被拒絕訪問,比如訪問https://www.zhihu.com/explore)
import requests
response=requests.get('https://www.zhihu.com/explore')
response.status_code #500


#自己定製headers
headers={
    'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36',

}
respone=requests.get('https://www.zhihu.com/explore',
                     headers=headers)
print(respone.status_code) #200

4、帶參數的GET請求->cookies
#登錄github,然後從瀏覽器中獲取cookies,以後就可以直接拿着cookie登錄了,無需輸入用戶名密碼
#用戶名:XXX 郵箱[email protected] 密碼XXX

import requests
Cookies={   'user_session':'wGMHFJKgDcmRIVvcA14_Wrt_3xaUyJNsBnPbYzEL6L0bHcfc',
}

response=requests.get('https://github.com/settings/emails',
             cookies=Cookies) #github對請求頭沒有什麼限制,我們無需定製user-agent,對於其他網站可能還需要定製,這個cookies裏面就已經包含了賬號密碼郵箱等內容
print('[email protected]' in response.text) #True

三: 關於requests中的POST請求相關

  1. post請求與get請求區別
#GET請求
HTTP默認的請求方法就是GET
     * 沒有請求體
     * 數據必須在1K之內!
     * GET請求數據會暴露在瀏覽器的地址欄中
GET請求常用的操作:
       1. 在瀏覽器的地址欄中直接給出URL,那麼就一定是GET請求
       2. 點擊頁面上的超鏈接也一定是GET請求
       3. 提交表單時,表單默認使用GET請求,但可以設置爲POST
#POST請求
(1). 數據不會出現在地址欄中
(2). 數據的大小沒有上限
(3). 有請求體
(4). 請求體中如果存在中文,會使用URL編碼!
#!!!requests.post()用法與requests.get()完全一致,特殊的是requests.post()有一個data參數,用來存放請求體數據
#對於登錄來說,應該輸錯用戶名或密碼然後分析抓包流程,用腦子想一想,輸對了瀏覽器就跳轉了,還分析個毛線,累死你也找不到包

2、發送post請求,模擬瀏覽器的登錄行爲

'''
一 目標站點分析
    瀏覽器輸入https://github.com/login
    然後輸入錯誤的賬號密碼,抓包
    發現登錄行爲是post提交到:https://github.com/session
    而且請求頭包含cookie
    而且請求體包含:
        commit:Sign in
        utf8:✓
        authenticity_token:lbI8IJCwGslZS8qJPnof5e7ZkCoSoMn6jmDTsL1r/m06NLyIbw7vCrpwrFAPzHMep3Tmf/TSJVoXWrvDZaVwxQ==
        login:egonlin
        password:123


二 流程分析
    先GET:https://github.com/login拿到初始cookie與authenticity_token
    返回POST:https://github.com/session, 帶上初始cookie,帶上請求體(authenticity_token,用戶名,密碼等)
    最後拿到登錄cookie

    ps:如果密碼時密文形式,則可以先輸錯賬號,輸對密碼,然後到瀏覽器中拿到加密後的密碼,github的密碼是明文
'''

import requests
import re

#第一次請求
r1=requests.get('https://github.com/login')
r1_cookie=r1.cookies.get_dict() #拿到初始cookie(未被授權)
authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #從頁面中拿到CSRF TOKEN

#第二次請求:帶着初始cookie和TOKEN發送POST請求給登錄頁面,帶上賬號密碼
data={
    'commit':'Sign in',
    'utf8':'✓',
    'authenticity_token':authenticity_token,
    'login':'[email protected]',
    'password':'alex3714'
}
r2=requests.post('https://github.com/session',
             data=data,
             cookies=r1_cookie
             )


login_cookie=r2.cookies.get_dict()


#第三次請求:以後的登錄,拿着login_cookie就可以,比如訪問一些個人配置
r3=requests.get('https://github.com/settings/emails',
                cookies=login_cookie)

print('[email protected]' in r3.text) #True

3、補充

requests.post(url='xxxxxxxx',
              data={'xxx':'yyy'}) #沒有指定請求頭,#默認的請求頭:application/x-www-form-urlencoed

#如果我們自定義請求頭是application/json,並且用data傳值, 則服務端取不到值
requests.post(url='',
              data={'':1,},
              headers={
                  'content-type':'application/json'
              })


requests.post(url='',
              json={'':1,},
              ) #默認的請求頭:application/json

四 響應Response
1、response屬性

import requests
respone=requests.get('http://www.jianshu.com')
# respone屬性
print(respone.text)
print(respone.content)

print(respone.status_code)
print(respone.headers)
print(respone.cookies)
print(respone.cookies.get_dict())
print(respone.cookies.items())

print(respone.url)
print(respone.history)

print(respone.encoding)

#關閉:response.close()
from contextlib import closing
with closing(requests.get('xxx',stream=True)) as response:
    for line in response.iter_content():
    pass

2、編碼問題

#編碼問題
import requests
response=requests.get('http://www.autohome.com/news')
# response.encoding='gbk' #汽車之家網站返回的頁面內容爲gb2312編碼的,而requests的默認編碼爲ISO-8859-1,如果不設置成gbk則中文亂碼
print(response.text)

3、獲取二進制數據

import requests

response=requests.get('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1509868306530&di=712e4ef3ab258b36e9f4b48e85a81c9d&imgtype=0&src=http%3A%2F%2Fc.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F11385343fbf2b211e1fb58a1c08065380dd78e0c.jpg')

with open('a.jpg','wb') as f:
    f.write(response.content)
#stream參數:一點一點的取,比如下載視頻時,如果視頻100G,用response.content然後一下子寫到文件中是不合理的

import requests
response=requests.get('https://gss3.baidu.com/6LZ0ej3k1Qd3ote6lo7D0j9wehsv/tieba-smallvideo-transcode/1767502_56ec685f9c7ec542eeaf6eac93a65dc7_6fe25cd1347c_3.mp4',
                      stream=True)
with open('b.mp4','wb') as f:
    for line in response.iter_content():
        f.write(line)

4、解析json:通過response.json() 方法直接獲取json格式的數據,還不用導入json

#解析json
import requests
response=requests.get('http://httpbin.org/get')
import json
res1=json.loads(response.text) #太麻煩
res2=response.json() #直接獲取json數據
print(res1 == res2) #True

5、Redirection and History

import requests
import re
#第一次請求
r1=requests.get('https://github.com/login')
r1_cookie=r1.cookies.get_dict() #拿到初始cookie(未被授權)
authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #從頁面中拿到CSRF TOKEN
#第二次請求:帶着初始cookie和TOKEN發送POST請求給登錄頁面,帶上賬號密碼
data={
    'commit':'Sign in',
    'utf8':'✓',
    'authenticity_token':authenticity_token,
    'login':'[email protected]',
    'password':'alex3714'
}
#測試一:沒有指定allow_redirects=False,則響應頭中出現Location就跳轉到新頁面,r2代表新頁面的response
r2=requests.post('https://github.com/session',
             data=data,
             cookies=r1_cookie
             )
print(r2.status_code) #200
print(r2.url) #看到的是跳轉後的頁面
print(r2.history) #看到的是跳轉前的response
print(r2.history[0].text) #看到的是跳轉前的response.text

#測試二:指定allow_redirects=False,則響應頭中即便出現Location也不會跳轉到新頁面,r2代表的仍然是老頁面的response
r2=requests.post('https://github.com/session',
             data=data,
             cookies=r1_cookie,
             allow_redirects=False
             )
print(r2.status_code) #302
print(r2.url) #看到的是跳轉前的頁面https://github.com/session
print(r2.history) #[]

五 高級用法
1、SSL Cert Verification

#證書驗證(大部分網站都是https)
import requests
respone=requests.get('https://www.12306.cn') #如果是ssl請求,首先檢查證書是否合法,不合法則報錯,程序終端


#改進1:去掉報錯,但是會報警告
import requests
respone=requests.get('https://www.12306.cn',verify=False) #不驗證證書,報警告,返回200
print(respone.status_code)


#改進2:去掉報錯,並且去掉警報信息
import requests
from requests.packages import urllib3
urllib3.disable_warnings() #關閉警告
respone=requests.get('https://www.12306.cn',verify=False)
print(respone.status_code)

#改進3:加上證書
#很多網站都是https,但是不用證書也可以訪問,大多數情況都是可以攜帶也可以不攜帶證書
#知乎\百度等都是可帶可不帶
#有硬性要求的,則必須帶,比如對於定向的用戶,拿到證書後纔有權限訪問某個特定網站
import requests
respone=requests.get('https://www.12306.cn',
                     cert=('/path/server.crt',
                           '/path/key'))
print(respone.status_code)

2、使用代理

#官網鏈接: http://docs.python-requests.org/en/master/user/advanced/#proxies

#代理設置:先發送請求給代理,然後由代理幫忙發送(封ip是常見的事情)
import requests
proxies={
    'http':'http://egon:123@localhost:9743',#帶用戶名密碼的代理,@符號前是用戶名與密碼
    'http':'http://localhost:9743',
    'https':'https://localhost:9743',
}
respone=requests.get('https://www.12306.cn',
                     proxies=proxies)

print(respone.status_code)



#支持socks代理,安裝:pip install requests[socks]
import requests
proxies = {
    'http': 'socks5://user:pass@host:port',
    'https': 'socks5://user:pass@host:port'
}
respone=requests.get('https://www.12306.cn',
                     proxies=proxies)

print(respone.status_code)

3、超時設置

#超時設置
#兩種超時:float or tuple
#timeout=0.1 #代表接收數據的超時時間
#timeout=(0.1,0.2)#0.1代表鏈接超時  0.2代表接收數據的超時時間

import requests
respone=requests.get('https://www.baidu.com',
                     timeout=0.0001)

4、 認證設置

#官網鏈接:http://docs.python-requests.org/en/master/user/authentication/

#認證設置:登陸網站是,彈出一個框,要求你輸入用戶名密碼(與alter很類似),此時是無法獲取html的
# 但本質原理是拼接成請求頭髮送
#         r.headers['Authorization'] = _basic_auth_str(self.username, self.password)
# 一般的網站都不用默認的加密方式,都是自己寫
# 那麼我們就需要按照網站的加密方式,自己寫一個類似於_basic_auth_str的方法
# 得到加密字符串後添加到請求頭
#         r.headers['Authorization'] =func('.....')

#看一看默認的加密方式吧,通常網站都不會用默認的加密設置
import requests
from requests.auth import HTTPBasicAuth
r=requests.get('xxx',auth=HTTPBasicAuth('user','password'))
print(r.status_code)

#HTTPBasicAuth可以簡寫爲如下格式
import requests
r=requests.get('xxx',auth=('user','password'))
print(r.status_code)

5、異常處理

#異常處理
import requests
from requests.exceptions import * #可以查看requests.exceptions獲取異常類型

try:
    r=requests.get('http://www.baidu.com',timeout=0.00001)
except ReadTimeout:
    print('===:')
# except ConnectionError: #網絡不通
#     print('-----')
# except Timeout:
#     print('aaaaa')

except RequestException:
    print('Error')

6、上傳文件

import requests
files={'file':open('a.jpg','rb')}
respone=requests.post('http://httpbin.org/post',files=files)
print(respone.status_code)

原文地址:https://www.cnblogs.com/linhaifeng/articles/7785043.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章