本帖最後由 michael3636 於 2015-4-30 21:45 編輯
Part 3
接著 Part 2 我們繼續深入.先根據我們之前學到的東西,開個批判大會,按鍵在"我的,命令庫自帶有2個函數",一個是獲取網頁源文件,一個是獲取網絡時間,我們一起來足個批判..寫的啥垃圾東西嘛,上代碼
- Function 獲得網頁源文件(網頁地址)
- //說明:支持遠程獲取文本內容,如:MsgBox lib.網絡.獲得網頁源文件("http://www./test.txt")
- //例子:MsgBox lib.網絡.獲得網頁源文件("http://www.")
- Dim xmlHttp, xmlBody, xmlUrl
- Dim ThisCharCode ,NextCharCode ,BytesToBstr
- If InStr(網頁地址, "http://") = 0 Then
- xmlUrl = "http://" & 網頁地址
- Else
- xmlUrl = 網頁地址
- End if
- Set xmlHttp = CreateObject("Microsoft.XMLHTTP") //對象用老了,不適合了,就算用新的也不適合,容易被緩存和cookie干擾
- xmlHttp.Open "Get", xmlUrl, False
- xmlHttp.Send
- xmlBody = xmlHttp.ResponseBody //返回的是字節數組
- Set xmlHttp = Nothing
- 獲得網頁源文件 = ""
- If Len(xmlBody) = 0 Then Exit Function //字節數組該用LenB()函數
- Set ObjStream = CreateObject("Adodb.Stream") //開始轉碼
- With ObjStream
- .Type = 1
- .Mode = 3
- .Open
- .Write xmlBody
- .Position = 0
- .Type = 2
- .Charset = "GB2312" //把返回的內容(字節數組,也就是二進制數據)不管三七二十一統統轉成"GB2312"編碼
- BytesToBstr = .ReadText
- .Close
- End With
- Set ObjStream = Nothing
- 獲得網頁源文件 = BytesToBstr
- End Function
複製代碼 看完代碼心嚮往之,下面詳細說明爛在哪裡:以下為本帖隱藏內容 ==============================
1.Microsoft.XMLHTTP對象就版本而言.實在太老了,該用"Msxml2.XMLHTTP.6.0",但是在這裡,就算是用"Msxml2.XMLHTTP.6.0",也不適合,為什麼呢?
這個對象跟IE瀏覽器有著不可分割的聯繫,它的緩存,cookie,是否只用代理等等等等,都跟著IE走的,換而言之,使用這個對象的話,很容易出現例如明明網頁改了,但是你得到的源文件卻沒跟新(緩存問題).去按鍵論壇竟然上去就是登陸狀態,因為你ie登陸了,它跟ie共享cookie,所以它也是登陸狀態等等很多此類問題...很多人本來就不熟..它再搞這麼一出,,不鬱悶才怪,所以,就這個函數的功能而言,用"msxml2.Serverxmlhttp.6.0"或者"WinHttp.WinHttpRequest.5.1"都是可以的它們都是獨立於ie的,沒有此類情況
2.轉碼問題,現在網頁方面"UTF-8"編碼大行其道,可以這麼說,100個網站裡面至少有95個是utf-8編碼的,而不是gb2312,這返回內容都轉成gb2312不是撿了芝麻丟了西瓜麼?就我個人記憶而言...我印象裡只有sina和按鍵是gbk編碼的..其他的全是utf-8....換而言之..就這個函數..在按鍵和sina得到的源碼是正常的...其他的..絕大大部分都是亂碼....我從沒用過這個函數,但是我想我的判斷是不會有錯的. 讓我們用我們學到的來修正這個錯誤吧!!!
==============================
- Function 獲得網頁源文件(網頁地址,網頁編碼) //多個參數.設置編碼.跟亂碼說88
- Dim xmlHttp, xmlUrl,ObjStream
- If InStr(網頁地址, "http://") = 0 Then
- xmlUrl = "http://" & 網頁地址
- Else
- xmlUrl = 網頁地址
- End if
- Set xmlHttp = CreateObject("WinHttp.WinHttpRequest.5.1") //用這個對象,跟緩存/cookie 干擾說88
- xmlHttp.Open "GET", xmlUrl, True
- xmlHttp.Send
- If xmlhttp.waitforresponse() Then
- Set ObjStream = CreateObject("Adodb.Stream")
- ObjStream.Type = 1
- ObjStream.Mode = 3
- ObjStream.Open
- ObjStream.Write xmlHttp.ResponseBody
- ObjStream.Position = 0
- ObjStream.Type = 2
- ObjStream.Charset = 網頁編碼
- 獲得網頁源文件 = ObjStream.ReadText
- Else
- 獲得網頁源文件=False //如果獲取失敗返回值是false
- End If
- End Function
- // 調試 Plugin.Sys.SetCLB(獲得網頁源文件("www.baidu.com","utf-8")) //百度
- // 調試 Plugin.Sys.SetCLB(獲得網頁源文件("www.sina.com.cn","gbk")) //新浪
複製代碼
- 按鍵的"獲取網絡時間"代碼.獲取網絡至於跑國外去麼..難不成中國的鐘沒外國的准?,再說了..俺要淘寶服務器時間.俺要新浪時間..俺要按鍵時間..咋辦啊?最離譜的幹啥用"PUT"方式嘛,最最省事的"HEAD"方式足夠了懶得批判了.直接上代碼
- Function 獲得網絡時間(網頁地址)
- Dim Http, URL,mt
- If InStr(網頁地址, "http://") = 0 Then
- Url = "http://" & 網頁地址
- Else
- Url = 網頁地址
- End if
- Set Http = CreateObject("WinHttp.WinHttpRequest.5.1")
- Http.Open "HEAD", URL, True //head方式,因為服務器返回的頭部裡面就有時間..所以不需要網頁了
- Http.Send
- If Http.waitforresponse() Then
- mt = Http.getresponseheader("Date") //從頭部取到時間..js格式的(帶有星期幾跟時區的格式,跟vbs不一樣)
- mt = Cdate(Mid(mt, 5, len(mt) - 8)) //截取js格式的時間字符串.得到vbs的模式的時間
- 獲得網絡時間 = DateAdd("h", 8, mt) //中國是8時區,而服務器普遍是世界標準時,也就是0時區得時間.所以得加上8小時
- Else
- 獲得網絡時間=False //失敗返回false
- End If
- End Function
- TracePrint 獲得網絡時間("msdn.microsoft.com") //去微軟取時間玩
- TracePrint 獲得網絡時間("www.taobao.com") //看看淘寶服務器時間
- TracePrint 獲得網絡時間("www.qq.com") //看看qq網站時間
複製代碼
寫到這,蠻多代碼,蠻多大家沒見過的屬性方法.相信大家也很莫名了..是該總結下的時候了,
- Set http = CreateObject("WinHttp.WinHttpRequest.5.1") //創建對象.沒啥好說的
- http.SetProxy // 設置代理:0代表系統代理,需要特定軟件設置,1代表直連(不用代理,默認), 2代表使用代理, 兩個參數設置代理(如:http.SetProxy 2,"156.32.25.21:8087")
- http.SetTimeouts //超時設置,4個參數,單位毫秒: 域名解析超時,連接超時,發送請求超時,服務器返回內容超時 默認值為:0,60000,30000,30000 (0代表無限制)
幾個有用的屬性:
- http.[option](0)=你設置的值 告訴服務器我是誰,我們可以設置火狐/ie/谷歌隨你冒充,,,,,,一般不用 默認值你可以自己tr一下看看
- http.[option](2)=你設置的值 設置發送的URL鏈接的編碼.默認是65001(UTF-8),其他常用的是 936(GB2312),950(BIG5)
- http.[option](6)=布爾值 是否激活網頁重定向,默認是啟用,一般不常用,默認即可
補充:對象的option屬性實質上是個數組,有很多內容,我僅僅把有可能用到的羅列出來
- http.OPen 方法:打開對象,常用參數3個 請求方式,請求地址,是否異步請求
- http.SetRequestHeader : 設置請求頭的方法,參數有2, 頭部項目,對應的值 如 :http.setrequestheader "Accept-Encoding","gzip, deflate" (告訴服務器,能接受的壓縮方式),一般用於"POST"方式,因為"POST"方式有2個請求頭必須我們自己設置,詳見 Part 2. 該方法總是出現在open之後,send之前
- http.send : 向目標服務器發送請求,"POST" 方式的話,需要加上請求內容.如果open方法的異步請求設置為false,此方法將是一個阻塞操作,程序到此將暫停,直到服務器返回信息或者請求失敗.如果設置為true,代碼將不會暫停.繼續執行
- http.waitforresponse :當open方法的異步請求設置為true時.此方法才起作用,等待請求完成,代碼到此暫停..直到請求有個結果,返回值為布爾值,表明請求失敗或者成功,參數可有可無,參數為請求超時的秒數,超過參數設置極為請求失敗,返回false.不設置參數則以http.SetTimeouts設置的參數為準
以下屬性只有當請求成功以後才有意義:
- http.GetResponseHeader :取得服務器返回的頭部的指定項目的值,用法同http.SetRequestHeader,2者的區別是,一個是設置發給服務器的頭部,一個是取得服務器返回的頭部
- http.GetAllResponseHeaders 取得服務器所返回的頭部的所有內容
- http.ResponseText 只讀屬性,取得服務返回的文本
- http.ResponseBody 只讀屬性,取得服務器返回的最原始數據,(2進制數據,即字節數組類型)
好了..一口氣說完了.下面說下3種對象各自的優缺點 "WinHttp.WinHttpRequest.5.1"的特點:
- 使用上無任何限制,我們可以設置任何請求的頭部參數和內容,cookie和緩存對象內部自維護,這意味著..我們可以創建10個對象,同時使用10個對象在按鍵登陸10個賬號.
"Msxml2.serverXMLHTTP.6.0"
- 無法在請求頭設置"Referer"項目,即無法進行來源冒充,其他基本跟上面相同,無waitforresponse方法.但是有readyState屬性.可以用該屬性是否等於4來進行請求是否成功的判斷
"Msxml2.XMLHTTP.6.0"
- 無法設置"Cookie",無法來源冒充,跟IE共享cookie/緩存/代理,超時無法設置.其他跟上面差不多,這也意味著,你無論建立多少個對象,都是使用一樣的cookie,意味著無法同時對同一個網站進行多賬號操作
- 看上去好像這東西最沒用,但是換個方式想:比如,我開個ie登陸按鍵,順便勾下"自動登陸".然後退出ie,,然後創建個這個對象去隨便"GET"按鍵論壇,,,啊哈..啥都沒幹直接登陸狀態啊.....
- 這個對象如何克服該死的緩存問題.其實很簡單..open以後加一句:http.setrequestheader "If-Modified-Since","Tue 24 Feb 2009 08:01:04 GMT" ,然後按照正常步驟來..齊活啦...木有緩存困擾啦.這行代碼的意思是:給請求頭加一個 "If-Modified-Since"項目,內容是一個過去的js格式日期,只要過去的就行了,解釋就是:瀏覽器告訴服務器說:大哥,自從這個日期以後你網頁變過沒啊,如果變過發給我啊.......這肯定是廢話...09年當現在都幾年過去了,,網頁肯定變過了,,服務器大哥就發過來網頁了...而不是發個304讓你自己從硬盤解決(其實實際情況很複雜,有時候根本連請求都不發直接讀緩存..這裡不展開了)
以下為本帖隱藏內容 ==============================
下一節我們將進行實戰.鬧他個天翻地覆,為了隱藏而隱藏
==============================
|