基于curl数据采集之单页面并行采集函数get_htmls的使用


Posted in PHP onApril 28, 2013

用第一篇的get_html()实现简单的数据采集,由于是一个一个执行才采集数据的传输时间就会是所有页面下载的总时长,一个页面假设1秒,那么10个页面就是10秒了。所幸curl还提供了并行处理的功能。

要写一个并行采集的函数,先要了解要采集什么样的页面,对采集的页面用什么请求,才能写出一个相对常用的函数。

功能需求分析:

返回什么?

当然每一个页面的html集合成的数组

传递什么参数?

编写get_html()时,我们知道了可以用options数组来传递更多的curl参数,那么多页面同时采集函数的编写这种特性也得保留下来。

什么类型的参数?

无论是请求网页HTML,还是调用互联网api接口,get和post传递参数总是请求同一个页面或者接口,只是参数不同罢了。那么参数的类型是:

get_htmls($url,$options);

$url 是string

$options,是一个二维数组,每一个页面的参数为一个数组。

这样的话,貌似解决了问题。但是我找遍了curl的手册都没有看到get的参数传递在什么地方,所以只能$url 是数组的形式传递并且增加一个method参数

函数的原型就定下来了get_htmls($urls,$options = array, $method = ‘get');代码如下:

function get_htmls($urls, $options = array(), $method = 'get'){
     $mh = curl_multi_init();
     if($method == 'get'){//get方式传值 最常用
         foreach($urls as $key=>$url){
             $ch = curl_init($url);
             $options[CURLOPT_RETURNTRANSFER] = true;
             $options[CURLOPT_TIMEOUT] = 5;
             curl_setopt_array($ch,$options);
             $curls[$key] = $ch;
             curl_multi_add_handle($mh,$curls[$key]);
         }
     }elseif($method == 'post'){//post方式传值 
         foreach($options as $key=>$option){
             $ch = curl_init($urls);
             $option[CURLOPT_RETURNTRANSFER] = true;
             $option[CURLOPT_TIMEOUT] = 5;
             $option[CURLOPT_POST] = true;
             curl_setopt_array($ch,$option);
             $curls[$key] = $ch;
             curl_multi_add_handle($mh,$curls[$key]);
         }
     }else{
         exit("参数出错!\n");
     }
     do{
         $mrc = curl_multi_exec($mh,$active);
         curl_multi_select($mh);//减少CPU压力 注释掉CPU压力变大
     }while($active);
     foreach($curls as $key=>$ch){
         $html = curl_multi_getcontent($ch);
         curl_multi_remove_handle($mh,$ch);
         curl_close($ch);
         $htmls[$key] = $html;
     }
     curl_multi_close($mh);
     return $htmls;
 }

常用的get请求是通过改变url参数来实现的,又因为我们的函数是针对数据采集的。必然是分类采集,所以网址类似于这种:

http://www.baidu.com/s?wd=shili&pn=0&ie=utf-8

http://www.baidu.com/s?wd=shili&pn=10&ie=utf-8

http://www.baidu.com/s?wd=shili&pn=20&ie=utf-8

http://www.baidu.com/s?wd=shili&pn=30&ie=utf-8

http://www.baidu.com/s?wd=shili&pn=50&ie=utf-8

上面五个页面是很有规律的,改变的仅仅是pn的值。

$urls = array();
 for($i=1; $i<=5; $i++){
     $urls[] = 'http://www.baidu.com/s?wd=shili&pn='.(($i-1)*10).'&ie=utf-8';
 }
 $option[CURLOPT_USERAGENT] = 'Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20100101 Firefox/19.0';
 $htmls = get_htmls($urls,$option);
 foreach($htmls as $html){
     echo $html;//这里得到html 就可以进行数据处理了
 }

模拟常用的post请求:

写一个post.php文件如下:

 if(isset($_POST['username']) && isset($_POST['password'])){
     echo '用户名是: '.$_POST['username'].' 密码是: '.$_POST['password'];
 }else{
     echo '请求错误!';
 }

然后调用如下:
$url = 'http://localhost/yourpath/post.php';//这里是你的路径
 $options = array();
 for($i=1; $i<=5; $i++){
     $option[CURLOPT_POSTFIELDS] = 'username=user'.$i.'&password=pass'.$i;
     $options[] = $option;
 }
 $htmls = get_htmls($url,$options,'post');
 foreach($htmls as $html){
     echo $html;//这里得到html 就可以进行数据处理了
 }

这样这个get_htmls函数也基本能实现一些数据采集的功能了

今天分享就到这里 写的不好的 讲得不清楚的 请多多指教

PHP 相关文章推荐
PHP数据库操作面向对象的优点
Oct 09 PHP
用php来检测proxy
Oct 09 PHP
PHP中的cookie
Nov 26 PHP
动易数据转成dedecms的php程序
Apr 07 PHP
php ci框架验证码实例分析
Jun 26 PHP
table标签的结构与合并单元格的实现方法
Jul 24 PHP
跟我学Laravel之配置Laravel
Oct 15 PHP
php实现根据IP地址获取其所在省市的方法
Apr 30 PHP
PHP版本的选择5.2.17 5.3.27 5.3.28 5.4 5.5兼容性问题分析
Apr 04 PHP
thinkphp配置文件路径的实现方法
Aug 30 PHP
浅谈php中fopen不能创建中文文件名文件的问题
Feb 06 PHP
在TP5数据库中四个字段实现无限分类的示例
Oct 18 PHP
基于curl数据采集之单页面采集函数get_html的使用
Apr 28 #PHP
基于php上传图片重命名的6种解决方法的详细介绍
Apr 28 #PHP
PHP基础学习之流程控制的实现分析
Apr 28 #PHP
PHP基础之运算符的使用方法
Apr 28 #PHP
PHP数据类型之整数类型、浮点数的介绍
Apr 28 #PHP
PHP数据类型之布尔型的介绍
Apr 28 #PHP
PHP中最容易忘记的一些知识点总结
Apr 28 #PHP
You might like
PHP下一个非常全面获取图象信息的函数
2008/11/20 PHP
PHP统计二维数组元素个数的方法
2013/11/12 PHP
php访问数组最后一个元素的函数end()用法
2015/03/18 PHP
PHP-FPM之Chroot执行环境详解
2015/08/03 PHP
PHP7.0安装笔记整理
2015/08/28 PHP
在WordPress中获取数据库字段内容和添加主题设置菜单
2016/01/11 PHP
ext combox 下拉框不出现自动提示,自动选中的解决方法
2010/02/24 Javascript
JavaScript 以对象为索引的关联数组
2010/05/19 Javascript
jquery json 实例代码
2010/12/02 Javascript
JS判断不同分辨率调用不同的CSS样式文件实现思路及测试代码
2013/01/23 Javascript
Javascript基础知识(二)事件
2014/09/29 Javascript
EasyUI Pagination 分页的两种做法小结
2016/07/09 Javascript
JS中parseInt()和map()用法分析
2016/12/16 Javascript
JavaScript 数据类型详解
2017/03/13 Javascript
微信小程序 循环及嵌套循环的使用总结
2017/09/26 Javascript
简述vue状态管理模式之vuex
2018/08/29 Javascript
vue-cli配置flexible过程详解
2019/07/04 Javascript
解决vue 退出动画无效的问题
2020/08/09 Javascript
Vue 实现拨打电话操作
2020/11/16 Javascript
python基础教程之python消息摘要算法使用示例
2014/02/10 Python
用tensorflow构建线性回归模型的示例代码
2018/03/05 Python
Python拼接微信好友头像大图的实现方法
2018/08/01 Python
PyCharm 设置SciView工具窗口的方法
2019/01/15 Python
使用Python向C语言的链接库传递数组、结构体、指针类型的数据
2019/01/29 Python
解决django前后端分离csrf验证的问题
2019/02/03 Python
使用 Python 快速实现 HTTP 和 FTP 服务器的方法
2019/07/22 Python
python中类的输出或类的实例输出为这种形式的原因
2019/08/12 Python
django商品分类及商品数据建模实例详解
2020/01/03 Python
Django bulk_create()、update()与数据库事务的效率对比分析
2020/05/15 Python
Selenium获取登录Cookies并添加Cookies自动登录的方法
2020/12/04 Python
马耳他航空公司官方网站:Air Malta
2019/05/15 全球购物
2014年迎新年活动方案
2014/02/19 职场文书
深入理解go slice结构
2021/09/15 Golang
JavaScript中isPrototypeOf函数
2021/11/07 Javascript
MySQL中rank() over、dense_rank() over、row_number() over用法介绍
2022/03/23 MySQL
VUE使用draggable实现组件拖拽
2022/04/06 Vue.js