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
關于ajax的詳細介紹請讀者自行百度或者參考http://theodor.top/article/26中的“ajax”一節。
簡單的來說,ajax請求返回的是一串組織好的數據。瀏覽器會在符合條件(js腳本)的情況下發送一系列符合條件的鏈接,來向服務器請求更新一組數據。服務器發送數據后,瀏覽器直接在當前頁面改寫DOM,達到不跳轉鏈接進行更新的目的。
很多網站利用ajax對頁面進行美化處理,同時也能節省服務器的帶寬。
有時候我們需要在資訊網站上爬取較多信息,而這些信息正常情況下需要用戶不斷在瀏覽器界面做出動作(大多數情況下這個動作是下拉滾動條)才能加載。如果使用selenium等無界面瀏覽器爬取則太耗時間,使用常規爬蟲庫則無法對爬取下來的html頁面做出動作(也就是激活js)。所以我們需要繞過動作,直接對ajax請求進行爬取,達到快速準確獲取數據的目的(事實上,ajax請求返回的數據一般都十分易讀,因為沒有html的干擾,但也不排除存在直接返回一段html的網站,比如百度貼吧)。
本節我們以微博為例。
我們可以用兩種方式獲取ajax鏈接:第一種是分析原頁面的script文件找到發送ajax請求的代碼;第二種是直接通過工具截取網頁發送的ajax請求url,分析其規律并仿寫。
其中,分析script腳本是十分不推薦采取的方法,因為網站開發者通常會將js腳本寫成十分不友好的形式(請想象一堆var abcdefg出現在你面前,js甚至不用聲明變量類型)。但在窮途末路或者爬取者本身有興趣的情況下也不是不能一試。
第二種方法中的工具可以用瀏覽器自帶的開發者工具(F12),當然想用Fiddler等也不是不可以,重要的是結果不是過程。在待爬取頁面按下F12鍵打開開發者工具,然后點擊標簽“Network”,將瀏覽的類別調整到“XHR”(XMLHTTPRequest,這是ajax專有的數據格式):
不斷下拉滾動條,會發現XHR區域多了很多內容。觀察可以得知它們是一系列GET請求,且其請求參數為ajwvr、category、page、lefnav、cursor、rnd。變動的參數為:page,其每次請求+1,推測為請求頁數;rnd,可知其為請求發出的時間戳。
json全稱JavaScript Object Notation,是一種數據格式。大多數情況下,你可以將json數據看做字典。
瀏覽器向服務器發送ajax請求后,服務器會返回一組json數據,瀏覽器根據此json更新頁面。在繞過瀏覽器直接發送ajax請求時,服務器返回的json數據自然也由我們自行解析。
在已經拿到ajax請求的瀏覽器開發者工具下,雙擊ajax請求連接,在展開的窗口中選擇Response,可以看到微博服務器端返回的json數據:
其具體的json返回形式如下,其中data為其返回的html文本:
{"code":"100000","msg":"","data":" <!--\u699c\u5355\u680f\u4f4d\u7f6e-->\n <div…(略)"}
可知我們需要的數據在data鍵內,其為html文本段。
import requests
import time
import datetime
page=2
#分析得知ajax請求的page從2開始(因為page1在打開頁面的時候就已經加載到文檔里)
lefnav=0
category=0
ajwvr=6
cursor=""
#其余的參數,其意義可以忽略
url="https://weibo.com/a/aj/transform/loadingmoreunlogin?"
#通過分析之前瀏覽器發出的ajax請求,可得知微博使用的時間戳為毫秒級時間戳
def getrnd():
return round(time.time()*1000)
def geturl():
global page #我們要修改page,就要聲明為全局變量
page=page+1
return url+"ajwvr="+str(ajwvr)+"&category="+str(category)+"&page"+str(page-1)+"&cursor="+cursor+"&_rnd="+str(getrnd())
response=requests.get(geturl())
print(response.text)
當然,此處的ajax請求采取了GET的方式,但也有采取POST方式并且要求攜帶cookie的ajax請求。對于這種情況可以采用設置POST字典的方式。在真正的情況中也會有很多猜不出ajax請求參數的情況,這就需要讀者因地制宜隨機應變了。但ajax請求的精髓已經被我們講解過了,無論有多少分支,都不過萬變不離其宗耳。
是我的一家之見,若有疏漏還請一笑而過。
其實除了ajax,網頁上幾乎所有的頁面都可以通過找到url->分析參數->偽裝請求的方式來爬取。比如說搜索框的操作可以通過向搜索框跳轉的鏈接發送請求來模擬,按鈕按下可以通過向按鈕綁定的鏈接發送請求來模擬。這是因為互聯網的本質是數據與地址的組合,無論它們有多么華麗,終究也不過是一堆數據。發送請求的主動權在我們手上,只要分析手頭的數據,可以說沒有什么請求是偽裝不了的(當然,我是指你本人使用瀏覽器可以做出的請求)。
AJAX 實例
一個簡單的AJAX實例
創建一個簡單的XMLHttpRequest,從一個TXT文件中返回數據。
用AJAX加載 XML 文件
創建一個簡單的XMLHttpRequest,從一個XML文件中返回數據。
用AJAX進行一次 HEAD 請求
檢索資源(文件)的頭信息。
用AJAX進行一次指定的 HEAD 請求
檢索資源(文件)的指定頭信息。
用AJAX從ASP 文件返回數據
當用戶在文本框內鍵入字符時網頁如何與Web服務器進行通信
用AJAX從數據庫返回數據
用AJAX網頁如何獲取數據庫中的信息
用AJAX從XML 文件返回數據
創建一個XMLHttpRequest從XML文件中檢索數據并顯示在一個HTML表格中。
用callback函數的AJAX實例
用一個callback函數創建一個XMLHttpRequest,并從一個TXT文件中檢索數據。
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
)url:
要求為String類型的參數,(默認為當前頁地址)發送請求的地址。
2)type:
要求為String類型的參數,請求方式(post或get)默認為get。注意其他http請求方法,例如put和delete也可以使用,但僅部分瀏覽器支持。
3)timeout:
要求為Number類型的參數,設置請求超時時間(毫秒)。此設置將覆蓋$.ajaxSetup()方法的全局設置。
4)async:
要求為Boolean類型的參數,默認設置為true,所有請求均為異步請求。如果需要發送同步請求,請將此選項設置為false。
注意,同步請求將鎖住瀏覽器,用戶其他操作必須等待請求完成才可以執行。
5)cache:
要求為Boolean類型的參數,默認為true(當dataType為script時,默認為false),設置為false將不會從瀏覽器緩存中加載請求信息。
6)data:
要求為Object或String類型的參數,發送到服務器的數據。如果已經不是字符串,將自動轉換為字符串格式。get請求中將附加在url后。防止這種自動轉換,可以查看 processData(防止自動轉換)選項。對象必須為key/value格式,例如{foo1:"bar1",foo2:"bar2"}轉換為&foo1=bar1&foo2=bar2。如果是數組,JQuery將自動為不同值對應同一個名稱。例如{foo:["bar1","bar2"]}轉換為&foo=bar1&foo=bar2。
7)dataType:
要求為String類型的參數,預期服務器返回的數據類型。如果不指定,JQuery將自動根據http包mime信息返回responseXML或responseText,并作為回調函數參數傳遞。可用的類型如下:
● xml:返回XML文檔,可用JQuery處理。
● html:返回純文本HTML信息;包含的script標簽會在插入DOM時執行。
● script:返回純文本JavaScript代碼。不會自動緩存結果。除非設置了cache參數。注意在遠程請求時(不在同一個域下),所有post請求都將轉為get請求。
● json:返回JSON數據。
● jsonp:JSONP格式。使用SONP形式調用函數時,例如myurl?callback=?,JQuery將自動替換后一個“?”為正確的函數名,以執行回調函數。
● text:返回純文本字符串。
8)beforeSend:
這個參數主要是為了在向服務器發送請求前,執行一些操作。要求為Function類型的參數,發送請求前可以修改XMLHttpRequest對象的函數,例如添加自定義HTTP頭。在beforeSend中如果返回false可以取消本次ajax請求。XMLHttpRequest對象是惟一的參數。
function(XMLHttpRequest){
this; //調用本次ajax請求時傳遞的options參數
}
9)complete:
要求為Function類型的參數,請求完成后調用的回調函數(請求成功或失敗時均調用)。參數:XMLHttpRequest對象和一個描述成功請求類型的字符串。
function(XMLHttpRequest, textStatus){
this; //調用本次ajax請求時傳遞的options參數
}
10)success:
要求為Function類型的參數,請求成功后調用的回調函數,有兩個參數。
(1)由服務器返回,并根據dataType參數進行處理后的數據。
(2)描述狀態的字符串。
function(data, textStatus){
//data可能是xmlDoc、jsonObj、html、text等等
this; //調用本次ajax請求時傳遞的options參數
}
11)error:
要求為Function類型的參數,請求失敗時被調用的函數。該函數有3個參數,即XMLHttpRequest對象、錯誤信息、捕獲的錯誤對象(可選)。ajax事件函數如下:
function(XMLHttpRequest, textStatus, errorThrown){
//通常情況下textStatus和errorThrown只有其中一個包含信息
this; //調用本次ajax請求時傳遞的options參數
}
12)contentType:
要求為String類型的參數,當發送信息至服務器時,內容編碼類型默認為"application/x-www-form-urlencoded"。該默認值適合大多數應用場合。
13)dataFilter:
要求為Function類型的參數,給Ajax返回的原始數據進行預處理的函數。提供data和type兩個參數。data是Ajax返回的原始數據,type是調用jQuery.ajax時提供的dataType參數。函數返回的值將由jQuery進一步處理。
function(data, type){
//返回處理后的數據
return data;
}
14)dataFilter:
要求為Function類型的參數,給Ajax返回的原始數據進行預處理的函數。提供data和type兩個參數。data是Ajax返回的原始數據,type是調用jQuery.ajax時提供的dataType參數。函數返回的值將由jQuery進一步處理。
function(data, type){
//返回處理后的數據
return data;
}
15)global:
要求為Boolean類型的參數,默認為true。表示是否觸發全局ajax事件。設置為false將不會觸發全局ajax事件,ajaxStart或ajaxStop可用于控制各種ajax事件。
16)ifModified:
要求為Boolean類型的參數,默認為false。僅在服務器數據改變時獲取新數據。服務器數據改變判斷的依據是Last-Modified頭信息。默認值是false,即忽略頭信息。
17)jsonp:
要求為String類型的參數,在一個jsonp請求中重寫回調函數的名字。該值用來替代在"callback=?"這種GET或POST請求中URL參數里的"callback"部分,例如{jsonp:'onJsonPLoad'}會導致將"onJsonPLoad=?"傳給服務器。
18)username:
要求為String類型的參數,用于響應HTTP訪問認證請求的用戶名。
19)password:
要求為String類型的參數,用于響應HTTP訪問認證請求的密碼。
20)processData:
要求為Boolean類型的參數,默認為true。默認情況下,發送的數據將被轉換為對象(從技術角度來講并非字符串)以配合默認內容類型"application/x-www-form-urlencoded"。如果要發送DOM樹信息或者其他不希望轉換的信息,請設置為false。
21)scriptCharset:
要求為String類型的參數,只有當請求時dataType為"jsonp"或者"script",并且type是GET時才會用于強制修改字符集(charset)。通常在本地和遠程的內容編碼不同時使用。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。