php使用curl和正则表达式抓取网页数据示例


Posted in PHP onApril 13, 2014

利用curl和正则表达式做的一个针对磨铁中文网非vip章节的小说抓取器,支持输入小说ID下载小说。
依赖项:curl
可以简单的看下,里面用到了curl ,正则表达式,ajax等技术,适合新手看看。在本地测试,必须保证联网并且确保php开启curl的mode

SpiderTools.class.php

<?php

  session_start();

 //封装成类 开启这些自动抓取文章

  #header("Refresh:30;http://www.test.com:8080");

 class SpiderTools{ 

 //////////////////////////////////////////////////////////////////////////////////////////////////////////

 /*传入文章ID 解析出文章标题*/

 //////////////////////////////////////////////////////////////////////////////////////////////////////////

 public function getBookNameById($aid){

  //初始化curl

  $ch= curl_init();

  //url

  $url='http://www.motie.com/book/'.$aid;

  if(is_numeric($aid)){

  //正则表达式匹配

  $ru="/<h1\sclass=\"p-title\">\s*<a\shref=\"\/book\/\d+\">(.*)\s*<\/a>\s*<\/h1>/";

  }

  else{

  //<title>丧尸爆发之全家求生路_第一章  丧尸爆发  为吾友爱乐儿更新~_磨铁</title>

  $ru="/<title>(.*)<\/title>/";

  }

  //设置选项,包括URL

  curl_setopt($ch, CURLOPT_URL, $url);

  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//不自动输出内容

  curl_setopt($ch, CURLOPT_HEADER, 0);//不返回头部信息

  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 0); 

  //执行curl

  $output = curl_exec($ch);

  //错误提示

  if(curl_exec($ch) === false){

   die(curl_error($ch));

  }

  // 检查是否有错误发生

  if(curl_errno($ch)){

  echo 'Curl error: ' . curl_error($ch);

  }

  //释放curl句柄

  curl_close($ch);

  $arr=array();

  preg_match_all($ru,$output,$arr);

  return $arr[1][0];

   }

 //////////////////////////////////////////////////////////////////////////////////////////////////////////     

 /*传入文章ID  解析文章内容*/

 //////////////////////////////////////////////////////////////////////////////////////////////////////////

 public  function getBookContextById($aid){

  //开始解析文章

  $ids=array();

  $ids=explode("_",$aid);

  $titleId=trim($ids[0]);

  $aticleId=trim($ids[1]);

  $ch= curl_init();

  $ru="/<div class=\"page-content\">[\s\S]*<pre ondragstart=\"return false\" oncopy=\"return false;\" oncut=\"return false;\" oncontextmenu=\"return false\" class=\"note\" id=\"html_content_\d*\">[\s\S]*(.*)<img src=\"\/ajax\/chapter\/$titleId\/$aticleId\" class=\"hidden\" \/><\/pre>/ui"; 

  $url='http://www.motie.com/book/'.$aid;

  //正则表达式匹配
  //设置选项,包括URL

  curl_setopt($ch, CURLOPT_URL, $url);

  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//不自动输出内容

  curl_setopt($ch, CURLOPT_HEADER, 0);//不返回头部信息

  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 0); 

  //执行curl

  $output = curl_exec($ch);

  //错误提示

  if(curl_exec($ch) === false){

   die(curl_error($ch));

  }

  // 检查是否有错误发生

  if(curl_errno($ch)){

   echo 'Curl error: ' . curl_error($ch);

  }

  $arr=array();

  $arr2=array();

  preg_match_all($ru,$output,$arr);

  curl_close($ch);

  #var_dump($arr);

  $s=$arr[0][0];

  $s=substr($s,180);

  $arr2=explode("<img",$s);

  return trim($arr2[0]);

 }
 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 

 /*静态方法 @生成小说文件 可以直接调用 */

 //////////////////////////////////////////////////////////////////////////////////////////////////////////

     public static function createBookById($id){

  

  if(!is_numeric($id)){
  echo "<br/>INIT BEGIN START WRITE!";

  $st=new self();

  $cons=$st->getBookContextById($id);

  $title=$st->getBookNameById($id);

  $cons=trim($cons);

  $t=explode(" ",$title);

  //构造目录

  $dir=array();

  $dir=explode("_",$t[0]);

  $wzdir=$dir[0];  //书名称 作为目录名称

  $wzchapter=$dir[1]; //第几章

  //创建目录

  $wzdir2=iconv("UTF-8", "GBK", $wzdir);//目录编码 注意这里保留对$wzdir字符串的引用,用来构造文件名,不能用此处,防止二次编码

  if(!file_exists($wzdir2)){

   mkdir($wzdir2); //创建目录

  }

  //构造文件名

  $wztitle="./".$wzdir."/"."$t[0]".".txt";

  //保证保存的文件名称不是乱码

  $wztitle=iconv("UTF-8", "GBK", $wztitle);

  $f=fopen($wztitle,"w+");

  fwrite($f,$cons);

  echo "<font color='green'>$wzdir </font>".$wzchapter."<font color='red'>写入成功</font>";

  fclose($f); 

  

  } 

  else{

  $ids=self::getBookIdsById($id); 

 

  //这里服务器可能会掉线,所以最好用session记录循环

  #for($i=$_SESSION["$id"."_fid"];$i<=count($ids);$_SESSION["$id"."_fid"]++,$i++){

 

   #self::createBookById($id."_".$ids[$_SESSION["$id"."_fid"]++]);//构造id

  #}

  

  for($i=$_SESSION["$id"."_fid"];$i<=count($ids);$_SESSION["$id"."_fid"]++,$i++){

 

   self::createBookById($id."_".$ids[$i]);//构造id

  }

  

  #echo "<hr/><hr/><br/><h1>写入工作全部完成</h1>";

  #echo $id."_".$ids[0]."<br/>"; 

  #var_dump($ids);

  

  }


 }

  /*

  获取小说的所有ID

  @param $id 文章ID

  @return array;

  */

  public static function getBookIdsById($aid){ 

  $ch= curl_init();

  $url='http://www.motie.com/book/'.$aid."/chapter";

  //注意这里的?可以获取最少匹配项

  $ru='/[\s\S]*?<li class=\"\" createdate=\"\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2}\">[\s\S]*?<a href=\"\/book\/'.$aid.'_(\d*?)\"\s{1}>.*?<\/a>.*?/u';//正则表达式匹配

  //设置选项,包括URL

  curl_setopt($ch, CURLOPT_URL, $url);

  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//不自动输出内容

  curl_setopt($ch, CURLOPT_HEADER, 0);//不返回头部信息

  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 0); 

  //执行curl

  $output = curl_exec($ch);

  // 检查是否有错误发生

  if(curl_errno($ch)){

  echo 'Curl error: ' . curl_error($ch);

  }

  //释放curl句柄

  curl_close($ch);

  $arr=array();

  preg_match_all($ru,$output,$arr,PREG_PATTERN_ORDER);

  return $arr[1];

  }

}

