AdvertCN - 广告中国

 找回密码
 立即注册

QQ登录

只需一步,快速开始

Binom
 谷歌+Bing+TT+MSN官方代理 
⚡️按条S5代理⚡️静态⚡️独享⚡️5G⚡️最干净<Wifi住宅+5G移动>IP代理指纹浏览器,就用AdsPower
Mediabuy⚡️玩家开户首选【鲁班跨境通-自助充值转账】FB/GG/TT❤️官方免费开户Affiliate 全媒体流量资源⚡️
Taboola/Outbrain /Bing⚡️一级代理开户投流-7*24h❤️人工在线【官方】❤️搜索套利广告开户独立站⚡️开户投放
DuoPlus专注打造跨境电商云手机E.PN 虚拟卡BINOM TRACKER 60% OFF!比Adplexity还好用的Spy工具
MediaGo+Taboola+Ob开户百度国际MediaGo⚡️让产品狂奔全球百度国际,高点击转化,快速放量百度国际MediaGo,独家原生流量
ADPLEXITY + ADVERTCN7200W全球动态不重复住宅IP代理虚拟信用卡+独立站收款全球虚拟卡, 支持U充值
Facebook 批量上广告尤里改 - FB 稳定投放免费黑五教程(持续更新、欢迎交流)FB 三不限源头 - 自助下户充值转款
各种主页、账单户、BM户(优势)⚡️个人户,bm户不限额,账单户一手BM分享户不限额9Proxy ⚡️ $0.04/IP, 无限带宽
FB二三解0.1元一个虚拟卡|PTM星际卡FB专用虚拟卡Google、Bing官方总代  联盟流量开户
FB账号资源/稳定靠谱/运行5年啦FB开户代投/三不限/白名单fb耐用号0.01一个fb账号官方合作商
广告位出租   
查看: 9366|回复: 13

分享我经常用的 php多线程源码 批量抓取内容的方法

[复制链接]

13

主题

276

广告币

434

积分

中级会员

Rank: 3Rank: 3

积分
434

社区QQ达人

