失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > PHP CURL 并发 采集

PHP CURL 并发 采集

时间:2021-06-01 13:08:44

相关推荐

PHP CURL 并发 采集

的第一缕阳光终于在2月27日早上照在了北京的街道上, 心情豁然开朗, 写个博客 以记录此重大事件.

说并发之前,先说防封锁吧.

近期工作中需要采集一些其它网站的数据(对同行兄弟表示歉意).

1. 先用了 file_get_contents ,结果 根本得不到任何内容.

2.换curl ,一点问题都没有,内容获取成功. 但 很快就被对方屏蔽了, 导致 整个公司 的同事都无法访问 目标网站. 由此可见,目标网站是根据访问者的IP进行的封锁.

3.使用代理,这个CURL支持. 上网搜了一堆代理服务器的地址(几千个),

4.程序中轮换使用随机代理, 但有些代理不好用, 也没办法手工剔除. 解决方法: 所有代理地址写到数据库的表中, 根据抓取成功与失败, 剔除掉不好用的服务器.

5.随机轮换UserAgent.

6.完成以上后,采集是没问题了,但速度 不满意, 主要时间都在网络上(从代理访问目标网站). 开始研究并发.

7.查了一下资料,也不难.

8.并发数是个问题, 根据个人的电脑和网络情况吧.

说那么多,开始贴代码

class LSynCatch {

//默认的超时设置 10 秒

private static $timeout=10;

//构造一个连接句柄

public static function curlInit($url){

$ch = curl_init ( $url );

//随机取一个用户代理, 此变量请自行添加

$agent=self::$agents[rand(0,count(self::$agents)-1)];

//设置CURL参数

curl_setopt_array($ch, array(

CURLOPT_RETURNTRANSFER=>true, //要求返回结果

CURLOPT_TIMEOUT=>self::$timeout,//超时

CURLOPT_USERAGENT=> $agent, //用户代理

CURLOPT_REFERER=>'', //上一次页面

CURLOPT_COOKIE=>'', //COOKIE 无

CURLOPT_FOLLOWLOCATION=>false, //不自动 跳转

//以下是Header,用FireBug之类的抓取一个正常请求的Header数据就可以

CURLOPT_HTTPHEADER=>array (

//.....略

),

));

return $ch;

}

//全部请求地址的栈

private $urlStack=array();

//入栈

public function push(array $info){

array_push($this->urlStack, $info);

}

//全部入栈完成后,开始爬行

public function run(){

$chs = curl_multi_init();

$map = array();

//初始20个并发, 根据网络情况自行修改

while(count($map)<20){

$info=array_pop($this->urlStack);

$url=$info['url'];

$ch=self::curlInit($url);

//代理的类,请根据上述原则行开发

$info['proxy']=LProxy::get();

curl_setopt($ch, CURLOPT_PROXY, $info['proxy']);

curl_multi_add_handle($chs, $ch);

$map[strval($ch)] = $info;

}

//同时发起网络请求,持续查看运行状态

do{

$status = curl_multi_exec($chs, $active);

if ($status == CURLM_CALL_MULTI_PERFORM) {

continue;

}

if ($status != CURLM_OK) {

continue;

} //如果没有准备就绪,就再次调用curl_multi_exec

//终于有请求完成的

while ($done = curl_multi_info_read($chs)) {

$ch=$done['handle'];

$params = $map[strval($ch)];

$params['info'] = curl_getinfo($ch);

$params['errno']=curl_errno($ch);

$params['error'] = curl_error($ch);

$params['code']=curl_getinfo($ch,CURLINFO_HTTP_CODE);

$params['result'] = curl_multi_getcontent($ch);

//请求出错了,应该是代理服务器的错,换代理

if($params['errno']){

LProxy::failure($params['proxy']);

if($params['errno']==28){

$error='timeout of '.self::$timeout.' s';

}else{

$error=$params['error'];

}

echo 'URL : '.$params['url']."\r\n";

echo 'Curl errno:'.$params['errno'].' Curl error: ' . $error."\r\n";

continue;

}

//目标网站出错,如: 302,504,404之类

if($params['code']==0){

echo 'URL : '.$params['url']."\r\n";

echo 'Code : 0 Length : '.strlen($params['result'])."\r\n";

continue;

}

//本次抓取成功

LProxy::success($params['proxy']);

echo 'URL : '.$params['url']."\r\n";

echo 'Http Code : '.$params['code']. " \tUsed : ".round($params['info']['total_time'],2)." \tLength : ".strlen($params['result'] )."\r\n";

//调用 回调方法,对采集的内容进行处理

if ($params['callback']) {

$params['callback']($params);

}

//从并发中去除此句柄

curl_multi_remove_handle($chs, $ch);

curl_close($ch);

//从栈里再拿一个放到并发中

$info=array_pop($this->urlStack);

if($info){

$ch=self::curlInit($info['url']);

$info['proxy']=LProxy::get();

curl_setopt($ch, CURLOPT_PROXY, $info['proxy']);

curl_multi_add_handle($chs, $ch);

$map[strval($ch)] = $info;

}

//如果仍然有未处理完毕的句柄,那么就select

if ($active > 0) {

curl_multi_select($chs, 0.5); //此处会导致阻塞大概0.5秒。

}

}

}while($active > 0); //还有句柄处理还在进行中

//全部结束

curl_multi_close($chs);

}

以上是并发采集类的主体代码,其它无关代码我就不贴了.

以下是调用 时的 代码

$syn=new LSynCatch();

foreach ( $articles as $k => $v ) {

// 分析文章内容

$syn->push(array('url'=>$v,'callback'=>function(array $info){

self::process($info);

}));

}

$syn->run();

如果觉得《PHP CURL 并发 采集》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
相关阅读
Curl 采集乱码与采集不到 PHP

Curl 采集乱码与采集不到 PHP

2019-03-17

php采集 curl

php采集 curl

2023-06-28

PHP curl采集

PHP curl采集

2021-02-25

php curl 内容采集

php curl 内容采集

2021-07-04