Python網絡爬蟲(三)
AJAX學習
AJAX=Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。通俗來說,AJAX是一種無需加載整個網頁的情況下,通過在後臺與服務器進行少量數據交換,更新部分網頁的技術,用於創建快速動態網頁的技術。
向服務器發送請求與服務器的響應
發送請求可以利用XMLHttpRequest對象的open()和send()方法。
方法 | 描述 |
---|---|
open(method,url,async) | 規定請求的類型、URL 以及是否異步處理請求。method:請求的類型;GET 或 POST;url:文件在服務器上的位置;async:true(異步)或 false(同步) |
send(string) | 將請求發送到服務器。string:僅用於 POST 請求 |
服務器的響應需要使用XMLHttpRequest對象的responseText或responseXML屬性。
屬性 | 描述 |
---|---|
responseText | 獲得字符串形式的響應數據。 |
responseXML | 獲得 XML 形式的響應數據。 |
下面有一段簡單的代碼:
<html>
<head>
<script type="text/javascript">
function loadXMLDoc()
{
var xmlhttp;
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
if(xmlhttp.status==404)
{
document.write("The file doesn't exist." );
}
}
xmlhttp.open("POST","/ajax/demo.asp",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");
}
</script>
</head>
<body>
<h2>我的一個測試案例</h2>
<button type="button" onclick="loadXMLDoc()">發出請求</button>
<div id="myDiv"></div>
</body>
</html>
可以在w3wschool測試網站看到相應的用法。
代碼中有xmlhttp.onreadystatechange=function()
,其中的onreadystatechange是一個事件,意思為當readyState發生改變時,onreadystatechange事件會自動觸發。下面是XMLHttpRequest對象的三個重要的屬性:
屬性 | 描述 |
---|---|
onreadystatechange | 存儲函數(或函數名),每當 readyState 屬性改變時,就會調用該函數。 |
readyState | 存有 XMLHttpRequest 的狀態。從 0 到 4 發生變化。0: 請求未初始化;1: 服務器連接已建立;2: 請求已接收;3: 請求處理中;4: 請求已完成,且響應已就緒 |
status | 200: "OK";404: 未找到頁面 |
網絡爬蟲相關
python角度分析AJAX
下面我們從python爬蟲的角度對AJAX進行思考,可以分為發送請求->解析內容->渲染網頁三個步驟。其中發送請求,是使用javascript的代碼進行實現,新建了XMLHttpRequest對象,然後利用onreadystatechange屬性設置了監聽,然後再用open()和send()方法發送請求,而我們在python中是請求後直接可以得到響應結果。解析內容是在發送請求並收到服務器的響應後,onreadystatechange事件又再一次被觸發,此時利用xmlhttp的responseText屬性就可以獲取響應的內容。類似於 Python 中利用 Requests向服務器發起了一個請求,然後得到響應的過程。那麽返回內容可能是 HTML,可能是 Json,接下來只需要在方法中用 JavaScript 進一步處理即可。最後一個步驟是渲染網頁,我們都知道javascript可以更改網頁內容,而代碼中document.getElementById().innerHTM
這樣的操作就是對某個元素內的源代碼進行更改,這樣網頁顯示的內容就發生了改變;這是對Document網頁文檔進行了操作,即DOM操作。在python中我們同樣的也是利用beautifulsoup庫解析了網頁後,查找其中的節點然後進行提取,AJAX只不過在對應的節點處更改為服務器返回的內容,這樣原網頁的代碼量很少,但是渲染的時候是通過服務器的響應進行渲染的。
AJAX分析
首先我們在瀏覽器中進入F12開發者模式,進入存儲並刷新一個頁面(這裏以用FireFox打開微博為例),會出現很多請求,這實際上就是在頁面加載過程中瀏覽器與服務器之間發送 Request 和接收 Response 的所有記錄。
而AJAX請求類型為xhr,可以看到有下面3條請求,我們隨便點進去一個進行查看:
而我們所有請求的第一個則是網頁的源代碼,基本上只是寫出了節點,沒有渲染的代碼。當我們加載新內容的時候,會出現新的AJAX請求,比如筆者這裏提供三個請求地址:
https://m.weibo.cn/api/container/getIndex?type=uid&value=2145291155&containerid=1005052145291155
https://m.weibo.cn/api/container/getIndex?type=uid&value=2145291155&containerid=1076032145291155
https://m.weibo.cn/api/container/getIndex?type=uid&value=2145291155&containerid=1076032145291155&page=2
每次更新都會有新的請求。所以我們需要利用python來實現AJAX請求的模擬,從而實現數據的抓取。
Python提取AJAX數據
首先分析一下上面筆者列出的三個請求地址,發現地址都包含有type、value、containerid與page,前兩個地址加上page=1也是可以請求的,瀏覽器自動省略了而已。觀察一下這些請求,發現它們的 type、value、containerid 始終如一。type 始終為 uid,value的值就是頁面的鏈接中的數字,其實這就是用戶的 id,另外還有一個containerid,經過觀察發現它就是 107603 然後加上用戶id。所以改變的值就是 page,很明顯這個參數就是用來控制分頁的,page=1 代表第一頁,page=2 代表第二頁,以此類推。
那麽我們只需要以這些參數作為請求參數請求然後抓取json數據就行了。
Python網絡爬蟲(三)