nodejs抓取别人家的页面的始末-阿里云开发者社区

开发者社区> 行者武松> 正文

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

简介:
+关注继续查看

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

事由以及动机

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

第一步,确定想要抓取的信息,获取数据服务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来调取他人的服务了


  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head> 
  4.     <meta charset="UTF-8"
  5.     <title>getData</title> 
  6. </head> 
  7. <body> 
  8.     <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script> 
  9.     <script> 
  10.         var sn="北京市"
  11.         var en="上海市"
  12.         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$$$$$$"
  13.         sn+"$$0$$$$&en=2$$$$$$"
  14.         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"
  15.  
  16.         $.ajax({ 
  17.             url:url, 
  18.             type:"get"
  19.             success:function(res){ 
  20.                 console.log(res) 
  21.             }, 
  22.             error:function(e){ 
  23.                 console.log(e) 
  24.             } 
  25.         }) 
  26.     </script> 
  27. </body> 
  28. </html> 
  29.  
  30. html 

运行察看结果:

跨域提示错误,跨域(见为什么浏览器不能跨域http://www.cnblogs.com/alvinwei1024/p/4626054.html)是浏览器的行为。

方法1: 通过jsonp的方法


  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head> 
  4.     <meta charset="UTF-8"
  5.     <title>getData</title> 
  6. </head> 
  7. <body> 
  8.     <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script> 
  9.     <script> 
  10.         var sn="北京市"
  11.         var en="上海市"
  12.         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$$$$$$"
  13.         sn+"$$0$$$$&en=2$$$$$$"
  14.         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"
  15.  
  16.         $.ajax({ 
  17.             url:url, 
  18.             type:"get"
  19.             dataType:"jsonp"
  20.              jsonp:"callback"
  21.             success:function(res){ 
  22.                 console.log(res) 
  23.             }, 
  24.             error:function(e){ 
  25.                 console.log(e) 
  26.             } 
  27.         }) 
  28.     </script> 
  29. </body> 
  30. </html> 
  31.  
  32. html 

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

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

  1. dis1208548

  2. kpsArray[38]

  3. rssArray[38]

  4. taxiObject

  5. time48617

  6. toll580

方法二:CORS

除了方法以利用jsonp跨域外,还可以通过服务器做一个代理,通过cors绕过原来资源不允许跨域的限制。

本文利用node来做服务器,原因很简单,最方便,几句代码就能搞定,方便又快捷。


  1. var http = require('http'); 
  2. var request_ = require('request'); 
  3. var urlencode2=require("urlencode2"); 
  4. var url=require('url'
  5. http.createServer(function (request, response) { 
  6.      var arg1 = url.parse(request.url, true).query;  
  7.     var sn=arg1.sn; 
  8.     var en=arg1.en; 
  9.     var req_url="http://api.map.baidu.com/?qt=nav&c=131&sn=2%24%24%24%24%24%24%20"
  10.           urlencode2(sn,'gbk')+"%24%240%24%24%24%24&en=2%24%24%24%24%24%24"
  11.           urlencode2(en,'gbk')+"%24%240%24%24%24%24&sy=0&ie=utf-8&oue=1&fromproduct=jsapi&res=api&callback=BMap._rd._cbk54249"
  12.       request_.get({ 
  13.             url:req_url, 
  14.             json:true 
  15.         }, 
  16.         function(error, response_, body) { 
  17.           if (!error && response_.statusCode == 200) { 
  18.             var res=-1
  19.             if(body){ 
  20.               res=body.split(',"toll":')[0];//time  s 
  21.               res=res.split('"time":')[2]; 
  22.               console.log(res) 
  23.               if(!res){ 
  24.                 res=-1
  25.               } 
  26.               else
  27.                 res=res/60
  28.               } 
  29.             } 
  30.             response.writeHead(200, { 
  31.                 "Content-Type""text/html; charset=UTF-8"
  32.                 'Access-Control-Allow-Origin':request.headers.origin 
  33.             }); 
  34.             response.end(res+'\n'); 
  35.           } 
  36.           else
  37.             // console.log(error) 
  38.           } 
  39.         } 
  40.     ) 
  41. }).listen(8888); 
  42. // 终端打印如下信息 
  43. console.log('Server running at http://127.0.0.1:8888/'); 
  44.  
  45. 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)一并发送到服务器即可。


来源:51CTO

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
4009 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
3956 0
chrome爬页面上表格某列的数据
有的时候会有这样一个需求,页面上有个大表格,我需要复制里面的一列到本地。比如,我要从表格里面,复制列出来的所有机器IP(这样比数据库导出方便点~) 首先,先用chrome的开发者工具,找到要复制的列中的某一个单元格,然后选择复制xpath。这样会复制下来这个元素的xpath路径,比如: //
2795 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
5676 0
阿里云服务器远程登录用户名和密码的查询方法
阿里云服务器远程连接登录用户名和密码在哪查看?阿里云服务器默认密码是什么?云服务器系统不同默认用户名不同
80 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
10712 0
Nodejs的第一个页面
nodejs安装后如何查看和安装其他工具 网上nodejs的文章已经很多,这里只是写下自己的小小心得,如果能帮到别人当然更好。 安装nodejs这里就不叙述了,直接上nodejs官网下载就好了,初学者建议直接下载安装版,无需自己去编译。
582 0
django的模板页面里,如何获取一个集合的数据?
以前以为是用[下标],原来在模板,也作了变换,得用. 才能搞定。 如下例中的 object_list.0.server_type 'nginx'    {% ifequal object_list.0.server_type 'nginx' %} 发布程序    回滚 {% endifequal %} 下午休息。
868 0
+关注
行者武松
杀人者,打虎武松也。
14545
文章
2569
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载