整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Python爬蟲進(jìn)階(六):爬取Ajax內(nèi)容

          jax

          1 ajax的定義

          關(guān)于ajax的詳細(xì)介紹請(qǐng)讀者自行百度或者參考http://theodor.top/article/26中的“ajax”一節(jié)。

          簡(jiǎn)單的來(lái)說(shuō),ajax請(qǐng)求返回的是一串組織好的數(shù)據(jù)。瀏覽器會(huì)在符合條件(js腳本)的情況下發(fā)送一系列符合條件的鏈接,來(lái)向服務(wù)器請(qǐng)求更新一組數(shù)據(jù)。服務(wù)器發(fā)送數(shù)據(jù)后,瀏覽器直接在當(dāng)前頁(yè)面改寫DOM,達(dá)到不跳轉(zhuǎn)鏈接進(jìn)行更新的目的。

          2 為什么要爬取ajax請(qǐng)求

          很多網(wǎng)站利用ajax對(duì)頁(yè)面進(jìn)行美化處理,同時(shí)也能節(jié)省服務(wù)器的帶寬。

          有時(shí)候我們需要在資訊網(wǎng)站上爬取較多信息,而這些信息正常情況下需要用戶不斷在瀏覽器界面做出動(dòng)作(大多數(shù)情況下這個(gè)動(dòng)作是下拉滾動(dòng)條)才能加載。如果使用selenium等無(wú)界面瀏覽器爬取則太耗時(shí)間,使用常規(guī)爬蟲庫(kù)則無(wú)法對(duì)爬取下來(lái)的html頁(yè)面做出動(dòng)作(也就是激活js)。所以我們需要繞過(guò)動(dòng)作,直接對(duì)ajax請(qǐng)求進(jìn)行爬取,達(dá)到快速準(zhǔn)確獲取數(shù)據(jù)的目的(事實(shí)上,ajax請(qǐng)求返回的數(shù)據(jù)一般都十分易讀,因?yàn)闆](méi)有html的干擾,但也不排除存在直接返回一段html的網(wǎng)站,比如百度貼吧)。

          通過(guò)ajax請(qǐng)求繞過(guò)瀏覽器操作

          本節(jié)我們以微博為例。

          1 獲取ajax鏈接

          我們可以用兩種方式獲取ajax鏈接:第一種是分析原頁(yè)面的script文件找到發(fā)送ajax請(qǐng)求的代碼;第二種是直接通過(guò)工具截取網(wǎng)頁(yè)發(fā)送的ajax請(qǐng)求url,分析其規(guī)律并仿寫。

          其中,分析script腳本是十分不推薦采取的方法,因?yàn)榫W(wǎng)站開(kāi)發(fā)者通常會(huì)將js腳本寫成十分不友好的形式(請(qǐng)想象一堆var abcdefg出現(xiàn)在你面前,js甚至不用聲明變量類型)。但在窮途末路或者爬取者本身有興趣的情況下也不是不能一試。

          第二種方法中的工具可以用瀏覽器自帶的開(kāi)發(fā)者工具(F12),當(dāng)然想用Fiddler等也不是不可以,重要的是結(jié)果不是過(guò)程。在待爬取頁(yè)面按下F12鍵打開(kāi)開(kāi)發(fā)者工具,然后點(diǎn)擊標(biāo)簽“Network”,將瀏覽的類別調(diào)整到“XHR”(XMLHTTPRequest,這是ajax專有的數(shù)據(jù)格式):

          不斷下拉滾動(dòng)條,會(huì)發(fā)現(xiàn)XHR區(qū)域多了很多內(nèi)容。觀察可以得知它們是一系列GET請(qǐng)求,且其請(qǐng)求參數(shù)為ajwvr、category、page、lefnav、cursor、rnd。變動(dòng)的參數(shù)為:page,其每次請(qǐng)求+1,推測(cè)為請(qǐng)求頁(yè)數(shù);rnd,可知其為請(qǐng)求發(fā)出的時(shí)間戳。

          2 解析ajax返回的json數(shù)據(jù)

          json全稱JavaScript Object Notation,是一種數(shù)據(jù)格式。大多數(shù)情況下,你可以將json數(shù)據(jù)看做字典。

          瀏覽器向服務(wù)器發(fā)送ajax請(qǐng)求后,服務(wù)器會(huì)返回一組json數(shù)據(jù),瀏覽器根據(jù)此json更新頁(yè)面。在繞過(guò)瀏覽器直接發(fā)送ajax請(qǐng)求時(shí),服務(wù)器返回的json數(shù)據(jù)自然也由我們自行解析。

          在已經(jīng)拿到ajax請(qǐng)求的瀏覽器開(kāi)發(fā)者工具下,雙擊ajax請(qǐng)求連接,在展開(kāi)的窗口中選擇Response,可以看到微博服務(wù)器端返回的json數(shù)據(jù):

          其具體的json返回形式如下,其中data為其返回的html文本:

          {"code":"100000","msg":"","data":" <!--\u699c\u5355\u680f\u4f4d\u7f6e-->\n <div…(略)"}

          可知我們需要的數(shù)據(jù)在data鍵內(nèi),其為html文本段。

          實(shí)例:使用request爬取微博首頁(yè)的下拉滾動(dòng)條更新內(nèi)容

          import requests
          
          import time 
          
          import datetime
          
          page=2 
          
          #分析得知ajax請(qǐng)求的page從2開(kāi)始(因?yàn)閜age1在打開(kāi)頁(yè)面的時(shí)候就已經(jīng)加載到文檔里)
          
          lefnav=0
          
          category=0
          
          ajwvr=6
          
          cursor=""
          
          #其余的參數(shù),其意義可以忽略
          
          url="https://weibo.com/a/aj/transform/loadingmoreunlogin?"
          
          #通過(guò)分析之前瀏覽器發(fā)出的ajax請(qǐng)求,可得知微博使用的時(shí)間戳為毫秒級(jí)時(shí)間戳
          
          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)

          當(dāng)然,此處的ajax請(qǐng)求采取了GET的方式,但也有采取POST方式并且要求攜帶cookie的ajax請(qǐng)求。對(duì)于這種情況可以采用設(shè)置POST字典的方式。在真正的情況中也會(huì)有很多猜不出ajax請(qǐng)求參數(shù)的情況,這就需要讀者因地制宜隨機(jī)應(yīng)變了。但ajax請(qǐng)求的精髓已經(jīng)被我們講解過(guò)了,無(wú)論有多少分支,都不過(guò)萬(wàn)變不離其宗耳。

          擴(kuò)展

          是我的一家之見(jiàn),若有疏漏還請(qǐng)一笑而過(guò)。

          其實(shí)除了ajax,網(wǎng)頁(yè)上幾乎所有的頁(yè)面都可以通過(guò)找到url->分析參數(shù)->偽裝請(qǐng)求的方式來(lái)爬取。比如說(shuō)搜索框的操作可以通過(guò)向搜索框跳轉(zhuǎn)的鏈接發(fā)送請(qǐng)求來(lái)模擬,按鈕按下可以通過(guò)向按鈕綁定的鏈接發(fā)送請(qǐng)求來(lái)模擬。這是因?yàn)榛ヂ?lián)網(wǎng)的本質(zhì)是數(shù)據(jù)與地址的組合,無(wú)論它們有多么華麗,終究也不過(guò)是一堆數(shù)據(jù)。發(fā)送請(qǐng)求的主動(dòng)權(quán)在我們手上,只要分析手頭的數(shù)據(jù),可以說(shuō)沒(méi)有什么請(qǐng)求是偽裝不了的(當(dāng)然,我是指你本人使用瀏覽器可以做出的請(qǐng)求)。

          AJAX 實(shí)例

          一個(gè)簡(jiǎn)單的AJAX實(shí)例

          創(chuàng)建一個(gè)簡(jiǎn)單的XMLHttpRequest,從一個(gè)TXT文件中返回?cái)?shù)據(jù)。

          用AJAX加載 XML 文件

          創(chuàng)建一個(gè)簡(jiǎn)單的XMLHttpRequest,從一個(gè)XML文件中返回?cái)?shù)據(jù)。

          用AJAX進(jìn)行一次 HEAD 請(qǐng)求

          檢索資源(文件)的頭信息。

          用AJAX進(jìn)行一次指定的 HEAD 請(qǐng)求

          檢索資源(文件)的指定頭信息。

          用AJAX從ASP 文件返回?cái)?shù)據(jù)

          當(dāng)用戶在文本框內(nèi)鍵入字符時(shí)網(wǎng)頁(yè)如何與Web服務(wù)器進(jìn)行通信

          用AJAX從數(shù)據(jù)庫(kù)返回?cái)?shù)據(jù)

          用AJAX網(wǎng)頁(yè)如何獲取數(shù)據(jù)庫(kù)中的信息

          用AJAX從XML 文件返回?cái)?shù)據(jù)

          創(chuàng)建一個(gè)XMLHttpRequest從XML文件中檢索數(shù)據(jù)并顯示在一個(gè)HTML表格中。

          用callback函數(shù)的AJAX實(shí)例

          用一個(gè)callback函數(shù)創(chuàng)建一個(gè)XMLHttpRequest,并從一個(gè)TXT文件中檢索數(shù)據(jù)。

          如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!

          )url:

            要求為String類型的參數(shù),(默認(rèn)為當(dāng)前頁(yè)地址)發(fā)送請(qǐng)求的地址。

          2)type:

            要求為String類型的參數(shù),請(qǐng)求方式(post或get)默認(rèn)為get。注意其他http請(qǐng)求方法,例如put和delete也可以使用,但僅部分瀏覽器支持。

          3)timeout:

            要求為Number類型的參數(shù),設(shè)置請(qǐng)求超時(shí)時(shí)間(毫秒)。此設(shè)置將覆蓋$.ajaxSetup()方法的全局設(shè)置。

          4)async:

            要求為Boolean類型的參數(shù),默認(rèn)設(shè)置為true,所有請(qǐng)求均為異步請(qǐng)求。如果需要發(fā)送同步請(qǐng)求,請(qǐng)將此選項(xiàng)設(shè)置為false。

          注意,同步請(qǐng)求將鎖住瀏覽器,用戶其他操作必須等待請(qǐng)求完成才可以執(zhí)行。

          5)cache:

            要求為Boolean類型的參數(shù),默認(rèn)為true(當(dāng)dataType為script時(shí),默認(rèn)為false),設(shè)置為false將不會(huì)從瀏覽器緩存中加載請(qǐng)求信息。

          6)data:

            要求為Object或String類型的參數(shù),發(fā)送到服務(wù)器的數(shù)據(jù)。如果已經(jīng)不是字符串,將自動(dòng)轉(zhuǎn)換為字符串格式。get請(qǐng)求中將附加在url后。防止這種自動(dòng)轉(zhuǎn)換,可以查看  processData(防止自動(dòng)轉(zhuǎn)換)選項(xiàng)。對(duì)象必須為key/value格式,例如{foo1:"bar1",foo2:"bar2"}轉(zhuǎn)換為&foo1=bar1&foo2=bar2。如果是數(shù)組,JQuery將自動(dòng)為不同值對(duì)應(yīng)同一個(gè)名稱。例如{foo:["bar1","bar2"]}轉(zhuǎn)換為&foo=bar1&foo=bar2。

          7)dataType:

            要求為String類型的參數(shù),預(yù)期服務(wù)器返回的數(shù)據(jù)類型。如果不指定,JQuery將自動(dòng)根據(jù)http包mime信息返回responseXML或responseText,并作為回調(diào)函數(shù)參數(shù)傳遞??捎玫念愋腿缦拢?/p>

            ● xml:返回XML文檔,可用JQuery處理。

            ● html:返回純文本HTML信息;包含的script標(biāo)簽會(huì)在插入DOM時(shí)執(zhí)行。

            ● script:返回純文本JavaScript代碼。不會(huì)自動(dòng)緩存結(jié)果。除非設(shè)置了cache參數(shù)。注意在遠(yuǎn)程請(qǐng)求時(shí)(不在同一個(gè)域下),所有post請(qǐng)求都將轉(zhuǎn)為get請(qǐng)求。

            ● json:返回JSON數(shù)據(jù)。

            ● jsonp:JSONP格式。使用SONP形式調(diào)用函數(shù)時(shí),例如myurl?callback=?,JQuery將自動(dòng)替換后一個(gè)“?”為正確的函數(shù)名,以執(zhí)行回調(diào)函數(shù)。

            ● text:返回純文本字符串。

          8)beforeSend:

            這個(gè)參數(shù)主要是為了在向服務(wù)器發(fā)送請(qǐng)求前,執(zhí)行一些操作。要求為Function類型的參數(shù),發(fā)送請(qǐng)求前可以修改XMLHttpRequest對(duì)象的函數(shù),例如添加自定義HTTP頭。在beforeSend中如果返回false可以取消本次ajax請(qǐng)求。XMLHttpRequest對(duì)象是惟一的參數(shù)。

               function(XMLHttpRequest){
                  this;  //調(diào)用本次ajax請(qǐng)求時(shí)傳遞的options參數(shù)
                }

          9)complete:

            要求為Function類型的參數(shù),請(qǐng)求完成后調(diào)用的回調(diào)函數(shù)(請(qǐng)求成功或失敗時(shí)均調(diào)用)。參數(shù):XMLHttpRequest對(duì)象和一個(gè)描述成功請(qǐng)求類型的字符串。

               function(XMLHttpRequest, textStatus){
                 this;  //調(diào)用本次ajax請(qǐng)求時(shí)傳遞的options參數(shù)
               }

          10)success:

            要求為Function類型的參數(shù),請(qǐng)求成功后調(diào)用的回調(diào)函數(shù),有兩個(gè)參數(shù)。

          (1)由服務(wù)器返回,并根據(jù)dataType參數(shù)進(jìn)行處理后的數(shù)據(jù)。

          (2)描述狀態(tài)的字符串。

               function(data, textStatus){
                //data可能是xmlDoc、jsonObj、html、text等等
                this; //調(diào)用本次ajax請(qǐng)求時(shí)傳遞的options參數(shù)
               }

          11)error:

          要求為Function類型的參數(shù),請(qǐng)求失敗時(shí)被調(diào)用的函數(shù)。該函數(shù)有3個(gè)參數(shù),即XMLHttpRequest對(duì)象、錯(cuò)誤信息、捕獲的錯(cuò)誤對(duì)象(可選)。ajax事件函數(shù)如下:

              function(XMLHttpRequest, textStatus, errorThrown){
               //通常情況下textStatus和errorThrown只有其中一個(gè)包含信息
               this;  //調(diào)用本次ajax請(qǐng)求時(shí)傳遞的options參數(shù)
              }

          12)contentType:

          要求為String類型的參數(shù),當(dāng)發(fā)送信息至服務(wù)器時(shí),內(nèi)容編碼類型默認(rèn)為"application/x-www-form-urlencoded"。該默認(rèn)值適合大多數(shù)應(yīng)用場(chǎng)合。

          13)dataFilter:

          要求為Function類型的參數(shù),給Ajax返回的原始數(shù)據(jù)進(jìn)行預(yù)處理的函數(shù)。提供data和type兩個(gè)參數(shù)。data是Ajax返回的原始數(shù)據(jù),type是調(diào)用jQuery.ajax時(shí)提供的dataType參數(shù)。函數(shù)返回的值將由jQuery進(jìn)一步處理。

                function(data, type){
                  //返回處理后的數(shù)據(jù)
                  return data;
                }

          14)dataFilter:

          要求為Function類型的參數(shù),給Ajax返回的原始數(shù)據(jù)進(jìn)行預(yù)處理的函數(shù)。提供data和type兩個(gè)參數(shù)。data是Ajax返回的原始數(shù)據(jù),type是調(diào)用jQuery.ajax時(shí)提供的dataType參數(shù)。函數(shù)返回的值將由jQuery進(jìn)一步處理。

             function(data, type){
                  //返回處理后的數(shù)據(jù)
                  return data;
                }

          15)global:

          要求為Boolean類型的參數(shù),默認(rèn)為true。表示是否觸發(fā)全局ajax事件。設(shè)置為false將不會(huì)觸發(fā)全局ajax事件,ajaxStart或ajaxStop可用于控制各種ajax事件。

          16)ifModified:

          要求為Boolean類型的參數(shù),默認(rèn)為false。僅在服務(wù)器數(shù)據(jù)改變時(shí)獲取新數(shù)據(jù)。服務(wù)器數(shù)據(jù)改變判斷的依據(jù)是Last-Modified頭信息。默認(rèn)值是false,即忽略頭信息。

          17)jsonp:

          要求為String類型的參數(shù),在一個(gè)jsonp請(qǐng)求中重寫回調(diào)函數(shù)的名字。該值用來(lái)替代在"callback=?"這種GET或POST請(qǐng)求中URL參數(shù)里的"callback"部分,例如{jsonp:'onJsonPLoad'}會(huì)導(dǎo)致將"onJsonPLoad=?"傳給服務(wù)器。

          18)username:

          要求為String類型的參數(shù),用于響應(yīng)HTTP訪問(wèn)認(rèn)證請(qǐng)求的用戶名。

          19)password:

          要求為String類型的參數(shù),用于響應(yīng)HTTP訪問(wèn)認(rèn)證請(qǐng)求的密碼。

          20)processData:

          要求為Boolean類型的參數(shù),默認(rèn)為true。默認(rèn)情況下,發(fā)送的數(shù)據(jù)將被轉(zhuǎn)換為對(duì)象(從技術(shù)角度來(lái)講并非字符串)以配合默認(rèn)內(nèi)容類型"application/x-www-form-urlencoded"。如果要發(fā)送DOM樹(shù)信息或者其他不希望轉(zhuǎn)換的信息,請(qǐng)?jiān)O(shè)置為false。

          21)scriptCharset:

          要求為String類型的參數(shù),只有當(dāng)請(qǐng)求時(shí)dataType為"jsonp"或者"script",并且type是GET時(shí)才會(huì)用于強(qiáng)制修改字符集(charset)。通常在本地和遠(yuǎn)程的內(nèi)容編碼不同時(shí)使用。


          主站蜘蛛池模板: 日本视频一区在线观看免费| 国产成人精品无码一区二区老年人| 少妇激情AV一区二区三区| 国内精品无码一区二区三区| 国产剧情一区二区| 亚洲福利一区二区精品秒拍| 日本一区二区在线不卡| 中文字幕一区二区三区精彩视频 | 免费一区二区无码视频在线播放| 国产亚洲欧洲Aⅴ综合一区| 国产综合精品一区二区| 亚洲av永久无码一区二区三区| 美女视频一区二区三区| 国偷自产视频一区二区久| 国产一区视频在线免费观看| 精品国产天堂综合一区在线| 中文字幕日韩丝袜一区| 毛片一区二区三区| 精品一区狼人国产在线| 成人无码一区二区三区| 亚洲av乱码一区二区三区| 日韩免费无码一区二区三区| 无码国产精品一区二区免费vr| 国产精品视频一区麻豆| 无码少妇A片一区二区三区| 国产在线步兵一区二区三区| 无码国产亚洲日韩国精品视频一区二区三区 | 国产视频一区在线观看| 国产精品一区二区av不卡| 国产成人精品无码一区二区三区| 亚洲乱码一区二区三区在线观看| 日产亚洲一区二区三区| 日韩精品一区二区三区中文版| 精品人体无码一区二区三区| 免费播放一区二区三区| 久久精品无码一区二区三区日韩| 亚洲AV综合色一区二区三区| 精品国产一区二区二三区在线观看| 一区二区三区在线观看中文字幕 | 国产午夜精品免费一区二区三区 | 精品一区二区三区在线播放视频 |