dev-master
9999999-devphp爬虫
Apache-2.0
The Requires
by edan
php crawl
Wallogit.com
2017 © Pedro Peláez
php爬虫
多进程可能出现的问题:因为多进程时各个进程之间的布隆过滤器无法保持一致,所以历史记录表和抓取任务表可能会出现重复内容。一般情况下也没必要使用多进程。, (*1)
多个线程使用同一个tor链路:已实测如果有多个线程正在使用同一个tor链路(比如下载),此时用kill -1 tor进程id切换tor链路,不会对这些线程产生影响,新的线程会使用新的tor链路, (*2)
长时间抓取需要考虑的问题:一般默认8小时后数据库连接将会断开,如果任务跑的时间特别长,修改mysql数据库配置的interactive_timeout和wait_timeout, (*3)
目前下文中所指"自定义信息数组"包含:① 'task'键保存任务数组 ② 'opt'键保存抓取选项数组 ③ 'tor'键保存一个数组['port'=>端口号,'pid'=>进程id], (*4)
通过addTask()方法或者手动向抓取任务表中添加任务时需注意:因为先添加的任务先处理,所以添加任务的顺序会影响采集到的数据在数据库中的排列顺序。通常老的任务应该先添加,最新任务后添加。, (*5)
即使返回响应状态码200,调用了抓取成功回调函数,也并不一定是\"真正的抓取成功\"了,因为返回的内容很可能是预期外的其他内容,所以务必进行特征检测,保证是需求的内容, (*6)
//创建FatGoose对象 $fg=new FatGoose(); //设置抓取回调函数数组 $fg->setCallbacksArr(); //注册一个回调函数,自动传入自定义信息数组的引用,此回调函数在创建每个curl资源的时候都会调用 //这个回调函数可以(1)用返回值设置额外的或覆盖已存在的curl选项(2)往自定义信息数组里面注入额外信息 /*此回调函数大致结构如下,特别要注意参数是引用传递 function(&$customInfoArr) { ... $customInfoArr['sum']=10000; 注入了额外信息 ... return [CURLOPT_PROXYTYPE=>CURLPROXY_HTTP,CURLOPT_PROXY=>'127.0.0.1:1080']; 设置额外的curl选项 } */ $fg->registerFuncExtraCurlOpt(); //添加初始抓取任务,要注意添加任务的顺序,先添加,先抓取。 //初始抓取任务只需添加一次,随后可注释掉 $fg->addTask(); //开始抓取 $fg->run();
//创建FatGoose对象 $fg=new FatGoose(); //设置监视回调函数数组 $fg->setMonitorCallbacksArr(); //开始监视 $fg->monitor();
静态方法mCrawl()用的回调函数没有中括号[ ]里面的部分,也没有返回值。此方法主要用于一些简单的抓取和进行抓取测试。, (*7)
curl信息数组里面有什么可以看这个页面的"Return Values"部分 https://www.php.net/manual/en/function.curl-getinfo.php, (*8)
onSuccess, (*9)
这个回调函数主要有三个作用:, (*10)
①对抓取到的内容进行分析,提取出自己想要的数据保存到数据库中, (*11)
②返回一个数组,里面的url会成为下一级别的抓取任务。形式:, (*12)
③返回\"reset\"重置任务,任务状态重新设置为0;返回\"ignore\"则先跳过任务,任务状态会保持在1,以后再处理, (*13)
onSuccessWithUnexpectedCode, (*14)
返回\"reset\"重置任务,任务状态重新设置为0, (*15)
onFail, (*16)
监视器对监视任务表中的任务进行监视(周期抓取),抓取成功后调用回调函数,回调函数中对页面是否更新进行判断。, (*17)
返回数组(形式同onSuccess的返回值)则向抓取任务表中追加新的任务(任务级别加1),返回true则更新抓取任务表中与当前监视任务对应的任务为未抓取(0)状态以便再次抓取。, (*18)
针对每个抓取的目标网站建立一个历史url集合,对即将添加到抓取任务表的url判断是否在这个集合中,没在才添加,并将这个新的url加入到集合中。, (*19)
技术上采用布隆过滤器(bloomfilter):时间和空间效率极高,有误判“结果在集合中,但实际不在集合中”,“结果不在集合中,实际也一定不在集合中”。所以使用bloomfilter最大的损失也就是有一些页面漏抓而已,这是完全可以承受的。, (*20)
项目地址: https://github.com/pleonasm/bloom-filter 使用时直接参考即可, (*21)
如果每次创建布隆过滤器对象都通过历史url表,当数据量特别大的时候整个过程会非常慢,而且很占内存。此时可考虑使用布隆过滤器缓存文件,如果缓存文件存在,则用缓存文件创建对象,否则还是通过历史url表创建对象。, (*22)
注意:①缓存文件只适用于单进程,否则多个进程之间会相互覆盖②如果程序异常终止或强制终止,缓存文件会和历史url表不一致,此时应该手动删除缓存文件以便生成新的缓存文件, (*23)
$config=[
//创建布隆过滤器时使用的预估条目数(确保添加到布隆过滤器中的条目数小于这个值)
'item_num'=>1000000,
//创建布隆过滤器时使用的误判几率
'probability'=>0.0001,
//无视布隆过滤器,开启时添加任务到任务表不会受到布隆过滤器的阻止
'ignore_bf'=>false,
//是否使用布隆过滤器缓存文件
'use_bf_cache_file'=>false,
//布隆过滤器缓存文件的路径
'bf_cache_file_path'=>'/home/data_bf',
//是否启用tor代理,必须保证当前环境已经创建了若干tor代理进程
'use_tor'=>false,
//tor代理进程的端口号和pid的映射数组 key是端口号 value是进程id
//形如 [20001=>1234,20002=>1235,20003=>1236,......]
'tor_ports_pids'=>[],
//爬取失败重试次数
'retry'=>1,
//线程数
'thread_num'=>15,
//是否开启守护模式,周期性从抓取任务表中取任务进行抓取
'daemon'=>false,
//开启守护模式后间隔多少秒尝试进行一次爬取
'daemon_interval'=>86400,
//监视器时间间隔
'monitor_interval'=>43200,
//是否随机用户代理字符串
'random_user_agent'=>false,
//预定义的一系列用户代理字符串
'user_agent'=>
[ ],
//curl默认选项
'curl_opt'=>
[
CURLOPT_RETURNTRANSFER => true, //抓取结果作为字符串返回,不输出到页面
CURLOPT_CONNECTTIMEOUT => 60, //连接60秒超时
CURLOPT_TIMEOUT => 120, //函数执行120秒超时
CURLOPT_FOLLOWLOCATION => true, //跟踪重定向
//设置Accept-Encoding请求头。同时能对压缩的响应内容解码
CURLOPT_ENCODING => 'gzip, deflate',
//设置用户代理字符串
//百度蜘蛛 Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)
//谷歌机器人 Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
CURLOPT_HEADEROPT => CURLHEADER_UNIFIED, //向目标服务器和代理服务器的请求都使用CURLOPT_HTTPHEADER定义的请求头
//构建更加真实的请求头
CURLOPT_HTTPHEADER=> [
'Connection: close',
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Upgrade-Insecure-Requests: 1',
'Accept-Language: en-US,en;q=0.9,de;q=0.8,ja;q=0.7,ru;q=0.6,zh-CN;q=0.5,zh;q=0.4',
'Cache-Control: no-cache',
],
/*设置代理*/
//CURLOPT_PROXYTYPE=>CURLPROXY_HTTP,//设置代理类型CURLPROXY_HTTP或CURLPROXY_SOCKS5
//CURLOPT_PROXY=>'127.0.0.1:1080',//设置代理的ip地址和端口号
/*抓取https页面必要*/
//CURLOPT_SSL_VERIFYPEER=>true,
//CURLOPT_CAINFO=>'/home/cacert.pem',
//CURLOPT_SSL_VERIFYHOST=>2,
],
//默认数据库配置
'database'=>
[
//服务器地址
'host'=>'',
//用户名
'username'=>'',
//密码
'password'=>'',
//端口
'port'=>3306,
]
]
__construct(), (*24)
创建FatGoose对象,参数依次为数据库名、任务表名、历史表名、监视表名、配置选项数组, (*25)
setCallbacksArr(), (*26)
设置抓取回调函数数组。此数组的格式为, (*27)
/*
[
['0级抓取成功的回调函数','0级抓取成功但状态码有问题的回调函数','0级抓取失败的回调函数'],//0级任务回调函数
['1级抓取成功的回调函数','1级抓取成功但状态码有问题的回调函数','1级抓取失败的回调函数'],//1级任务回调函数
......
...... 以此类推可以无限级
]
*/
setMonitorCallbacksArr(), (*28)
设置监视回调函数数组。此数组的格式为, (*29)
/* [0级监视任务成功的回调函数,1级监视任务成功的回调函数,2级监视任务成功的回调函数......] */
addTask(), (*30)
用于添加抓取任务,第一个参数是任务数组,第二个参数是否忽略布隆过滤器(默认false)。任务数组的格式为, (*31)
/* [ [[url,extraInfo],level],[[url,extraInfo],level],...... ] 或 [ [url,level],[url,level],...... ] 样的形式则默认extraInfo为null */
registerFuncExtraCurlOpt(), (*32)
注册一个回调函数,自动传入自定义信息数组的引用,此回调函数在创建每个curl资源的时候都会调用, (*33)
这个回调函数可以(1)用返回值设置额外的或覆盖已存在的curl选项(2)往自定义信息数组里面注入额外信息, (*34)
此回调函数大致结构如下,特别要注意参数是引用传递, (*35)
/*
function(&$customInfoArr)
{
...
$customInfoArr['sum']=10000; 注入了额外信息
...
return [CURLOPT_PROXYTYPE=>CURLPROXY_HTTP,CURLOPT_PROXY=>'127.0.0.1:1080']; 设置额外的curl选项
}
*/
run(), (*36)
开始爬取, (*37)
monitor(), (*38)
开始监视, (*39)
静态方法 mCrawl(), (*40)
多线程异步爬虫,此方法功能有所简化,主要用于简单的抓取和抓取测试。传入的参数依次为,待抓取的页面(字符串或数组)、抓取成功的回调函数、响应状态码预期外的回调函数、抓取失败的回调函数、线程数、重试次数、抓取选项数组, (*41)
静态方法 absoluteUrl(), (*42)
相对url转绝对url。传入的参数依次为,待转换的url(字符串或数组)、参照url,如果是目录后面带上/, (*43)
静态方法 customArrayMerge(), (*44)
将第二个数组的数组项合并到第一个数组中,有则覆盖,无则追加,并且实现递归。, (*45)
php爬虫
Apache-2.0
php crawl