?>

getinfo.php

<?php

 session_start();

require_once("SpiderTools.class.php");

if($_REQUEST["bid"]){

if(is_numeric($_REQUEST["bid"])){

 SpiderTools::createBookById(trim($_REQUEST["bid"]));

 }

 else{

  echo "<br/>请输入正确的文章ID<br/>";

 }

}

?>

index.html

<html>

<head><meta charset="utf-8"/></head>

<title>下载小说啦</title>

<body>

<h1>输入磨铁中文网你想看到的小说ID号就可以下载小说啦</h1>

<form method="get" action="getinfo.php">

<input type="text" id="myid" name="myid" value=""/>

<input type="button" value="生成小说" onclick="createbook();"/>

</form>

<div id="info" style="background:black;height:500px;width:1067px;overflow:scroll;color:white">

</div>
<!-----AJAX------>

<script language="javascript">

var xmlHttp;

function createbook()

{

xmlHttp=GetXmlHttpObject()

if (xmlHttp==null)

 {

 alert ("浏览器不支持ajax")

 return

 }

var bookid=document.getElementById("myid").value

var url="getinfo.php"

url=url+"?bid="+bookid;

url=url+"&sid="+Math.random()

xmlHttp.onreadystatechange=stateChanged 

xmlHttp.open("GET",url,true)

xmlHttp.send(null)

}
function stateChanged() 

{ 

if(xmlHttp.readyState==1){
 document.getElementById("info").innerHTML="正在准备工作,请耐心点哦~^_^~<img src=\"img/1.gif\"  /><br/>"; 

} 

if(xmlHttp.readyState==2){
 document.getElementById("info").innerHTML="正在联系服务器,这可能需要一点时间啦^><img src=\"img/2.gif\"  /><^<br/>"; 

}
if(xmlHttp.readyState==3){
 document.getElementById("info").innerHTML="正在解析数据<img src=\"img/3.gif\"  /><br/>"; 

}
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")

 { 

 

 document.getElementById("info").innerHTML=xmlHttp.responseText; 

 //xmlHttp.abort();
 
 }


}
function GetXmlHttpObject()

