概要:
 
这篇博文主要讲一下如何使用Phantomjs进行数据抓取,这里面抓的网站是太平洋电脑网估价的内容。主要是对电脑笔记本以及他们的属性进行抓取,然后在使用nodejs进行下载图片和插入数据库操作。

先进行所有页面的内容进行抓取

  1. var page =require('webpage').create();
  2. var address='http://product.pconline.com.cn/server/';
  3. var fs = require('fs');
  4. var mypath = 'version/server/server.txt';
  5. var count = 2;
  6. var pageSize=0;
  7. phantom.outputEncoding="gbk";
  8. page.settings.userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko";
  9.  
  10. function loadController(status){
  11. loadComputerList(address);
  12. }
  13.  
  14. function loadComputerList(url){
  15. console.log('loading '+url);
  16.  
  17. page.onLoadFinished = function loadListsucc(status){
  18. console.log("loadlistSucc ["+url+"] =======================Status:"+status);
  19. };
  20.  
  21. page.open(url,function(status){
  22. setTimeout(function(){
  23. console.log(status);
  24. var content='';
  25. content = page.evaluate(function(){
  26. var cont='';
  27. var listComputer = document.querySelectorAll('div.item-title>h3>a');
  28. var listPrice =document.querySelectorAll('div.price');
  29. for(var j=0;jvar computer = listComputer[j].innerText;
  30. var price = listPrice[j].innerText;
  31. var url = listComputer[j];
  32. cont += computer+'\t\t价格:'+price+','+url+'\r\n';
  33. }
  34. return cont;
  35. });
  36. console.log(content);
  37. console.log('========== write to file !============');
  38. try{
  39. fs.write(mypath, content, 'a');
  40. }catch(e){
  41. console.log(e);
  42. }
  43. console.log('========== begin loading next page!============');
  44. var nextUrl = page.evaluate(function(){
  45. var url = '';
  46. var next = document.querySelectorAll('div.pager a[class=page-next]');
  47. var cont = '';
  48. url = next[0];
  49. cont += url;
  50. return cont;
  51. });
  52. console.log(nextUrl);
  53.  
  54. if(count else{
  55. console.log(count);
  56. phantom.exit();
  57. }
  58. }, 100);
  59. });
  60. }
  61.  
  62. page.open(address,function(status){
  63. // page.onLoadFinished = loadController;
  64. page.render('computer.jpeg');
  65. pageSize = page.evaluate(function(){
  66. var cont='';
  67. var size =document.querySelector('div.pager>em>i').innerText;
  68. cont += size;
  69. return cont;
  70. });
  71. console.log(pageSize);
  72. loadController(status);
  73. });

上面部分代码可以直接抓取到

  1. http://product.pconline.com.cn/server/

这个页面中所有分页的信息

下面进行代码分析:

  1. page.open(address,function(status){
  2. // page.onLoadFinished = loadController;
  3. page.render('computer.jpeg');
  4. pageSize = page.evaluate(function(){
  5. var cont='';
  6. var size =document.querySelector('div.pager>em>i').innerText;
  7. cont += size;
  8. return cont;
  9. });
  10. console.log(pageSize);
  11. loadController(status);
  12. });

这部分代码是Phantomjs的入口,也是我们进行数据抓取的开始部分。

  1. var size =document.querySelector('div.pager>em>i').innerText;

这里抓到的信息是所有页面的页数,用来作为循环判断的次数依据

然后观察代码就可以发现从入口结束之后就跳转到了LoadContriller函数中去,然后再调用loadComputerList这个函数,然后就可以进行数据抓取了

我们再看一下

  1. var listComputer = document.querySelectorAll('div.item-title>h3>a');
  2. var listPrice =document.querySelectorAll('div.price');

这两段代码,就是我们要抓取的电脑URL以及价格的信息。 
再抓到我们想要的信息之后,我们再对其进行拼接

  1. for(var j=0;jlistComputer.length;j++){
  2. var computer = listComputer[j].innerText;
  3. var price = listPrice[j].innerText;
  4. var url = listComputer[j];
  5. cont += computer+'\t\t价格:'+price+','+url+'\r\n';
  6. }

然后获得一行具有基本信息的电脑属性。 
然后接下来的工作就是要把这些信息进行存储,我们这里因为不能直接存入数据库,所以要先存入文本中,代码如下:

  1. var fs = require('fs');
  2.  
  3. try{
  4. fs.write(mypath, content, 'a');
  5. }catch(e){
  6. console.log(e);
  7. }

再PhantomJS中有API种有相应的读写文件讲解,这里就不多说了,上述代码就是在请求获得之后,将我们拼接好的内容写入文件中,采用的方式是’a’是添加的意思

经过上述过程,我们已经能够将第一个页面中的所有基本信息抓下来了,接下来的问题就是我们该如何跳转到下一个页面中,去抓取接下来的内容

代码如下:

  1. var nextUrl = page.evaluate(function(){
  2. var url = '';
  3. var next = document.querySelectorAll('div.pager a[class=page-next]');
  4. var cont = '';
  5. url = next[0];
  6. cont += url;
  7. return cont;
  8. });
  9. console.log(nextUrl);
  10.  
  11. if(count console.log(nextUrl);
  12. count++;
  13. console.log(count);
  14. loadComputerList(nextUrl);
  15. }else{
  16. console.log(count);
  17. phantom.exit();
  18. }

这里面获取下一个页面Url用到的js语句是:

  1. var next = document.querySelectorAll('div.pager a[class=page-next]');

朋友们可以使用开发者工具去该网站中看一下点击下一页按钮对应的dom节点是什么,然后就明白这段代码的含义了

再这里面,我们获取了下一页的按钮之后,还需要进行判断现在的循环次数,由于下一页的按钮是一直存在的,我们并不能通过判断是否为空来结束任务,所以我这里用了一个比较蠢得办法来解决这个问题。

抓取所有页面的内容就基本上完成了,这段脚本代码比较简单,如果需要抓同一个网站,只需要修改两部分就可以了,一个是address这个入口,还有就是写文件的路径。

抓取详细信息

再上面我们已经抓到了一些基本信息了,但是页面中并没有为我们提供比如电脑cpu,内存,显卡这些内容,所以我们的抓取工作并没有完成。那么接下来的工作就是要通过我们刚才有抓到的url进入到电脑商品的详细信息页面中去,然后再抓下我们所需要的详细信息。 
代码如下:

  1. var page =require('webpage').create();
  2. var address='http://product.pconline.com.cn/server/';
  3. var fs = require('fs');
  4. var mypath='version/Server/server_page.txt';
  5. var stream = null;
  6. var steams = null;
  7. var K=1;
  8. var line ='';
  9. var cate ='';
  10. var url = '';
  11. var dragPath='version/Server/server_detail.txt';
  12. phantom.outputEncoding="gbk";
  13. page.settings.userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko";
  14.  
  15. function start(url){
  16. console.log(url);
  17. page.open(url,function(status){
  18. setTimeout(function(){
  19. if(status == 'success'){
  20. console.log('open success!');
  21. console.log('==========begin work!=============');
  22. stream = page.evaluate(function(){
  23. var name = document.querySelector('.pro-tit>h1').innerText;
  24. name = name.replace('参数','');
  25. var listComputer = document.querySelectorAll('div.pannel>ul .title');
  26. var listParameter = document.querySelectorAll('[itemid]');
  27. var price = document.querySelector('.r-price').innerText;
  28. price = price.replace(/\n/g,'');
  29. var cont= name+'|&|'+price+'|&|产品特性:';
  30. for(var j=0;jvar computer = listComputer[j].innerText;
  31. computer = computer.replace(' ','');
  32. cont += computer+' ';
  33. }
  34. for( var j = 0;jvar parameter = listParameter[j].innerText;
  35. parameter = parameter.replace(/\n/g,'');
  36. parameter = parameter.replace('\t',' ');
  37. if(j1){
  38. cont += parameter+"|&|";
  39. }else{
  40. cont += parameter+'';
  41. }
  42. }
  43.  
  44. return cont+'\r\n';
  45. });
  46. try{
  47. fs.write(dragPath, stream, 'a');
  48. }catch(e){
  49. console.log(e);
  50. }
  51. console.log(stream);
  52. }else{
  53. console.log('page open fail!');
  54. }
  55. before();
  56. }, 100);
  57. });
  58. }
  59.  
  60. function readFile(status){
  61. streams = fs.open(mypath,'r');
  62. before();
  63. }
  64.  
  65. function before(){
  66. console.log('=========work in befor==========='+K);
  67. K++;
  68. if(!streams.atEnd()){
  69. console.log('=========work in befor get Next Line===========');
  70. line = streams.readLine();
  71. cate = line.split(',');
  72. console.log(cate[1]);
  73. var pcUrl = cate[1].replace('.html','_detail.html');
  74. console.log(pcUrl);
  75. start(pcUrl);
  76. }else{
  77. console.log('end!!!!!!!!!!!!');
  78. phantom.exit();
  79. }
  80.  
  81. }
  82.  
  83. page.open(address,function(status){
  84.  
  85. readFile(status);
  86.  
  87. })

我们继续来分析下代码,Phantomjs的开始入口我们就不讲了,每次启动phantomjs都是由这个入口开始,然后再到我们想要的操作中去。

  1. function readFile(status){
  2. streams = fs.open(mypath,'r');
  3. before();
  4. }

这里我们成功打开文件,并且把文件中的内容缓存到了streams中去,这里设置的是全局变量,所以直接跳到before这个函数中去

  1. function before(){
  2. console.log('=========work in befor==========='+K);
  3. K++;
  4. if(!streams.atEnd()){
  5. console.log('=========work in befor get Next Line===========');
  6. line = streams.readLine();
  7. cate = line.split(',');
  8. console.log(cate[1]);
  9. var pcUrl = cate[1].replace('.html','_detail.html');
  10. console.log(pcUrl);
  11. start(pcUrl);
  12. }else{
  13. console.log('end!!!!!!!!!!!!');
  14. phantom.exit();
  15. }
  16.  
  17. }

这里面进行的操作主要是在抓文件前,我们需要对我们刚才读进来的内容进行分析,比如:

  1. line = streams.readLine();
  2. cate = line.split(',');
  3. var pcUrl = cate[1].replace('.html','_detail.html');

这三部分,首先就是实现了逐行读取的功能,将每一行的内容读出来,然后通过分隔符获得Url,这里由于我们获得的url并不是我们要的详细信息url,所以我们要进行拼接。

  1. http://product.pconline.com.cn/server/lenovo/514943.html
  2. http://product.pconline.com.cn/server/lenovo/514943_detail.html

这里提供两段实例,读者可以进去看一下,就明白我们为什么要这么拼接url了

  1. stream = page.evaluate(function(){
  2. var name = document.querySelector('.pro-tit>h1').innerText;
  3. name = name.replace('参数','');
  4. var listComputer = document.querySelectorAll('div.pannel>ul .title');
  5. var listParameter = document.querySelectorAll('[itemid]');
  6. var price = document.querySelector('.r-price').innerText;
  7. price = price.replace(/\n/g,'');
  8. var cont= name+'|&|'+price+'|&|产品特性:';
  9. for(var j=0;jvar computer = listComputer[j].innerText;
  10. computer = computer.replace(' ','');

这部分代码就是我们要获取详细信息的代码了,读者可以研究一下,其实原理就是找到节点,然后取出来,进行拼接,最后获得一个详细的信息,实例:

  1. 联想ThinkServer TS130 S1225/2G/500O|&|¥5417|&|产品特性:产品型号 TS130 S1225/2G/500O|&|产品类型 塔式|&|产品结构 4U|&|CPU系列 至强处理器E3系列,Intel|&|CPU核心 四核|&|总线规格 DMI 5GT/s|&|CPU型号 E3-1225|&|CPU主频 3.1GHz|&|三级缓存 6M|&|标配CPU数目 1个|&|主板插槽 1×PCIE 2.0 x161×PCIE 2.0 x12×PCI 32/33|&|内存类型 DDR3|&|标配内存 2G|&|最大内存容量 32G|&|硬盘接口类型 SATAⅢ|&|标配硬盘 500G|&|最大硬盘容量 4TB|&|硬盘转速 7200转|&|硬盘阵列 Raid 0,Raid 1|&|光驱 DVD-ROM光驱|&|显示芯片 集成显卡|&|网卡 双端口千兆网卡|&|工作环境 工作温度:10℃-35℃,工作湿度:10%-80%|&|存储环境 储存温度:-40℃-70℃,储存湿度:10%-90%|&|电源 180PLUS单电源|&|最大功率 280W|&|操作系统 Windows 2003 R2 SP2简体中文标准版(32位/64位) Windows 2003 R2 SP2简体中文企业版(32位/64位)Windows Server 2008 简体中文基础版(64位) Windows Server 2008 简体中文标准版(32位/64位)Windows Server 2008 简体中文企业版(32位/64位)Windows Server 2008 R2 简体中文基础版(64位)Windows Server 2008 R2 简体中文标准版(64位) Windows Server 2008 R2 简体中文企业版(64位) Windows Small Business Server 2011 Essential Windows XP 简体中文专业版,SP2Windows Vista Business 简体中文商业版Windows 7简体中文专业版(32位/64位)Windows 7简体中文旗舰版(32位/64位)|&|尺寸 406×377×174mm

上面这部分就是我们获取到的详细的电脑信息内容,然后再拼接完信息之后,我们要做的就是写入文件中去,这里和上面是相似的,我就不重复了。

Phantomjs+Nodejs+Mysql数据抓取(1.数据抓取)的更多相关文章

  1. Phantomjs+Nodejs+Mysql数据抓取(2.抓取图片)

    概要 这篇博客是在上一篇博客Phantomjs+Nodejs+Mysql数据抓取(1.抓取数据) http://blog.csdn.net/jokerkon/article/details/50868 ...

  2. [原创.数据可视化系列之十二]使用 nodejs通过async await建立同步数据抓取

    做数据分析和可视化工作,最重要的一点就是数据抓取工作,之前使用Java和python都做过简单的数据抓取,感觉用的很不顺手. 后来用nodejs发现非常不错,通过js就可以进行数据抓取工作,类似jqu ...

  3. [Python爬虫] 之八:Selenium +phantomjs抓取微博数据

    基本思路:在登录状态下,打开首页,利用高级搜索框输入需要查询的条件,点击搜索链接进行搜索.如果数据有多页,每页数据是20条件,读取页数 然后循环页数,对每页数据进行抓取数据. 在实践过程中发现一个问题 ...

  4. 爬虫抓取页面数据原理(php爬虫框架有很多 )

    爬虫抓取页面数据原理(php爬虫框架有很多 ) 一.总结 1.php爬虫框架有很多,包括很多傻瓜式的软件 2.照以前写过java爬虫的例子来看,真的非常简单,就是一个获取网页数据的类或者方法(这里的话 ...

  5. 使用NodeJS+AngularJS+MongoDB实现一个Web数据扒取-分析-展示的系统

    说到Web爬虫,Python占了半壁江山.但是Web页面不是Python的强项了,如果需要扒取Web数据,再Mashup出来一个自己的系统,全端JS是个不错的解决方案(其实不用Python扒数据是因为 ...

  6. 使用selenium webdriver+beautifulsoup+跳转frame,实现模拟点击网页下一页按钮,抓取网页数据

    记录一次快速实现的python爬虫,想要抓取中财网数据引擎的新三板板块下面所有股票的公司档案,网址为http://data.cfi.cn/data_ndkA0A1934A1935A1986A1995. ...

  7. 数据抓取的艺术(三):抓取Google数据之心得

    本来是想把这部分内容放到前一篇<数据抓取的艺术(二):数据抓取程序优化>之中.但是随着任务的完成,我越来越感觉到其中深深的趣味,现总结如下: (1)时间     时间是一个与抓取规模相形而 ...

  8. Charles 如何抓取https数据包

    Charles可以正常抓取http数据包,但是如果没有经过进一步设置的话,无法正常抓取https的数据包,通常会出现乱码.举个例子,如果没有做更多设置,Charles抓取https://www.bai ...

  9. 手把手教你用python打造网易公开课视频下载软件3-对抓取的数据进行处理

    上篇讲到抓取的数据保存到rawhtml变量中,然后通过编码最终保存到html变量当中,那么html变量还会有什么问题吗?当然会有了,例如可能html变量中的保存的抓取的页面源代码可能有些标签没有关闭标 ...

随机推荐

  1. JavaScript 中的数据类型

    Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...

  2. Linq表达式、Lambda表达式你更喜欢哪个?

    什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...

  3. 学习ASP.NET Core, 怎能不了解请求处理管道[6]: 管道是如何随着WebHost的开启被构建出来的?

    注册的服务器和中间件共同构成了ASP.NET Core用于处理请求的管道, 这样一个管道是在我们启动作为应用宿主的WebHost时构建出来的.要深刻了解这个管道是如何被构建出来的,我们就必须对WebH ...

  4. PHP的学习--RSA加密解密

    PHP服务端与客户端交互或者提供开放API时,通常需要对敏感的数据进行加密,这时候rsa非对称加密就能派上用处了. 举个通俗易懂的例子,假设我们再登录一个网站,发送账号和密码,请求被拦截了. 密码没加 ...

  5. hadoop2.7之Mapper/reducer源码分析

    一切从示例程序开始: 示例程序 Hadoop2.7 提供的示例程序WordCount.java package org.apache.hadoop.examples; import java.io.I ...

  6. jq选择器基础

    Jquery $代表选择器 使用jq必须要导入jq文件 <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js&qu ...

  7. UML图中经常用到几种的关系图例

    学习这个东西挺奇怪的,时间一长就容易忘记,或者记不清楚.今天看到一些UML图的关系,发现有些出入了,索性就写下来,以后再忘记的时候过来看看. 在UML的类图中,常见的有以下几种关系: 继承(Gener ...

  8. 易用BPM时代,软件开发者缘何选择H3?

    近年来,企业级软件开发市场暗流汹涌,呈现出多种态势.软件开发团队规模趋于小型化,工作方式趋于快捷化,超过半数的软件开发者在工作中会选择使用易用的软件开发工具.随着流程管理越来越受到企业的重视,流程开发 ...

  9. iOS 自定义方法 - 不完整边框

    示例代码 ///////////////////////////OC.h////////////////////////// ////  UIView+FreeBorder.h//  BHBFreeB ...

  10. java 字节流与字符流的区别

    字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢?实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作 ...