您好,登錄后才能下訂單哦!
使用nodejs怎么抓取頁面的始末,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
事由以及動機
2015年9月份全國研究生數學建模競賽的F題,旅游線路規劃問題。其中需要自己去查很多數據。例如所給201個***級景區的位置,以及景區距離所 在省會距離等等~開始隊友小伙伴準備從百度手動去一個一個查詢,但是效率極低,在這么短的時間內,需要收集這么多數據是多么的耗時,并且也不能把大把時間 花費在查資料上,雖然說查資料是必須的,題目也鼓勵我們從網上查詢相關數據,因此在團隊中的我就想到了讓計算機幫我們去做這件事。
***步,確定想要抓取的信息,獲取數據服務api
以查詢個兩地的行車時間為例,我們以百度地圖為例,見下圖
先打開需要去請求數據的網頁,打開開發人員工具(我用的是chrome),選擇Network選項卡,輸入需要查詢的內容(tips:先清除掉之前的網絡獲取紀錄,以方便接下來的借接口分析)。
點擊“查詢”,并監控網絡數據流,會發現網頁發起了很多的http請求,并返回了結果。
通過分析所有請求,拿到想要的請求接口(一般情況下,都不會是Type為圖片類型的,并且耗時較長的)。
點擊某個請求時能看到該請求的詳細信息
查看請求的頭部信息Headers
拿到請求的地 址:requestURL,例如:http://map.baidu.com/?newmap=1&reqflag=pcmap& biz=1&pcevaname=pc2&da_par=direct&from=webmap&qt=nav&da_src=pcmappg.searchBox.button&c=289&sn=2$$$$$$%E4%B8%8A%E6%B5%B7%E5%B8%82$$0$$$$&en=2$$$$$$%E5%8C%97%E4%BA%AC%E5%B8%82$$0$$$$&sc=289&ec=289&rn=5&extinfo=63&tn=B_NORMAL_MAP&nn=0&ie=utf-8&l=12&b=(13503777.31,3639994.64;13542753.31,3642234.64)&t=1443022534161
并分析,一般我們要看的是URL中的querey部分,也就是?后面的內容,一般來說由很多(字母+百分號)構成的為中文字符,是漢字被url轉碼獲得。可以把該地址拿到地址欄查詢一下,漢字的內容
那我們的數據服務API就拿到了
編寫數據訪問頁面
接下來就是利用XMLHTTPRequerst來調取他人的服務了
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>getData</title> </head> <body> <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script> <script> var sn="北京市"; var en="上海市"; var url="http://map.baidu.com/?newmap=1&reqflag=pcmap&biz=1&pcevaname=pc2&da_par=direct&from=webmap&qt=nav&da_src=pcmappg.searchBox.button&c=289&sn=2$$$$$$"+ sn+"$$0$$$$&en=2$$$$$$"+ en+"$$0$$$$&sc=289&ec=289&rn=5&extinfo=63&tn=B_NORMAL_MAP&nn=0&ie=utf-8&l=12&b=(13503777.31,3639994.64;13542753.31,3642234.64)&t=1443022534161"; $.ajax({ url:url, type:"get", success:function(res){ console.log(res) }, error:function(e){ console.log(e) } }) </script> </body> </html> html
運行察看結果:
跨域提示錯誤,跨域(見為什么瀏覽器不能跨域http://www.cnblogs.com/alvinwei1024/p/4626054.html)是瀏覽器的行為。
方法1: 通過jsonp的方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>getData</title> </head> <body> <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script> <script> var sn="北京市"; var en="上海市"; var url="http://map.baidu.com/?newmap=1&reqflag=pcmap&biz=1&pcevaname=pc2&da_par=direct&from=webmap&qt=nav&da_src=pcmappg.searchBox.button&c=289&sn=2$$$$$$"+ sn+"$$0$$$$&en=2$$$$$$"+ en+"$$0$$$$&sc=289&ec=289&rn=5&extinfo=63&tn=B_NORMAL_MAP&nn=0&ie=utf-8&l=12&b=(13503777.31,3639994.64;13542753.31,3642234.64)&t=1443022534161"; $.ajax({ url:url, type:"get", dataType:"jsonp", jsonp:"callback", success:function(res){ console.log(res) }, error:function(e){ console.log(e) } }) </script> </body> </html> html
運行結果:獲取到想要的數據
可以拿到,北京到上海的距離1208548,時間48617以及距離等。
dis: 1208548
kps: Array[38]
rss: Array[38]
taxi: Object
time: 48617
toll: 580
方法二:CORS
除了方法以利用jsonp跨域外,還可以通過服務器做一個代理,通過cors繞過原來資源不允許跨域的限制。
本文利用node來做服務器,原因很簡單,最方便,幾句代碼就能搞定,方便又快捷。
var http = require('http'); var request_ = require('request'); var urlencode2=require("urlencode2"); var url=require('url') http.createServer(function (request, response) { var arg1 = url.parse(request.url, true).query; var sn=arg1.sn; var en=arg1.en; var req_url="http://api.map.baidu.com/?qt=nav&c=131&sn=2%24%24%24%24%24%24%20"+ urlencode2(sn,'gbk')+"%24%240%24%24%24%24&en=2%24%24%24%24%24%24"+ urlencode2(en,'gbk')+"%24%240%24%24%24%24&sy=0&ie=utf-8&oue=1&fromproduct=jsapi&res=api&callback=BMap._rd._cbk54249"; request_.get({ url:req_url, json:true }, function(error, response_, body) { if (!error && response_.statusCode == 200) { var res=-1; if(body){ res=body.split(',"toll":')[0];//time s res=res.split('"time":')[2]; console.log(res) if(!res){ res=-1; } else{ res=res/60; } } response.writeHead(200, { "Content-Type": "text/html; charset=UTF-8", 'Access-Control-Allow-Origin':request.headers.origin }); response.end(res+'\n'); } else{ // console.log(error) } } ) }).listen(8888); // 終端打印如下信息 console.log('Server running at http://127.0.0.1:8888/'); nodejs
其中,本文用到了request(用于發起http請求)模塊和urlencode2(主要用于URLEncode)模塊
request安裝:
npm install request
詳見:https://github.com/request/request
urlencode2安裝:
詳見:https://github.com/node-modules/urlencode
1 var http = require('http');
2 http.createServer(function (request, response) {
3 //...
4 response.end('welcome baby');
5 }).listen(8888);
這幾句簡單的代碼就搭建了一個web服務,端口號是8888
$ node 文件名.js
在終端輸入以上指令即可允許該服務。
1 var arg1 = url.parse(request.url, true).query;
2 var sn=arg1.sn;
3 var en=arg1.en;
4 var req_url="http://api.map.baidu.com/?qt=nav&c=131&sn=2%24%24%24%24%24%24%20"+ 5 urlencode2(sn,'gbk')+"%24%240%24%24%24%24&en=2%24%24%24%24%24%24"+ 6 urlencode2(en,'gbk')+"%24%240%24%24%24%24&sy=0&ie=utf-8&oue=1&fromproduct=jsapi&res=api&callback=BMap._rd._cbk54249";
以上是獲取查詢參數并拼接請求字符串
然后利用request向目標服務器發送請求,并解析出需要的信息
最重要的是以下代碼:
1 response.writeHead(200, {
2 "Content-Type": "text/html; charset=UTF-8", 3 'Access-Control-Allow-Origin':request.headers.origin 4 }); 5 response.end(res+'\n');
允許所有用戶跨域訪問,因此我們就能訪問自己搭建的web服務了。
我在前端頁面只需,請求我們的地址http://localhost:8888
并且指定sn(start node)與 en(end node)一并發送到服務器即可。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。