python3 requests 动态网页post提交数据_Python爬虫三:动态网页爬虫
1. 利用API爬取數據
有時,使用BeautifulSoup解析和提取數據后,輸出結果為空。這是由于網頁使用了另一種加載數據的方式——通過API加載數據。API(Application Programming Interface)即應用程序編程接口,也就是網頁和服務器交互的途徑。
1) Network
開發者工具中的Network記錄的是從打開工具到網頁加載完畢之間的所有請求。其中,以All開頭的一行是請求類型過濾器,可以展示對應類型的請求。爬蟲中常用的有All、XHR、Img和Media。
2) XHR
XHR全稱XMLHttpRequest,是瀏覽器內置的對象,使得JavaScript可以發送HTTP請求。
爬取需要的數據時,首先要在XHR的Name欄中找到數據所在的位置(可通過請求名稱和數據大小判斷),找到目標后點擊這條請求,在Preview中查看數據,即可確認。數據有很多,需要按名稱逐層展開。
接下來,點擊Headers里的General就可以看到API的鏈接(即Request URL),這就是獲取數據的真正鏈接。但這個鏈接一般又長又亂,這時可以用requests.get()方法的params參數,以字典的形式傳遞鏈接的查詢字符串參數,使代碼看上去更加簡潔明了。利用Convert HTTP Query String to JSON網站,將網址問號后的參數粘貼到input框中,即可得到轉換后的字典形式的參數。
例如,爬取QQ音樂《等你下課》的評論,可以將代碼寫為:
import requests
headers = {
'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
params = {
'g_tk': '5381',
'loginUin': '0',
'hostUin': '0',
'format': 'json',
'inCharset': 'utf8',
'outCharset': 'GB2312',
'notice': '0',
'platform': 'yqq.json',
'needNewCode': '0',
'cid': '205360772',
'reqtype': '2',
'biztype': '1',
'topid': '212877900',
'cmd': '8',
'needmusiccrit': '0',
'pagenum': '0',
'pagesize': '25',
'lasthotcommentid': '',
'domain': 'qq.com',
'ct': '24',
'cv': '10101010'
}
res = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', headers=headers, params=params)
print(res.text)
用res.text獲取到的數據是字符串形式的,而如果是字典或列表的話,會更容易從中提取評論數據。可以用JSON將其轉換為字典或列表。
3) JSON
JSON(JavaScript Object Notation)是編程語言之間通用的數據格式。它的本質是一個字符串,建構于兩種結構:鍵值對的集合和值的有序列表,分別對應Python里的字典和列表。它是一種標準,規定了基本數據結構的寫法,不同的編程語言拿到后可以解析成自己對應的數據結構。
4) 解析JSON
對于JSON格式的內容,調用json()方法即可對響應內容解碼。例如,獲取最新的第一條評論內容,可以在上面的代碼后續寫:
data = res.json()
print(data['comment']['commentlist'][0]['rootcommentcontent'])
5) 獲取多頁數據
通過對比不同頁碼的鏈接參數可以得出其變化規律。
查看第二頁評論的請求,可以發現只有pagenum和lasthotcommentid兩個參數發生了變化,pagenum從0變成了1,而lasthotcommentid則是上頁最后一條評論的commentid。因此,通過修改參數pagenum和lasthotcommentid的值即可獲取多頁的評論數據。
例如,獲取《等你下課》前五頁的評論,完整的代碼可以寫為:
import requests
import time
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
lasthotcommentid = ''
for pagenum in range(5):
params = {
'g_tk': '5381',
'loginUin': '0',
'hostUin': '0',
'format': 'json',
'inCharset': 'utf8',
'outCharset': 'GB2312',
'notice': '0',
'platform': 'yqq.json',
'needNewCode': '0',
'cid': '205360772',
'reqtype': '2',
'biztype': '1',
'topid': '212877900',
'cmd': '8',
'needmusiccrit': '0',
'pagenum': pagenum,
'pagesize': '25',
'lasthotcommentid': lasthotcommentid,
'domain': 'qq.com',
'ct': '24',
'cv': '10101010'
}
res = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', headers=headers, params=params)
data = res.json()
for item in data['comment']['commentlist']:
print('{}:{}'.format(item['nick'], item['rootcommentcontent']))
lasthotcommentid = data['comment']['commentlist'][-1]['commentid']
time.sleep(1)
總之,根據網站是靜態的還是動態的,爬蟲的策略有所不同。靜態網頁使用BeautifulSoup解析網頁源代碼,動態網頁直接找到加載數據的API,從API中爬取數據。
2. cookie
1) 登錄賬號
在開發者工具中,點擊Network,清空請求記錄后勾選Preserve log,接下來在網頁中輸入賬號密碼登錄,即可看到login或signin之類的請求。在這一條請求中,請求方式(Request Method)顯示為POST。
2) POST請求
與GET一樣,POST也是請求方式的一種。GET用于獲取數據,其參數顯示在請求地址里;POST用于提交數據,其參數隱藏在Form Data里。可以通過requests.post()來發送POST請求,其參數通過字典的形式傳遞給data參數。因此,登錄賬號的操作可以寫為:
import requests
headers = {
'user-agent': '……'
}
data = {
'…': '…',
'…': '…'
}
requests.post('登錄頁面網址', data = data, headers = headers)
在發出POST請求后,服務器會在Response Headers(響應頭)中返回一些關于該請求的信息,其中有關登錄的信息是set-cookie,其作用是在瀏覽器中寫入cookie,之后的請求中會帶上cookie信息。
3) cookie
cookie是瀏覽器儲存在用戶電腦上的一小段文本文件,該文件中存了加密后的用戶信息、過期時間等,且每次請求都會帶上cookie。
4) 發評論
登錄成功后,可以用Python做一些只有登錄后才能進行的操作。例如,找到一篇文章的評論區,在開發者工具中將請求列表清空,接下來在網頁中進行評論操作,即可在請求列表中找到發評論的請求。請求地址在General中,其他參數在Form Data中。
Note:Request請求之間的cookie不共享,需要手動將登錄過后的cookie傳給發評論的請求。
import requests
headers = {
'user-agent': '……'
}
# 登錄參數
login_data = {
'…': '…',
'…': '…'
}
# 評論參數(其中的評論內容可自定義)
comment_data = {
'…': '…',
'…': '…'
}
# 發請求登錄
login_req = requests.post('登錄地址', data = login_data, headers = headers)
# 將登錄后的cookies傳遞給cookies參數用于發評論請求
comment_req = requests.post('發評論請求地址', cookies = login_req.cookies, data = comment_data, headers = headers)
# 狀態碼為200表示評論成功
print(comment_req.status_code)
5) session
由于cookie容量有限,難以存儲所有的用戶信息,因此可以用session建立一份用戶檔案。cookie中只要存儲用戶的身份信息,服務器可以通過身份信息來在session中查詢用戶的其他信息。
可以通過requests.Session()創建一個session,多個請求之間就可以共享cookie了,后續請求便不需要再傳cookie參數。此外,也可以通過session.headers.update()方法來更新全局的headers。因此,之前發評論的代碼可以改寫為:
import requests
headers = {
'user-agent': '……'
}
# 登錄參數
login_data = {
'…': '…',
'…': '…'
}
# 評論參數(其中的評論內容可自定義)
comment_data = {
'…': '…',
'…': '…'
}
session = requests.Session()
session.headers.update(headers)
# 使用session登錄
login_req = session.post('登錄地址', data = login_data)
# 使用session發評論
comment_req = session.post('發評論請求地址', data = comment_data)
# 狀態碼為200表示評論成功
print(comment_req.status_code)
3. selenium
1) selenium
selenium是瀏覽器自動化測試框架,可以控制瀏覽器,模擬人瀏覽網頁,從而獲取數據、自動操作等。
可以使用pip install selenium來安裝selenium,此外,還需安裝相應的瀏覽器驅動。以Chrome瀏覽器為例,可打開https://npm.taobao.org/mirrors/chromedriver網站,找到對應的瀏覽器驅動,并下載zip文件。下載完成后將解壓的exe放到Python安裝目錄的Scripts文件夾中。
2) 打開瀏覽器
用selenium打開Chrome瀏覽器的代碼如下:
from selenium import webdriver
browser = webdriver.Chrome()
運行代碼即可打開瀏覽器,然后將實例化后的瀏覽器對象賦值給browser變量,就可以操作該對象來控制瀏覽器。
3) 獲取數據
將要打開的網址傳給browser對象的get()方法,就可以打開對應的網頁,調用quit()可將瀏覽器關閉。
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.quit()
用selenium獲取的網頁源代碼是數據加載完畢后最終的源代碼,網頁加載后通過API獲取的數據也在其中,因此不必區分要爬取的網頁是靜態網頁還是動態網頁。
用print(browser.page_source)可以打印出網頁源代碼。
4) 處理數據
以獲取百度首頁的div標簽為例:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
div = browser.find_element_by_tag_name('div')
print(div.text)
browser.quit()
用selenium查找元素的方法如下:find_element_by_tag_name:通過標簽查找元素
find_element_by_class_name:通過class屬性名查找元素
find_element_by_id:通過id查找元素
find_element_by_name:通過name屬性查找元素
find_element_by_link_text:通過鏈接文本查找元素
find_element_by_partial_link_text:通過部分鏈接文本查找元素
通過這些方法得到的返回值都是WebElement對象,它與Tag對象相似,可以獲取文本內容和屬性值:WebElement.text:獲取元素文本內容
WebElement.get_attribute('屬性名'):獲取元素屬性值
上面的方法獲取的是第一個符合條件的元素,如果要查找所有符合條件的元素,將方法中的element改為elements即可。
此外,也可以將selenium與BeautifulSoup結合起來,共同完成獲取數據和處理數據的工作。例如,獲取網頁源代碼中所有a標簽:
soup = BeautifulSoup(browser.page_source, 'html.parser')
a_tags = soup.find_all('a')
for tag in a_tags:
print(tag.text)
browser.quit()
5) 控制瀏覽器click():點擊元素
send_keys():模擬按鍵輸入
通過以上兩個方法,在查找到對應的元素后,調用click()方法可以模擬點擊該元素,一般用于點擊鏈接或按鈕;調用send_keys()方法模擬按鍵輸入,傳入要輸入的內容即可,一般用于賬號密碼等輸入框的表單填寫。
例如,在百度中搜索python并打印搜索結果的標題:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
# 找到搜索框并輸入python
search = browser.find_element_by_id('kw')
search.send_keys('python')
# 點擊搜索按鈕
submit = browser.find_element_by_id('su')
submit.click()
# 找到搜索結果標題
titles = browser.find_element_by_class_name('qnBI_e')
# 打印搜索結果標題
for title in titles:
print(title.text)
browser.quit()
為了提升爬取效率,也可以通過以下代碼將瀏覽器設置為靜默模式,讓瀏覽器在后臺獲取數據、操作頁面:
options = webdriver.ChromeOptions()
options.add_argument('--headless')
browser = webdriver.Chrome(options = options)
Reference:
[1] Wes McKinney. 2017. Python for Data Analysis: Data Wrangling with Pandas, NumPy, and IPython, 2nd Edition [M]. O'Reilly Media, Inc.
[2] CSDN博客. Python博客[OL]. https://www.csdn.net/nav/python. 2020.
總結
以上是生活随笔為你收集整理的python3 requests 动态网页post提交数据_Python爬虫三:动态网页爬虫的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java redis 批量删除key_R
- 下一篇: react ui框架 移动端_你必须要知