{

var xmlHttp=null;

try

 {

 // Firefox, Opera 8.0+, Safari

 xmlHttp=new XMLHttpRequest();

 }

catch (e)

 {

 //Internet Explorer

 try

  {

  xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");

  }

 catch (e)

  {

  xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");

  }

 }

return xmlHttp;

}

</script>

</body>

</html>
PHP 相关文章推荐
从零开始 教你如何搭建Discuz!4.1论坛
Jul 07 PHP
PHP中的函数嵌套层数限制分析
Jun 13 PHP
php安全配置 如何配置使其更安全
Dec 16 PHP
php数组声明、遍历、数组全局变量使用小结
Jun 05 PHP
php使用strtotime和date函数判断日期是否有效代码分享
Dec 25 PHP
使用Discuz关键词服务器实现PHP中文分词
Mar 11 PHP
php一维二维数组键排序方法实例总结
Nov 13 PHP
PHP框架自动加载类文件原理详解
Jun 06 PHP
PHP实现的链式队列结构示例
Sep 15 PHP
源码分析 Laravel 重复执行同一个队列任务的原因
Dec 25 PHP
PHP使用ajax的post方式下载excel文件简单示例
Aug 06 PHP
详解使用php-cs-fixer格式化代码
Sep 16 PHP
PHP header()函数常用方法总结
Apr 11 #PHP
开源php中文分词系统SCWS安装和使用实例
Apr 11 #PHP
PHP获取网页标题的3种实现方法代码实例
Apr 11 #PHP
PHP动态生成javascript文件的2个例子
Apr 11 #PHP
php实现数组筛选奇数和偶数示例
Apr 11 #PHP
php求正负数数组中连续元素最大值示例
Apr 11 #PHP
PHP入门经历和学习过程分享
Apr 11 #PHP
You might like
ThinkPHP模板判断输出Defined标签用法详解
2014/06/30 PHP
thinkphp查询,3.X 5.0方法(亲试可行)
2017/06/17 PHP
php实现微信公众号企业转账功能
2018/10/01 PHP
javascript 框架小结 个人工作经验
2009/06/13 Javascript
JavaScript CSS修改学习第二章 样式
2010/02/19 Javascript
jquery插件制作 提示框插件实现代码
2012/08/17 Javascript
JavaScript 命名空间 使用介绍
2013/08/29 Javascript
JS下载文件|无刷新下载文件示例代码
2014/04/17 Javascript
ECMAScript 6即将带给我们新的数组操作方法前瞻
2015/01/06 Javascript
JS实现同时搜索百度和必应的方法
2015/01/27 Javascript
Nodejs express框架一个工程中同时使用ejs模版和jade模版
2015/12/28 NodeJs
AngularJS延迟加载html template
2016/07/27 Javascript
原生js封装的ajax方法示例
2018/08/02 Javascript
Vue2.0实现组件之间数据交互和通信操作示例
2019/05/16 Javascript
JS+CSS实现3D切割轮播图
2020/03/21 Javascript
js实现特别简单的钟表效果
2020/09/14 Javascript
JS实现超级好看的鼠标小尾巴特效
2020/12/01 Javascript
Python内置函数之filter map reduce介绍
2014/11/30 Python
python实现nao机器人手臂动作控制
2019/04/29 Python
Python中@property的理解和使用示例
2019/06/11 Python
python中如何设置代码自动提示
2020/07/15 Python
Python3以GitHub为例来实现模拟登录和爬取的实例讲解
2020/07/30 Python
python实现自动打卡的示例代码
2020/10/10 Python
带你认识HTML5中的WebSocket
2015/05/22 HTML / CSS
世界上最全面的汽车零部件和配件集合:JC Whitney
2016/09/04 全球购物
Lancome兰蔻官方旗舰店:来自法国的世界知名美妆品牌
2018/06/14 全球购物
英国旅行箱包和行李箱购物网站:Travel Luggage & Cabin Bags
2019/08/26 全球购物
澳洲Chemist Direct药房中文网:澳洲大型线上直邮药房
2019/11/04 全球购物
集团公司党的群众路线教育实践活动工作总结
2014/03/03 职场文书
计算机售后服务承诺书
2014/05/30 职场文书
化工专业自荐书
2014/06/16 职场文书
财务工作犯错检讨书
2014/10/07 职场文书
逃课检讨书范文
2015/05/06 职场文书
小学开学典礼新闻稿
2015/07/17 职场文书
教你如何使用Python Tkinter库制作记事本
2021/06/10 Python
SpringBoot工程下使用OpenFeign的坑及解决
2021/07/02 Java/Android