在上一篇文章基础上对代码进行了整理,并合并进同步采集的方法
类中用到了另一个 Proxy代理类,请自行实现, 如果不需要使用代理,请去除相关代码
同步调用示意
$this->catcher=new LCatcher(10,20,false,true,true);
list($code,$content)=$this->catcher->get($url);
并发采集示意
$this->catch=new LCatcher(10,$asynNum,true);
$this->catch->pushJob($this,$url,9);
完整代码如下
<?php
/**
* 并发异步采集者
*/
class LCatcher {
//以下是需要配置的运行参数
public $timeout=10; //默认的超时设置 10 秒
public $useProxy=true; //是否使用代理服务器
public $concurrentNum=20; //并发数量
public $autoUserAgent=true; //是否自动更换UserAgent
public $autoFollow=false; //是否自动301/302跳转
/**
* 创建一个采集者
* @param number $timeout 超时
* @param number $concurrentNum 并发数
* @param string $useProxy 是否使用代理
*/
public function __construct($timeout=10,$concurrentNum=20,$useProxy=true,$autoFollow=false,$autoUserAgent=true){
$this->timeout=$timeout;
$this->concurrentNum=$concurrentNum;
$this->useProxy=$useProxy;
$this->autoFollow=$autoFollow;
$this->autoUserAgent=$autoUserAgent;
}
/**
* 串行采集
*
* @param unknown $url
* 要采集的地址
* @param string $must
* 是否肯定对方一定存在 (200,且有</html>)
* @param string $referer
* @return multitype:NULL mixed 阻塞当前进程直到采集到数据
*/
public function get($url, $must = true, $iconv = true, $referer = false) {
$url = trim ( $url );
static $lastUrl;
echo "\r\nURL : $url\r\n";
if ($referer === true) {
$referer = $lastUrl;
} elseif (! $referer) {
$referer = '';
}
//直到成功或放弃
while ( true ) {
list ( $ch, $proxy ) = $this->createHandle ( $url, $referer );
// 开始抓取
$begin = microtime ( true );
$content = curl_exec ( $ch );
$code = curl_getinfo ( $ch, CURLINFO_HTTP_CODE );
$end = microtime ( true );
$errno = curl_errno ( $ch ); // 错误编号
$error = curl_error ( $ch ); //错误 信息
// 关闭连接
curl_close ( $ch );
// 出错,应该是代理的问题,源站不可能出现此情况
if ($errno or $code >= '500' or ! $content or $code == '400' or $code == '403' or $code == '401' or $code == '408' or $code == '407') {
// 此代理标记失败
if ($this->useProxy) {
LProxy::failure ( $proxy);
}
// 显示错误信息
if ($errno) {
if ($errno == 28) {
$error = 'timeout of ' . $this->timeout . 's';
}
echo "\r\nProxy : $proxy\r\n";
echo "Curl error : $errno ($error)\r\n";
continue;
}
if ($code >= '500') {
echo "\r\nProxy : $proxy\r\n";
echo "Http Code : $code\r\n";
continue;
}
}
if ($must and ($code != 200 or ! strpos ( $content, '</html>' ))) {
if ($code != 200) {
echo "\r\nProxy : $proxy\r\n";
echo "Http Code : $code\r\n";
continue;
}
if (! strpos ( $content, '</html>' )) {
echo "\r\nProxy