1.post請求
get請求與post請求的區別
從網上找到很好的解釋:
一.在我大萬維網世界中,TCP就像汽車,我們用TCP來運輸數據,它很可靠,從來不會發生丟件少件的現象。但是如果路上跑的全是看起來一模一樣的汽車,那這個世界看起來是一團混亂,送急件的汽車可能被前面滿載貨物的汽車攔堵在路上,整個交通系統一定會癱瘓。為了避免這種情況發生,交通規則HTTP誕生了。HTTP給汽車運輸設定了好幾個服務類別,有GET, POST, PUT, DELETE等等,HTTP規定,當執行GET請求的時候,要給汽車貼上GET的標簽(設置method為GET),而且要求把傳送的數據放在車頂上(url中)以方便記錄。如果是POST請求,就要在車上貼上POST的標簽,並把貨物放在車廂里。當然,你也可以在GET的時候往車廂內偷偷藏點貨物,但是這是很不光彩;也可以在POST的時候在車頂上也放一些數據,讓人覺得傻乎乎的。HTTP只是個行為准則,而TCP才是GET和POST怎么實現的基本。
二.在我大萬維網世界中,還有另一個重要的角色:運輸公司。不同的瀏覽器(發起http請求)和服務器(接受http請求)就是不同的運輸公司。 雖然理論上,你可以在車頂上無限的堆貨物(url中無限加參數)。但是運輸公司可不傻,裝貨和卸貨也是有很大成本的,他們會限制單次運輸量來控制風險,數據量太大對瀏覽器和服務器都是很大負擔。業界不成文的規定是,(大多數)瀏覽器通常都會限制url長度在2K個字節,而(大多數)服務器最多處理64K大小的url。超過的部分,恕不處理。如果你用GET服務,在request body偷偷藏了數據,不同服務器的處理方式也是不同的,有些服務器會幫你卸貨,讀出數據,有些服務器直接忽略,所以,雖然GET可以帶request body,也不能保證一定能被接收到哦。
GET和POST本質上就是TCP鏈接,並無差別。但是由於HTTP的規定和瀏覽器/服務器的限制,導致他們在應用過程中體現出一些不同。
三.GET和POST還有一個重大區別,簡單的說:
GET產生一個TCP數據包;POST產生兩個TCP數據包。
長的說:
對於GET方式的請求,瀏覽器會把http header和data一並發送出去,服務器響應200(返回數據);
而對於POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。
也就是說,GET只需要汽車跑一趟就把貨送到了,而POST得跑兩趟,第一趟,先去和服務器打個招呼“嗨,我等下要送一批貨來,你們打開門迎接我”,然后再回頭把貨送過去。
因為POST需要兩步,時間上消耗的要多一點,看起來GET比POST更有效。因此Yahoo團隊有推薦用GET替換POST來優化網站性能。但這是一個坑!跳入需謹慎。為什么?
1. GET與POST都有自己的語義,不能隨便混用。
2. 據研究,在網絡環境好的情況下,發一次包的時間和發兩次包的時間差別基本可以無視。而在網絡環境差的情況下,兩次包的TCP在驗證數據包完整性上,有非常大的優點。
3. 並不是所有瀏覽器都會在POST中發送兩次包,Firefox就只發送一次。
'''''' ''' post請求登陸github ''' import requests import re # 一 訪問login頁獲取token信息 ''' 請求url: https://github.com/login 請求方式: GET 響應頭: Set-Cookie 請求頭: Cookie User-Agent ''' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' } response = requests.get(url='https://github.com/login', headers=headers) # print(response.text) # 把login頁返回的cookies信息轉換成字典 login_cookies = response.cookies.get_dict() authenticity_token = re.findall('<input type="hidden" name="authenticity_token" value="(.*?)" />', response.text, re.S)[0] print(authenticity_token) # 二 往sessionurl發送POST請求 ''' 請求url: https://github.com/session 請求方式: POST 請求頭: # 上一次請求從哪里來 Referer: https://github.com/login Cookie:... User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36 請求體: 只有POST請求才會有請求體。 commit: Sign in utf8: ✓ authenticity_token: VX79esFc0YPdR1UFzUM/6MTRZOlYQ0btF5k2/x7uZea0x2E6W4bmRpwHsaCBN+096PaWNkcQjJOsyUzUqsAhIw== LLWlTr0qLcYC74hn7OI7IlyeB9rZei9737Lqtzz0sKTgY7Js7pUUhZ6bNC6lCkS+OHfVukkbTejjd0BnjPvGUg== login: tankjam1 password: ***** webauthn-support: unsupported ''' # 拼接請求頭信息 headers2 = { 'Referer': 'https://github.com/login', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36', } # 拼接請求體信息 form_data = { "commit": "Sign in", "utf8": "✓", "authenticity_token": authenticity_token, "login": "tankjam", "password": "kermit46709394", "webauthn-support": "unsupported", } # 往session地址發送post請求 # 攜帶請求頭、請求體、login頁的cookies信息 response2 = requests.post(url='https://github.com/session', data=form_data, headers=headers2, cookies=login_cookies) print(response2.status_code) # print(response2.text) with open('github.html', 'w', encoding='utf-8') as f: f.write(response2.text)
2.request的高級用法
import requests response=requests.get('https://www.baidu.com/') # reponse響應 # 獲取響應狀態碼 print(response.status_code) # 獲取url地址 print(response.url ) # 獲取文本 print(response.text) # 獲取二進制流 print(response.content) # 獲取頁面請求頭信息 print(response.headers) # 上一次跳轉的地址 print(response.history) # 返回cookie字典,返回cookies對象 # 獲取cookies信息 print(response.cookies) # 獲取cookies信息轉換成字典 print(response.cookies.get_dic()) # 獲取cookies信息轉換成字典 print(response.cookies.items()) # 字符編碼 print(response.encoding) response.encoding='utf-8' print(response.elapsed) # 生成器 # 往音頻地址發送get請求 import requests # https=http+ssl(攜帶安全認證證書) # ssl是全世界的安全認證中心 requests.get(url='https://xiaohuar.com',verify=True) # 方法一:True 代表攜帶證書 print() # 超時設置 import requests response=requests.get('https://www.baidu.com/',timeout=0.1) print(response.status_code) # 代理使用 # 偽代碼 import requests proxies={ # 帶用戶名密碼的代理,@符號前是用戶名與密碼 'http':'http://tank:123@localhost:9527', 'http':'http://localhost:9527', 'https':'https://localhost:9527', } response=requests.get('https://www.12306.cn', proxies=proxies) print(response.status_code) # 免費代理西刺代理 # http://ipip.net # 花生代理 # 加密方式與用戶體驗是掛鈎的 # 認證方式 # # 6.上傳文件 import requests # 上傳文本文件 files1 = {'file': open('user.txt', 'rb')} response = requests.post('http://httpbin.org/post', files=files1) print(response.status_code) # 200 print(response.text) # 200 # # 上傳圖片文件 files2 = {'jpg': open('35mm-aerial-aerial-shot-1105766.jpg', 'rb')} response = requests.post('http://httpbin.org/post', files=files2) print(response.status_code) # 200 print(response.text) # 200
3.selenium模塊
超級無敵好用,用來模擬人操作瀏覽器。
''' selenium模塊講解 一、什么是selenium 最初是一個自動化測試工具,selenium會模擬瀏覽器以及人的行為幫我們 給網站發送JS請求,跳過登錄方式 request不可以自動執行JS代碼 瀏覽器會幫我們的再次發送異步請求自動執行JS代碼 二、為什么要使用? 1.優點: 使用requests模塊登錄需要分析大量的復雜通信流程,使用selenium可以輕松跳過登錄驗證 2.缺點: 要驅動瀏覽器,瀏覽器會加載css,js,圖片。。數據等所有的代碼,會使得爬取效率低。 三、如何使用 1.首先需要下載selenium模塊,方法和下載requests模塊相同 在命令行中輸入:pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple selenium 2.下載驅動器 ''' #selenium第一次 # webdriver是用來驅動瀏覽器的 # from selenium.webdriver import ActionChains 調用得到一個動作鏈對象,破解滑動驗證碼的時候用的,可以拖動圖片 from selenium import webdriver # 用來驅動瀏覽器的 from selenium.webdriver import ActionChains # 破解滑動驗證碼的時候用的 可以拖動圖片 from selenium.webdriver.common.by import By # 按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys # 鍵盤按鍵操作 from selenium.webdriver.support import expected_conditions as EC # 和下面WebDriverWait一起用的 from selenium.webdriver.support.wait import WebDriverWait # 等待頁面加載某些元素 from selenium import webdriver import time # 通過谷歌瀏覽器驅動打開谷歌瀏覽器 # 絕對路徑有可能有.exe,有可能沒有 # 驅動瀏覽器的一種方式 chrome=webdriver.Chrome(r'D:\360安全瀏覽器下載\chromedriver_win32\chromedriver') # 驅動瀏覽器的另一種方式,將chromedriver.exe放入到python解釋器的scipt文件中,;之后還要進行環境變量的配置。 # 往博客園主頁發送get請求 try: # chrome.get('https://www.cnblogs.com/') # 訪問百度 # chrome是一個驅動對象,里面包含其他函數 # 參數1:驅動對象。參數2:等待 wait=WebDriverWait(chrome,10) chrome.get('https://www.baidu.com/') # 查找input輸入框 #!!!!!!注意!!!!!EC.presence_of_element_located((By.ID,"kw"))里面是寫的元組, #參數1.查找屬性的方式,參數2:屬性的名字 input_tag=wait.until(EC.presence_of_element_located((By.ID,"kw")))# kw是id的屬性 # 3.搜索一拳超人 input_tag.send_keys('一拳超人') # 4.按鍵盤回車鍵 input_tag.send_keys(Keys.EQUALS) time.sleep(20) # 無論發生什么異常都會關閉瀏覽器 finally: # 關閉瀏覽器 chrome.close()
4.selenium之基本選擇器
注意:所找屬性要是唯一的,一般來說首選id
from selenium import webdriver # 用來驅動瀏覽器的 import time # 獲取驅動對象 driver=webdriver.Chrome() try: # 顯示等待:等待某個元素加載 # 參數1:驅動對象,參數2:等待時間 # wait=WebDriverWait(chrome,10) driver.get('https://china.nba.com/') # 隱式等待:等待頁面所有元素加載完成 # 等待加載完成后,從加載好的標簽里查找,每次查找會等待10秒,如果找不到就下一個 driver.implicitly_wait(10) news_tag=driver.find_element_by_class_name('nav-news') print(news_tag) time.sleep(10) finally: driver.close() ''' ===============所有方法=================== element是查找一個標簽 elements是查找所有標簽 1、find_element_by_link_text 通過鏈接文本去找 2、find_element_by_id 通過id去找 3、find_element_by_class_name 4、find_element_by_partial_link_text 5、find_element_by_name 6、find_element_by_css_selector 7、find_element_by_tag_name ''' # 1.以文本作為標識 try: # 顯示等待:等待某個元素加載 # 參數1:驅動對象,參數2:等待時間 # wait=WebDriverWait(chrome,10) driver.get('https://baidu.com/') driver.implicitly_wait(10) send_tag=driver.find_element_by_link_text('登錄') send_tag.click() # 隱式等待:等待頁面所有元素加載完成 # 等待加載完成后,從加載好的標簽里查找,每次查找會等待10秒,如果找不到就下一個 finally: driver.close() # 2.通過局部文本查找標識 try: # 顯示等待:等待某個元素加載 # 參數1:驅動對象,參數2:等待時間 # wait=WebDriverWait(chrome,10) driver.get('https://baidu.com/') driver.implicitly_wait(10) login_button = driver.find_element_by_partial_link_text('登') login_button.click() # 隱式等待:等待頁面所有元素加載完成 # 等待加載完成后,從加載好的標簽里查找,每次查找會等待10秒,如果找不到就下一個 finally: driver.close() # 3.通過class來找 try: # 顯示等待:等待某個元素加載 # 參數1:驅動對象,參數2:等待時間 # wait=WebDriverWait(chrome,10) driver.get('https://baidu.com/') driver.implicitly_wait(10) login_tag1 = driver.find_element_by_class_name('tang-pass-footerBarULogin') login_button.click() time.sleep(1) # 隱式等待:等待頁面所有元素加載完成 # 等待加載完成后,從加載好的標簽里查找,每次查找會等待10秒,如果找不到就下一個 finally: driver.close() # 4.通過name屬性名查找 try: driver.get('https://baidu.com/') driver.implicitly_wait(10) username = driver.find_element_by_class_name('useName') username.send_keys('*******') time.sleep(1) finally: driver.close() # 5.通過id屬性查找 try: driver.get('https://baidu.com/') driver.implicitly_wait(10) username = driver.find_element_by_class_name('useName') username.send_keys('*******') time.sleep(1) finally: driver.close() # 6.通過屬性選擇器查找 try: driver.get('https://baidu.com/') driver.implicitly_wait(10) login_submit = driver.find_element_by_css_selector('#TANGRAM__PSP_10__submit') # driver.find_element_by_css_selector('.pass-button-submit') login_submit.click() time.sleep(1) finally: driver.close() # 7、find_element_by_tag_name 根據標簽名稱查找標簽 try: driver.get('https://baidu.com/') driver.implicitly_wait(10) div = driver.find_element_by_tag_name('div') print(div.tag_name) time.sleep(1) finally: driver.close()
5.京東實例
# 標簽中首選id # 目的就是查找唯一的屬性,來定位 from selenium import webdriver # 用來驅動瀏覽器的 from selenium.webdriver import ActionChains # 破解滑動驗證碼的時候用的 可以拖動圖片 from selenium.webdriver.common.by import By # 按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys # 鍵盤按鍵操作 from selenium.webdriver.support import expected_conditions as EC # 和下面WebDriverWait一起用的 from selenium.webdriver.support.wait import WebDriverWait # 等待頁面加載某些元素 from selenium import webdriver import time # 通過谷歌瀏覽器驅動打開谷歌瀏覽器 # 絕對路徑有可能有.exe,有可能沒有 # 驅動瀏覽器的一種方式 chrome=webdriver.Chrome(r'D:\360安全瀏覽器下載\chromedriver_win32\chromedriver') # 驅動瀏覽器的另一種方式,將chromedriver.exe放入到python解釋器的scipt文件中,;之后還要進行環境變量的配置。 # 往博客園主頁發送get請求 try: # chrome.get('https://www.cnblogs.com/') # 訪問百度 # chrome是一個驅動對象,里面包含其他函數 # 參數1:驅動對象。參數2:等待 wait=WebDriverWait(chrome,10) chrome.get('https://www.jd.com/') # 查找input輸入框 #!!!!!!注意!!!!!EC.presence_of_element_located((By.ID,"kw"))里面是寫的元組, #參數1.查找屬性的方式,參數2:屬性的名字 input_tag=wait.until(EC.presence_of_element_located((By.ID,"key")))# kw是id的屬性 # 3.搜索一拳超人 input_tag.send_keys('唐詩三百首') # 4.按鍵盤回車鍵 search_button=wait.until(EC.presence_of_element_located((By.CLASS_NAME,"button"))) search_button.click() time.sleep(20) # 無論發生什么異常都會關閉瀏覽器 finally: # 關閉瀏覽器 chrome.close()
