Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
equests庫的七個主要方法:
r=requests.get(url) :
構造一個向服務器請求資源的Request對象(Request),并且get方法返回一個包含服務器資源的Response對象;
requests.get函數的完整參數如下:
requests.get(url, params=None, **kwargs)
url: 擬獲取頁面的url鏈接
params: url中額外參數,字典或字節流格式,可選
**kwargs: 12個控 訪問的參數
Requests庫的2個重要的對象 Request 和 Response對象(Response對象包含爬蟲返回的所有內容)
>>> import requests #導入requests庫
>>> r=requests.get("http://www.baidu.com")
>>> print(r.status_code) #檢測請求的狀態碼,200表示請求成功
200
>>> type(r)
<class 'requests.models.Response'>
>>> r.headers
Response對象的屬性:
Response對象的處理流程如下圖示:
理解Response的編碼:
r.encoding:如果header中不存在charset,則認為編碼為'ISO-8859-1'
r.apparent_encoding: 根據網頁內容分析出的編碼方式
需求:獲取京東頁面數據
import requests
resp=requests.get('http:www.jd.com/')
print(resp)
requests模塊如何處理攜帶參數的get請求,返回攜帶參數的請求:
需求:指定一個詞條,獲取搜狗搜索結果所對應的頁面數據
之前urllib模塊處理url上參數有中文的需要處理編碼,requests會自動處理url編碼
發起帶參數的get請求
params可以是傳字典或者列表
def get(url, params=None, **kwargs):
r"""Sends a GET request.
:param url: URL for the new :class:`Request` object.
:param params: (optional) Dictionary, list of tuples or bytes to send
in the body of the :class:`Request`.
:param \*\*kwargs: Optional arguments that ``request`` takes.
:return: :class:`Response <Response>` object
:rtype: requests.Response
import requests
# 指定url
url='https://www.sogou.com/web'
# 封裝get請求參數
prams={
'query':'周杰倫',
'ie':'utf-8'
}
response=requests.get(url=url,params=prams)
page_text=response.text
with open("周杰倫.html","w",encoding="utf-8") as f:
f.write(page_text)
f.close()
print("ok")
利用requests模塊自定義請求頭信息,并且發起帶參數的get請求
get方法有個headers參數 把請求頭信息的字典賦給headers參數
本文的內容源自其他博客的總結,結構如下:
HTTP 的請求報文
GET 方法的特點
POST 方法的特點
GET 和 POST 的區別
首先我們要解決的第一個問題是:GET 和 POST 是什么?
GET 和 POST 其實都是 HTTP 的請求方法。除了這 2 個請求方法之外,HTTP 還有 HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS 這 6 個請求方法。所以HTTP 的請求方法共計有 8 種,它們的描述如下所示:
接下來我們解決第二個問題:請求方法如何使用?
要解決這個問題,我們首先需要了解 HTTP 的請求報文結構:
?可以看到 HTTP 的請求報文由三部分構成:
我們通過一個實際的例子來看看 HTTP 的 GET 請求報文是什么樣的,我們這里以訪問 https://api.github.com/search/users?q=JakeWharton 為例,通過抓包我們得到的請求報文如下所示:
GET /search/users?q=JakeWharton HTTP/1.1
Host: api.github.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _octo=GH1.1.1623908978.1549006668; _ga=GA1.2.548087391.1549006688; logged_in=yes; dotcom_user=GoMarck; _gid=GA1.2.17634150.1554639136; _gat=1
我們重點看到請求行:
GET /search/users?q=JakeWharton HTTP/1.1
可以看到請求方法用的是 GET 請求,URL為 /search/users?q=JakeWharton,協議為 HTTP1.1。
請求行下面部分全都是請求頭部,我們可以看到 host 為 api.github.com,連接方式為長連接等信息。值得注意的是我們這個例子中是不存在請求數據的。
接下來我們在來看一下 POST 請求的報文(該例子源自其他博客):
POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
可以看到請求行中請求方法為 POST,URL 為空,協議版本也是 HTTP1.1。它和上面 GET 方法例子不一樣的地方在于它的請求參數是位于請求數據中的,可以看到 name=Professional%20Ajax&publisher=Wiley 就是它的請求數據。并且我們要注意到在請求數據和請求頭之間是空出一行的,這是必不可少的。
1、前面的例子:https://api.github.com/search/users?q=JakeWharton 就是一個非常典型的 GET 請求的表現形式,即請求的數據會附在 URL 之后(放在請求行中),以 ? 分割 URL 和傳輸數據,多個參數用 & 連接。
2、除此之外,根據 HTTP 規范,GET 用于信息獲取,而且應該是安全和冪等的 。
安全性指的是非修改信息,即該操作用于獲取信息而非修改信息。換句話說,GET請求一般不應產生副作用,也就是說,它僅僅是獲取資源信息,就像數據庫查詢一樣,不會修改,增加數據,不會影響資源的狀態。
冪等性 (Idempotence) 則指的是無論調用這個URL 多少次,都不會有不同的結果的 HTTP 方法。而在實際過程中,這個規定沒有那么嚴格。例如在一個新聞應用中,新聞站點的頭版不斷更新,雖然第二次請求會返回不同的一批新聞,該操作仍然被認為是安全的和冪等的,因為它總是返回當前的新聞。
3、GET 是會被瀏覽器主動緩存的,如果下一次傳輸的數據相同,那么就會返回緩存中的內容,以求更快地展示數據。
4、GET 方法的 URL 一般都具有長度限制,但是需要注意的是 HTTP 協議中并未規定 GET 請求的長度。這個長度限制主要是由瀏覽器和 Web 服務器所決定的,并且各個瀏覽器對長度的限制也各不相同。
5、GET 方法只產生一個 TCP 數據包,瀏覽器會把請求頭和請求數據一并發送出去,服務器響應 200 ok(返回數據)。
相關視頻推薦
c++后臺開發,如何讓你的http web服務器做的與眾不同
從50道騰訊面試題,分析騰訊c++后端工程的技能樹
學習地址:C/C++Linux服務器開發/后臺架構師【零聲教育】-學習視頻教程-騰訊課堂
需要C/C++ Linux服務器架構師學習資料加群812855908獲取(資料包括C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg等),免費分享
上面說了那么多 GET 方法和 POST 方法各自的特點,它們在外在的表現上似乎是有著諸多的不同,但是實際上,它們的本質是一樣的,并無區別!!!
這似乎有些不可思議,但是我們重新回想一下 GET 和 POST 是什么?它們是 HTTP 請求協議的請求方法,而 HTTP 又是基于TCP/IP的關于數據如何在萬維網中如何通信的協議,所以 GET/POST 實際上都是 TCP 鏈接。
也就是說,GET 和 POST 所做的事其實是一樣的,如果你給 GET 加上請求數據,給 POST 加上 URL 參數,這在技術上是完全可行的,事實上確實有一些人為了貪圖方便在更新資源時用了GET,因為用POST必須要到FORM(表單),這樣會麻煩一點(但是強烈不建議這樣子做!!!)。
既然 GET 和 POST 的底層都是 TCP,那么為什么 HTTP 還要特別將它們區分出來呢?
其實可以想象一下,如果我們直接使用 TCP 進行數據的傳輸,那么無論是單純獲取資源的請求還是修改服務器資源的請求在外觀上看起來都是 TCP 鏈接,這樣就非常不利于進行管理。所以在 HTTP 協議中,就會對這些不同的請求設置不同的類別進行管理,例如單純獲取資源的請求就規定為 GET、修改服務器資源的請求就規定為 POST,并且也對它們的請求報文的格式做出了相應的要求(例如請求參數 GET 位于 URL 而 POST 則位于請求數據中)。
當然,如果我們想將 GET 的請求參數放置在請求數據中或者將 POST 的請求數據放置在 URL 中,這是完全可以的,雖然這樣子做并不符合 HTTP 的規范。但是這樣子做是否能得到我們期望的響應數據呢?答案是未必,這取決于服務器的行為。
以 GET 方法在請求數據中放置請求參數為例,有些服務器會將請求數據中的參數讀出,在這種情況下我們依然能獲得我們期望的響應數據;而有些服務器則會選擇直接忽略,這種情況下我們就無法獲取期望的響應數據了。
所以,對于 GET 和 POST 的區別,總結來說就是:它們的本質都是 TCP 鏈接,并無區別。但是由于 HTTP 的規定以及瀏覽器/服務器的限制,導致它們在應用過程中可能會有所不同。
首先說一下為什么寫這篇文章,以前寫客戶端的時候,要經常調用后端的接口,一般很多公司的接口,都是統一POST提交方式
服務端響應的是 JSON 格式字符串,方便統一管理,當時對POST不太清楚,開始的時候,不覺得有啥
但是真正等到自己寫一個獨立的技術社區的時候,也就是 www.helloworld.net ,需要上傳,需要表單提交等
才發現,不懂這些,用到了的時候,很是費勁,很耽誤時間。
下面就當是復習了,學習一下GET , POST 這兩種最常用的提交方式
HTTP 請求方法有9種,分別是
序號 | 方法 | 描述 |
1 | GET | 請求指定的頁面信息,并返回實體主體。 |
2 | HEAD | 類似于 GET 請求,只不過返回的響應中沒有具體的內容,用于獲取報頭 |
3 | POST | 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST 請求可能會導致新的資源的建立和/或已有資源的修改。 |
4 | PUT | 從客戶端向服務器傳送的數據取代指定的文檔的內容。 |
5 | DELETE | 請求服務器刪除指定的頁面。 |
6 | CONNECT | HTTP/1.1 協議中預留給能夠將連接改為管道方式的代理服務器。 |
7 | OPTIONS | 允許客戶端查看服務器的性能。 |
8 | TRACE | 回顯服務器收到的請求,主要用于測試或診斷。 |
9 | PATCH | 是對 PUT 方法的補充,用來對已知資源進行局部更新 。 |
最常用的還是 GET , POST
我們知道,http是一個通信協議,啥叫通信協議,通信嘛,就是兩個人要溝通,協議嘛,就是怎么溝通
比如我說A,你知道我餓了想吃東西了,我再說 A 米飯, 你就知道我餓了,并且想吃米飯了。
對的,協議就是雙方提前商量好的溝通的內容的格式
HTTP通信協議就是 HTTP客戶端和HTTP服務端 雙方規定好的格式
那么這個HTTP消息,有哪幾部分組成呢
很簡單,HTTP消息包含兩部分
比如我們在瀏覽器中發一個請求www.helloworld.net 回車,此時我們發的是GET請求
那么請求頭是:
GET / HTTP/2
Host: www.helloworld.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: Hm_lvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406379; Hm_lpvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406379
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
If-None-Match: "d696-1nnZwKI6/LZalqvEzQx9IFil/tw"
TE: trailers
注意: HTTP 的GET請求,是沒有請求體的,這也就是為什么有些公司統一封裝請求為POST,而不是GET的原因了
因為POST是有請求體的,可以帶大量的數據,GET因為沒有請求體,攜帶參數只能放在URL中,能帶的數據量是比較少的。
GET 訪求方法最常用,也是最簡單的一種,像其語義一樣,GET 就是獲取文件的意思
所以GET請求就是獲取服務器上的某個資源 ,使用也很簡單,我們記住下面兩點就行了
服務器收到請求就可以解析出來url后面帶的參數了,name=tom , age=23
下面我們重點看一下POST請求
POST 是提交的意思,如果我們需要向服務器提交一些數據,就可以使用POST方法
雖然POST是提交的意思,協議規定的也是用POST提交數據,但是現在很多公司并沒有這樣搞
查詢也會用POST,其實它只是個單詞,服務端收到 請求后,是查詢資源,還是刪除資源,還是提交
都可以的,只是看你們公司前后端怎么規定即可。
下面我們看看POST有哪幾種提交數據的方式
這也是POST默認的一種方式 ,對應的請求頭中的 Content-Type 為 application/x-www-form-urlencoded
我們從瀏覽器中抓取www.helloworld.net 上的幾個請求方式,為例,如下
## 請求頭
POST /v1/special/getSpecialCateList HTTP/2
Host: tiger-api.helloworld.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Authorization:
token:
ts: 1668407094
sign: d41d8cd98f00b204e9800998ecf8427e
deviceType: pc
Origin: https://www.helloworld.net
Connection: keep-alive
Referer: https://www.helloworld.net/
Cookie: Hm_lvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406379; Hm_lpvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406398
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Content-Length: 0
## 請求體
action=10&pageNum=1&pageSize=10&uuid=15139897
此種方式,一般是提交key, value 的值。
我之前把這種當作了上面的那種,后來寫文件上傳的時候,查了一下,原來 不是
這種提交方法一般是上傳文件用的多。通常是用在客戶端向服務端傳送大文件數據,如:圖片或者文件。
首先來解釋下什么它的編碼方式,首先會生成一個很長的 boundary 字符串分界線,表明下面的都是表單內容,然后緊接著跟的是表單中的第一個鍵值對中的名稱,而后一個換行,跟著值。然后再生成一個boundary 字符串分界線,用于分割不同的鍵值。之后就重復以上操作,詳細的流程請看下方的例子。
同樣我們以 www.helloworld.net 舉例,我們從里面找個接口,抓取一下,看看
# 請求頭
POST http://www.helloworld.net/xyz HTTP/1.1
Host: www.helloworld.net
User-Agent: python-requests/2.24.0
Accept-Encoding: gzip, deflate
Accept: */*
Content-Type: multipart/form-data; boundary=e42346452as650adf2345fadade
Content-Length: 222
Connection: keep-alive
# 請求體
--e42346452as650adf2345fadade
Content-Disposition: form-data; name="field0"
value1
--e42346452as650adf2345fadade
Content-Disposition: form-data; name="field1"
value2
--e42346452as650adf2345fadade--
Content-Disposition: form-data; name="field2"; filename="filename"
Content-Type: text/plain
--e42346452as650adf2345fadade--
從上面我們可以知道,在請求頭中的 Content-Type中,有一個 boundary=e42346452as650adf2345fadade
這個boundary后面的字符串都是隨機生成的。用于請求體中數據的分段的。
其實就是個分隔符的作用。
這種就是我們現在用的最多的了,而且也非常方便
在請求頭中設置 content-type=application/json,就表明請求體中的內容格式為json格式
同樣的,服務端在響應的時候,順應頭中也會添加一個 content-type=application/json
同樣的也是告訴客戶端,我響應給你的響應體中的內容,格式同樣為 json 格式
同的樣我們也參照 www.helloworld.net 中的一個請求,如下
## 請求頭
POST /v1/special/getSpecialList HTTP/2
Host: tiger-api.helloworld.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/json
Authorization:
token:
ts: 1668408188
sign: 08fab32346193fa92037b5ca5f9ed592
deviceType: pc
Content-Length: 30
Origin: https://www.helloworld.net
Connection: keep-alive
Referer: https://www.helloworld.net/
Cookie: Hm_lvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668406379,1668408042,1668408051; Hm_lpvt_c7e77fd22dddf4a169b8d6f4807c5a4c=1668408051
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
TE: trailers
## 請求體
action=10&pageNum=1&sortType=0
我們看一下響應體:
{
"code": 1,
"data": {
"hasMore": false,
"list": [
{
"uuid": "5441523000",
"title": "區塊鏈原理和應用",
"totalCount": 0,
"chapterCount": 1,
"readCount": 0,
"subscribeCount": 1,
"createTime": "0001-01-01T00:00:00Z",
"status": 0,
"profile": "1037883613",
"nicker": "小天",
"avatar": "https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/d04d513fbea19f6cb7c3b4beee3c7f5e.jfif",
"subscribed": false
},
{
"uuid": "bbatgp",
"title": "C語言編程(初級)",
"totalCount": 0,
"chapterCount": 19,
"readCount": 2938,
"subscribeCount": 1,
"createTime": "0001-01-01T00:00:00Z",
"status": 0,
"profile": "80662724",
"nicker": "Suzhou",
"avatar": "https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/d04d513fbea19f6cb7c3b4beee3c7f5e.jfif",
"subscribed": false
}
]
},
"message": "獲取數據成功",
"errMessage": ""
}
這個一直沒有遇到過,很少用
其實就是請求消息中,請求體中的內容格式是純文本xml格式
此種我們就不作介紹
有興趣的可以下面自己查資料
綜上所述,HTTP 的POST四種方法以及GET的簡單介紹,我們總結如下:
1. `application/x-www-form-urlencoded` , 也是默認的方式,主要提交的數據是key, value 形式的
2. `multipart/form-data` ,此種方式 是客戶端向服務端提交大數據用的,一般上傳文件等用到。
? 注意這種方式,會在請求頭中生成一個boundary字段,其對應的值是一個隨機生成的字符串,用于分隔請求體中的數據用的
簡單的介紹了一下HTTP的GET,POST的一些知識,希望對你們有用。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。