nodejs抓取别人家的页面的始末

开发 前端
2015年9月份全国研究生数学建模竞赛的F题,旅游线路规划问题。其中需要自己去查很多数据。例如所给201个5A级景区的位置,以及景区距离所 在省会距离等等~开始队友小伙伴准备从百度手动去一个一个查询,但是效率极低,在这么短的时间内,需要收集这么多数据是多么的耗时,并且也不能把大把时间 花费在查资料上,虽然说查资料是必须的,题目也鼓励我们从网上查询相关数据,因此在团队中的我就想到了让计算机帮我们去做这件事。

内容:分析并获取页面调取数据的API(接口),并跨域获取数据保存在文档中(nodejs做代理-CORS)

事由以及动机

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 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

运行察看结果:

跨域提示错误,跨域(见为什么浏览器不能跨域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 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

运行结果:获取到想要的数据

可以拿到,北京到上海的距离1208548,时间48617以及距离等。

  1. dis1208548

  2. kpsArray[38]

  3. rssArray[38]

  4. taxiObject

  5. time48617

  6. toll580

#p#

方法二: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 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.

 其中,本文用到了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)一并发送到服务器即可。

相关代码:https://github.com/AlvinWei1024/blog-resources/tree/master/20150923 

作者:AlvinWei  文章出处:韦躐晟的博客 http://www.cnblogs.com/alvinwei1024/p/4834045.html

责任编辑:王雪燕 来源: 韦躐晟的博客
相关推荐

2017-09-22 13:22:59

大数据南京大学宿舍

2024-11-12 08:20:31

2017-11-12 21:32:52

戴尔

2024-10-24 08:21:33

2021-07-14 06:31:08

京东互联网加薪

2016-01-08 09:49:19

DockerDocker案例云应用开发

2022-12-12 08:14:47

2024-12-02 00:59:30

Spring

2025-02-28 08:21:00

2021-01-20 05:42:27

RabbitMQMQ vhost

2019-06-11 09:35:50

戴尔

2017-12-25 11:24:57

程序员代码编程

2017-06-13 14:15:51

戴尔协同计算汽车神话

2017-12-27 09:21:31

程序员华为年终奖

2024-02-20 12:53:41

2022-10-11 15:18:41

NodeJSCookie

2020-01-13 09:39:52

工具代码开发

2021-09-30 09:02:33

获取家庭住址

2017-11-02 10:45:21

2009-07-03 18:12:49

JSP页面
点赞
收藏

51CTO技术栈公众号