QQ
发表于 2013-4-14 03:37:23 | 显示全部楼层 |阅读模式
  1. <?php
  2. class Http_MultiRequest
  3. {
  4.     //要并行抓取的url 列表
  5.     private $urls = array();

  6.     //curl 的选项
  7.     private $options;
  8.    
  9.     //构造函数
  10.     function __construct($options = array())
  11.     {
  12.         $this->setOptions($options);
  13.     }

  14.     //设置url 列表
  15.     function setUrls($urls)
  16.     {
  17.         $this->urls = $urls;
  18.         return $this;
  19.     }


  20.     //设置选项
  21.     function setOptions($options)
  22.     {
  23.         $options[CURLOPT_RETURNTRANSFER] = 1;
  24.         if (isset($options['HTTP_POST']))
  25.         {
  26.             curl_setopt($ch, CURLOPT_POST, 1);
  27.             curl_setopt($ch, CURLOPT_POSTFIELDS, $options['HTTP_POST']);
  28.             unset($options['HTTP_POST']);
  29.         }

  30.         if (!isset($options[CURLOPT_USERAGENT]))
  31.         {
  32.             $options[CURLOPT_USERAGENT] = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)';
  33.         }

  34.         if (!isset($options[CURLOPT_FOLLOWLOCATION]))
  35.         {
  36.             $options[CURLOPT_FOLLOWLOCATION] = 1;
  37.         }

  38.         if (!isset($options[CURLOPT_HEADER]))
  39.         {
  40.             $options[CURLOPT_HEADER] = 0;
  41.         }
  42.         $this->options = $options;
  43.     }

  44.     //并行抓取所有的内容
  45.     function exec()
  46.     {
  47.         if(empty($this->urls) || !is_array($this->urls))
  48.         {
  49.             return false;
  50.         }
  51.         $curl = $data = array();
  52.         $mh = curl_multi_init();
  53.         foreach($this->urls as $k => $v)
  54.         {
  55.             $curl[$k] = $this->addHandle($mh, $v);
  56.         }
  57.         $this->execMulitHandle($mh);
  58.         foreach($this->urls as $k => $v)
  59.         {
  60.             $data[$k] = curl_multi_getcontent($curl[$k]);
  61.             curl_multi_remove_handle($mh, $curl[$k]);
  62.         }
  63.         curl_multi_close($mh);
  64.         return $data;
  65.     }
  66.    
  67.     //只抓取一个网页的内容。
  68.     function execOne($url)
  69.     {
  70.         if (empty($url)) {
  71.             return false;
  72.         }
  73.         $ch = curl_init($url);
  74.         $this->setOneOption($ch);
  75.         $content = curl_exec($ch);
  76.         curl_close($ch);
  77.         return $content;
  78.     }
  79.    
  80.     //内部函数,设置某个handle 的选项
  81.     private function setOneOption($ch)
  82.     {
  83.         curl_setopt_array($ch, $this->options);
  84.     }

  85.     //添加一个新的并行抓取 handle
  86.     private function addHandle($mh, $url)
  87.     {
  88.         $ch = curl_init($url);
  89.         $this->setOneOption($ch);
  90.         curl_multi_add_handle($mh, $ch);
  91.         return $ch;
  92.     }

  93.     //并行执行(这样的写法是一个常见的错误,我这里还是采用这样的写法,这个写法
  94.     //下载一个小文件都可能导致cup占用100%, 并且,这个循环会运行10万次以上
  95.     //这是一个典型的不懂原理产生的错误。这个错误在PHP官方的文档上都相当的常见。)
  96.     private function execMulitHandle2($mh)
  97.     {
  98.         $running = null;
  99.         do {
  100.             curl_multi_exec($mh, $running);
  101.         } while ($running > 0);
  102.     }
  103.     //应该用这样的写法
  104.     private function execMulitHandle($mh){
  105.       $i = 0;
  106.       do {$mrc = curl_multi_exec($mh,$active); $i++;} while ($mrc == CURLM_CALL_MULTI_PERFORM);
  107.       while ($active && $mrc == CURLM_OK){
  108.         if (curl_multi_select($mh) != -1){
  109.             do {$mrc = curl_multi_exec($mh, $active); $i++;} while ($mrc == CURLM_CALL_MULTI_PERFORM);
  110.         }
  111.         $i++;
  112.       }
  113.       //var_dump($i);
  114.     }
  115. }

  116. /*下面是上面的类的一个测试的例子:*/

  117. $urls = array("http://baidu.com", "http://baidu.com", "http://baidu.com", "http://baidu.com", "http://baidu.com", "http://baidu.com", "http://www.google.com", "http://www.sina.com.cn", );
  118. $m = new Http_MultiRequest();

  119. $t = microtime(true);
  120. $m->setUrls($urls);

  121. //parallel fetch(并行抓取):
  122. $data = $m->exec();
  123. $parallel_time = microtime(true) - $t;
  124. echo $parallel_time . "\n";

  125. $t = microtime(true);

  126. //serial fetch(串行抓取):
  127. foreach ($urls as $url)
  128. {
  129.     $data[] = $m->execOne($url);
  130. }
  131. $serial_time = microtime(true) - $t;
  132. echo $serial_time . "\n";
  133. ?>
复制代码
相关帖子
回复

使用道具 举报

1618

主题

2万

广告币

2万

积分

管理员

宇宙无敌河马天神

Rank: 9Rank: 9Rank: 9

积分
29619

社区QQ达人

发表于 2013-4-14 04:00:21 | 显示全部楼层
学会提问的艺术, 从小处入手, 忌大而空
AdvertCN电报群

我最喜欢用的工具
7200W全球动态不重复住宅IP代理
回复 支持 反对

使用道具 举报

2

