From 6c2a12ed98068d4ec9566fd9b4bc93f0261bc04f Mon Sep 17 00:00:00 2001 From: HJ <734708094@qq.com> Date: Thu, 18 Sep 2014 17:48:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=9B=9E=E8=B0=83=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E4=BB=A5=E5=8F=8A=E6=A0=87=E7=AD=BE=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QueryList.class.php | 104 +++++++++++++++++++++++++++++++++------- README.md | 27 ++++++++++- demo/Searcher.class.php | 2 + 3 files changed, 116 insertions(+), 17 deletions(-) diff --git a/QueryList.class.php b/QueryList.class.php index fc92215..a3b466a 100644 --- a/QueryList.class.php +++ b/QueryList.class.php @@ -7,7 +7,7 @@ * @author Jaeger * @email 734708094@qq.com * @link http://git.oschina.net/jae/QueryList - * @version 2.0.0 + * @version 2.1.0 * * @example * @@ -15,12 +15,25 @@ $hj = QueryList::Query('http://mobile.csdn.net/',array("title"=>array('.unit h1','text'))); print_r($hj->jsonArr); +//回调函数1 +function callfun1($content,$key) +{ + return '回调函数1:'.$key.'-'.$content; +} +class HJ{ + //回调函数2 + static public function callfun2($content,$key) + { + return '回调函数2:'.$key.'-'.$content; + } +} //获取CSDN文章页下面的文章标题和内容 $url = 'http://www.csdn.net/article/2014-06-05/2820091-build-or-buy-a-mobile-game-backend'; $reg = array( - 'title'=>array('h1','text'), //获取纯文本格式的标题 - 'summary'=>array('.summary','text','input strong'), //获取纯文本的文章摘要,但保留input和strong标签 - 'content'=>array('.news_content','html','div a') //获取html格式的文章内容,但过滤掉div和a标签 + 'title'=>array('h1','text','','callfun1'), //获取纯文本格式的标题,并调用回调函数1 + 'summary'=>array('.summary','text','-input strong'), //获取纯文本的文章摘要,但保strong标签并去除input标签 + 'content'=>array('.news_content','html','div a -.copyright'), //获取html格式的文章内容,但过滤掉div和a标签,去除类名为copyright的元素 + 'callback'=>array('HJ','callfun2') //调用回调函数2作为全局回调函数 ); $rang = '.left'; $hj = QueryList::Query($url,$reg,$rang,'curl'); @@ -30,6 +43,7 @@ print_r($hj->jsonArr); $hj->setQuery(array('title'=>array('','text'),'url'=>array('a','href')),'#con_two_2 li'); //输出json数据 echo $hj->getJson(); + */ require 'phpQuery/phpQuery.php'; class QueryList @@ -44,7 +58,12 @@ class QueryList /** * 静态方法,访问入口 * @param string $page 要抓取的网页URL地址(支持https);或者是html源代码 - * @param array $regArr 【选择器数组】说明:格式array("名称"=>array("选择器","类型"[,"标签列表"]),.......),【类型】说明:值 "text" ,"html" ,"属性" ,【标签列表】:可选,当【类型】值为text时表示需要保留的HTML标签,为html时表示要过滤掉的HTML标签 + * @param array $regArr 【选择器数组】说明:格式array("名称"=>array("选择器","类型"[,"标签过滤列表"][,"回调函数"]),.......[,"callback"=>"全局回调函数"]); + * 【选择器】说明:可以为任意的jQuery选择器语法 + * 【类型】说明:值 "text" ,"html" ,"HTML标签属性" , + * 【标签过滤列表】:可选,当标签名前面添加减号(-)时(此时标签可以为任意的元素选择器),表示移除该标签以及标签内容,否则当【类型】值为text时表示需要保留的HTML标签,为html时表示要过滤掉的HTML标签 + * 【回调函数】/【全局回调函数】:可选,字符串(函数名) 或 数组(array("类名","类的静态方法")),回调函数应有俩个参数,第一个参数是选择到的内容,第二个参数是选择器数组下标,回调函数会覆盖全局回调函数 + * * @param string $regRange 【块选择器】:指 先按照规则 选出 几个大块 ,然后再分别再在块里面 进行相关的选择 * @param string $getHtmlWay 【源码获取方式】指是通过curl抓取源码,还是通过file_get_contents抓取源码 * @param string $outputEncoding【输出编码格式】指要以什么编码输出(UTF-8,GB2312,.....),防止出现乱码,如果设置为 假值 则不改变原字符串编码 @@ -100,6 +119,7 @@ class QueryList } //获取编码格式 $this->htmlEncoding = $this->_getEncode($this->html); + $this->html = $this->_removeTags($this->html,array('script','style')); if (!empty($regArr)) { $this->regArr = $regArr; $this->regRange = $regRange; @@ -114,8 +134,10 @@ class QueryList $i = 0; foreach ($robj as $item) { while (list($key, $reg_value) = each($this->regArr)) { + if($key=='callback')continue; $tags = isset($reg_value[2])?$reg_value[2]:''; $iobj = pq($item)->find($reg_value[0]); + switch ($reg_value[1]) { case 'text': $this->jsonArr[$i][$key] = $this->_allowTags(pq($iobj)->html(),$tags); @@ -127,6 +149,12 @@ class QueryList $this->jsonArr[$i][$key] = pq($iobj)->attr($reg_value[1]); break; } + + if(isset($reg_value[3])){ + $this->jsonArr[$i][$key] = call_user_func($reg_value[3],$this->jsonArr[$i][$key],$key); + }else if(isset($this->regArr['callback'])){ + $this->jsonArr[$i][$key] = call_user_func($this->regArr['callback'],$this->jsonArr[$i][$key],$key); + } } //重置数组指针 reset($this->regArr); @@ -134,21 +162,30 @@ class QueryList } } else { while (list($key, $reg_value) = each($this->regArr)) { + if($key=='callback')continue; $tags = isset($reg_value[2])?$reg_value[2]:''; $lobj = pq($hobj)->find($reg_value[0]); $i = 0; foreach ($lobj as $item) { switch ($reg_value[1]) { case 'text': - $this->jsonArr[$i++][$key] = $this->_allowTags(pq($item)->html(),$tags); + $this->jsonArr[$i][$key] = $this->_allowTags(pq($item)->html(),$tags); break; case 'html': - $this->jsonArr[$i++][$key] = $this->_stripTags(pq($item)->html(),$tags); + $this->jsonArr[$i][$key] = $this->_stripTags(pq($item)->html(),$tags); break; default: - $this->jsonArr[$i++][$key] = pq($item)->attr($reg_value[1]); + $this->jsonArr[$i][$key] = pq($item)->attr($reg_value[1]); break; } + + if(isset($reg_value[3])){ + $this->jsonArr[$i][$key] = call_user_func($reg_value[3],$this->jsonArr[$i][$key],$key); + }else if(isset($this->regArr['callback'])){ + $this->jsonArr[$i][$key] = call_user_func($this->regArr['callback'],$this->jsonArr[$i][$key],$key); + } + + $i++; } } } @@ -202,14 +239,15 @@ class QueryList /** * 去除特定的html标签 * @param string $html - * @param string $tags 多个标签名之间用空格隔开 + * @param string $tags_str 多个标签名之间用空格隔开 * @return string */ - private function _stripTags($html,$tags) + private function _stripTags($html,$tags_str) { - $tagsArr = preg_split("/\s+/",$tags,-1,PREG_SPLIT_NO_EMPTY); + $tagsArr = $this->_tag($tags_str); + $html = $this->_removeTags($html,$tagsArr[1]); $p = array(); - foreach ($tagsArr as $tag) { + foreach ($tagsArr[0] as $tag) { $p[]="/(<(?:\/".$tag."|".$tag.")[^>]*>)/i"; } $html = preg_replace($p,"",trim($html)); @@ -218,17 +256,51 @@ class QueryList /** * 保留特定的html标签 * @param string $html - * @param string $tags 多个标签名之间用空格隔开 + * @param string $tags_str 多个标签名之间用空格隔开 * @return string */ - private function _allowTags($html,$tags) + private function _allowTags($html,$tags_str) { - $tagsArr = preg_split("/\s+/",$tags,-1,PREG_SPLIT_NO_EMPTY); + $tagsArr = $this->_tag($tags_str); + $html = $this->_removeTags($html,$tagsArr[1]); $allow = ''; - foreach ($tagsArr as $tag) { + foreach ($tagsArr[0] as $tag) { $allow .= "<$tag> "; } return strip_tags(trim($html),$allow); } + private function _tag($tags_str) + { + $tagArr = preg_split("/\s+/",$tags_str,-1,PREG_SPLIT_NO_EMPTY); + $tags = array(array(),array()); + foreach($tagArr as $tag) + { + if(preg_match('/-(.+)/', $tag,$arr)) + { + array_push($tags[1], $arr[1]); + }else{ + array_push($tags[0], $tag); + } + } + return $tags; + } + /** + * 移除特定的html标签 + * @param string $html + * @param array $tags 标签数组 + * @return string + */ + private function _removeTags($html,$tags) + { + $tag_str = ''; + foreach ($tags as $tag) { + $tag_str .= $tag_str?','.$tag:$tag; + } + $doc = phpQuery::newDocumentHTML($html); + pq($doc)->find($tag_str)->remove(); + return pq($doc)->htmlOuter(); + } } + + diff --git a/README.md b/README.md index 2e2ba63..e7bdd39 100644 --- a/README.md +++ b/README.md @@ -1 +1,26 @@ -#QueryList交流社区: [http://ql.44i.cc/](http://ql.44i.cc/) #QueryList交流QQ群:123266961 ╰☆邪恶 魔方☆ #QueryList简介 *** QueryList是一个基于phpQuery的通用列表采集类,是一个简单、 灵活、强大的采集工具,采集任何复杂的页面 基本上就一句话就能搞定了。 #QueryList 使用 ```php //获取采集对象 $hj = QueryList::Query('http://www.baidu.com/s?wd=jaekj',array('title'=>array('h3','text'))); //输出结果:二维关联数组 print_r($hj->jsonArr); //输出结果:JSON数据 echo $hj->getJSON(); ``` 上面的代码实现的功能是采集百度搜索结果页面的所有搜索结果的标题,然后分别以数组和JSON格式输出。 ###QueryList 静态方法Query原型: >***Query***($page,$regArr,$regRange='',$getHtmlWay="curl",$output_encoding=false) 一共有五个参数,后面三个参数是可选的 * *$page* 要抓取的网页URL地址(默认支持https);或者是html源代码 * *$regArr* 【选择器数组】说明:格式array("名称"=>array("选择器","类型"[,"标签列表"]),.......),【类型】说明:值 "text" ,"html" ,"属性" ,【标签列表】:可选,当【类型】值为text时表示需要保留的HTML标签,为html时表示要过滤掉的HTML标签 * *$regRange* 【块选择器】:指 先按照规则 选出 几个大块 ,然后再分别再在块里面 进行相关的选择 * *$getHtmlWay* 【源码获取方式】指是通过curl抓取源码,还是通过file\_get_contents抓取源码,当$page参数为URL时此参数才有效 * *$output_encoding*【输出编码格式】指要以什么编码输出(UTF-8,GB2312,.....),防止出现乱码,如果设置为 假值 则不改变原字符串编码 ###QueryList 属性 * **得到多维数组格式的采集结果** >***jsonArr*** ###QueryList 方法 * **重新设置选择器** >void ***setQuery***($regArr,$regRange='') 一共两个参数,第二个参数是可选的,参数意义同构造函数。 * **得到JSON格式的采集结果** > string ***getJSON***() 无参,返回JSON字符串。 ##QueryList 依赖库 ``` phpQuery ``` phpQuery项目主页:[https://code.google.com/p/phpquery/](https://code.google.com/p/phpquery/) ##其它说明 QueryList 内置的只是简单的源码抓取方法,遇到更复杂的抓取情况,如:需要登陆 身份验证 时,请配合其它的PHP的HTTP类来使用,通过将辅助的HTTP类抓取到的网页源码传给QueryList即可。 ##DEMO站 微动态:[http://querylist.jaekj.com/](http://querylist.jaekj.com/) * thinkphp版本:V3.1.2 * QueryList版本:V1.6 * 后台地址: /admin * 后台账号密码: guest guest 这个demo站实现的功能相当于一个轻量级的微博站,内容全自动采集更新,可以自定义时间间隔采集任意站点的信息,自动更新到这个站点来,只需要在后台规则库简单的添加一条规则就可以实现全自动采集了,大家可以自行进入后台进行尝试,体验QueryList的魅力! ##作者信息 ``` Author : Jaeger Email : hj.q@qq.com 交流QQ群:123266961 ``` ##支持作者 如果您觉得 QueryList 对您非常有用并希望QueryList能越来越好,您可以考虑通过捐赠来支持作者,您的帮助是对作者最大的支持和动力。
![捐赠](http://git.oschina.net/jae/QueryList/raw/master/demo/thanks.png) 用手机扫描二位码支付
\ No newline at end of file +#QueryList交流社区: [http://ql.44i.cc/](http://ql.44i.cc/) #QueryList交流QQ群:123266961 ╰☆邪恶 魔方☆ #QueryList简介 *** QueryList是一个基于phpQuery的通用列表采集类,是一个简单、 灵活、强大的采集工具,采集任何复杂的页面 基本上就一句话就能搞定了。 #QueryList 使用 ```php //获取采集对象 $hj = QueryList::Query('http://www.baidu.com/s?wd=jaekj',array('title'=>array('h3','text'))); //输出结果:二维关联数组 print_r($hj->jsonArr); //输出结果:JSON数据 echo $hj->getJSON(); ``` 上面的代码实现的功能是采集百度搜索结果页面的所有搜索结果的标题,然后分别以数组和JSON格式输出。 ###QueryList 静态方法Query原型: >***Query***($page,$regArr,$regRange='',$getHtmlWay="curl",$output_encoding=false) 一共有五个参数,后面三个参数是可选的 >$page +>>类型: **string** +>>说明: **必选参数,要抓取的网页URL地址(支持https),或者是html源代码;这意味着你可以直接传一个网址给QueryList,也可以将通过自己的方式获取到的并经过你自己处理过的HTML源码传给QueryList** + +>$regArr +>>类型: **array** +>> 说明: **必选参数,选择器数组,格式array("名称"=>array("选择器","类型"[,"标签过滤列表"][,"回调函数"]),.......[,"callback"=>"全局回调函数"]);** +>>>+ **选择器**:可以为任意的jQuery选择器语法 +>>>+ **类型**:值 "text" ,"html" ,"HTML标签属性" +>>>+ **标签过滤列表**:可选,当标签名前面添加减号(-)时(此时标签可以为任意的元素选择器),表示移除该标签以及标签内容;否则当 **类型** 值为text时表示需要保留的HTML标签,为html时表示要过滤掉的HTML标签。有减号与没有减号的区别就在于,有减号时会移除那个标签包括那个标签内的所有内容,没有减号时只会移除那个标签并不会移除标签内的内容 +>>>+ **回调函数** / **全局回调函数**:可选,字符串(函数名) 或 数组(array("类名","类的静态方法")),回调函数应有俩个参数,第一个参数是选择到的内容,第二个参数是选择器数组下标,回调函数会覆盖全局回调函数 + >$regRange +>>类型:**array** +>默认值:**''** +>说明:**可选参数,块选择器,指 先按照规则 选出 几个大块 ,然后再分别再在块里面 进行相关的选择** + +>$getHtmlWay +>>类型:**string** +>>默认值:**'curl'** +>>可选值:**'curl','get'** +>>说明:**可选参数,源码获取方式,指是通过curl抓取源码,还是通过file\_get\_contents抓取源码** + >$outputEncoding +>>类型:**string** +>>默认值:**false** +>>可选值:**false,'UTF-8','GB2312'等** +>>说明:**可选参数,输出编码格式,指要以什么编码输出(UTF-8,GB2312,.....),防止出现乱码,如果设置为 假值 则不改变原字符串编码** ###QueryList 属性 * **得到多维数组格式的采集结果** >***jsonArr*** ###QueryList 方法 * **重新设置选择器** >void ***setQuery***($regArr,$regRange='') 一共两个参数,第二个参数是可选的,参数意义同构造函数。 * **得到JSON格式的采集结果** > string ***getJSON***() 无参,返回JSON字符串。 ##QueryList 依赖库 ``` phpQuery ``` phpQuery项目主页:[https://code.google.com/p/phpquery/](https://code.google.com/p/phpquery/) ##其它说明 QueryList 内置的只是简单的源码抓取方法,遇到更复杂的抓取情况,如:需要登陆 身份验证 时,请配合其它的PHP的HTTP类来使用,通过将辅助的HTTP类抓取到的网页源码传给QueryList即可。 ##DEMO站 微动态:[http://querylist.jaekj.com/](http://querylist.jaekj.com/) * thinkphp版本:V3.1.2 * QueryList版本:V1.6 * 后台地址: /admin * 后台账号密码: guest guest 这个demo站实现的功能相当于一个轻量级的微博站,内容全自动采集更新,可以自定义时间间隔采集任意站点的信息,自动更新到这个站点来,只需要在后台规则库简单的添加一条规则就可以实现全自动采集了,大家可以自行进入后台进行尝试,体验QueryList的魅力! 冷云搞笑:[http://x.44i.cc/](http://x.44i.cc/) ##作者信息 ``` Author : Jaeger Email : hj.q@qq.com 交流QQ群:123266961 ``` ##支持作者 如果您觉得 QueryList 对您非常有用并希望QueryList能越来越好,您可以考虑通过捐赠来支持作者,您的帮助是对作者最大的支持和动力。
![捐赠](http://git.oschina.net/jae/QueryList/raw/master/demo/thanks.png) 用手机扫描二位码支付
\ No newline at end of file diff --git a/demo/Searcher.class.php b/demo/Searcher.class.php index 1ce41d5..42ef808 100644 --- a/demo/Searcher.class.php +++ b/demo/Searcher.class.php @@ -148,3 +148,5 @@ require '../QueryList.class.php'; + $hj = Searcher::S('site:pan.baidu.com torrent','sogou',20,2); + print_r( $hj->jsonArr); \ No newline at end of file