主题

27

广告币

139

积分

初级会员

Rank: 2

积分
139
发表于 2013-4-14 08:58:55 | 显示全部楼层
有个rollingurl是非block模式的
回复 支持 反对

使用道具 举报

43

主题

1107

广告币

1473

积分

高级会员

Rank: 4

积分
1473

社区QQ达人

发表于 2013-4-14 09:55:38 | 显示全部楼层
河小马 发表于 2013-4-14 04:00
多线程差不多都是用curl

因为最需要用到多线程的就是网络访问,等待响应有时候是个漫长的过程。。。
回复 支持 反对

使用道具 举报

21

主题

678

广告币

893

积分

中级会员

Rank: 3Rank: 3

积分
893

社区QQ达人

发表于 2013-4-14 11:14:31 | 显示全部楼层
http://code.google.com/p/rolling-curl/source/checkout

rolling curl的源码地址,要svn checkout下来的
回复 支持 反对

使用道具 举报

4

主题

144

广告币

173

积分

初级会员

Rank: 2

积分
173

社区QQ达人

发表于 2013-4-14 13:00:38 | 显示全部楼层
不错哦,用来升级一下我的代码,之前自己写得很简单的
亿爸爸SEO
回复 支持 反对

使用道具 举报

13

主题

276

广告币

434

积分

中级会员

Rank: 3Rank: 3

积分
434

社区QQ达人

QQ
 楼主| 发表于 2013-4-15 20:28:58 | 显示全部楼层
luguo 发表于 2013-4-14 08:58
有个rollingurl是非block模式的

Rolling cURL 并发机制真的挺不错啊  thanks luguo
回复 支持 反对

使用道具 举报

2

主题

27

广告币

139

积分

初级会员

Rank: 2

积分
139
发表于 2013-4-16 10:25:14 | 显示全部楼层
光大 发表于 2013-4-15 20:28
Rolling cURL 并发机制真的挺不错啊  thanks luguo

其实就多了一个callback呗
回复 支持 反对

使用道具 举报

0

主题

3

广告币

20

积分

初级会员

Rank: 2

积分
20
发表于 2013-4-23 12:38:35 | 显示全部楼层
学习下,,, 对这方面认识不够  
回复 支持 反对

使用道具 举报

4

主题

0

广告币

9

积分

禁止发言

积分
9

社区QQ达人

发表于 2013-9-4 13:46:17 | 显示全部楼层
增长了见识了呵呵呵
回复 支持 反对

使用道具 举报

19

主题

290

广告币

532

积分

中级会员

Rank: 3Rank: 3

积分
532

社区QQ达人

发表于 2013-9-18 17:44:49 | 显示全部楼层
还是不太习惯
以前没用过curl的multi
内容少点,确实可以用这个,东西多了我还是倾向于消息队列,更稳定些
回复 支持 反对

使用道具 举报

1

主题

12

广告币

91

积分

初级会员

Rank: 2

积分
91
发表于 2013-9-22 18:01:32 | 显示全部楼层
php网络操作效率太差,换个别的语言实现吧
回复 支持 反对

使用道具 举报

12

主题

128

广告币

318

积分

初级会员

Rank: 2

积分
318

社区QQ达人

发表于 2013-11-21 17:03:55 | 显示全部楼层

学习了
回复 支持 反对

使用道具 举报

3

主题

902

广告币

1942

积分

高级会员

Rank: 4

积分
1942

社区QQ达人

发表于 2015-10-12 15:57:10 | 显示全部楼层
pthreads 也非常不错
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们|联系我们|DMCA|广告服务|小黑屋|手机版|Archiver|Github|网站地图|AdvertCN

GMT+8, 2024-11-21 23:46 , Processed in 0.051991 second(s), 14 queries , Gzip On, MemCache On.

Copyright © 2001-2023, AdvertCN

Proudly Operating in Hong Kong.

快速回复 返回顶部 返回列表