AdvertCN - 广告中国

 找回密码
 立即注册

QQ登录

只需一步,快速开始

 谷歌+Bing+TT+MSN官方代理 
⚡️按条S5代理⚡️静态⚡️独享⚡️5G⚡️最干净<Wifi住宅+5G移动>IP代理泰国仓储,本土仓发货2-3元/单
指纹浏览器,就用AdsPower谷歌/FB/Bing/Yahoo代理商开户7200W全球动态不重复住宅IP代理全球优质流量,选TrafficStars
出售Facebook,友缘号,FB广告号,insFB/TT/KW 加白开户ADPLEXITY + ADVERTCN比Adplexity还好用的Spy工具
广
FB/Google/TK海外多媒体极速下户
BINOM TRACKER 60% OFF!MediaGo+Taboola+Ob开户百度国际MediaGo⚡️让产品狂奔全球百度国际,高点击转化,快速放量
百度国际MediaGo,独家原生流量虚拟信用卡+独立站收款行业首创新型指纹Cloak, 谷歌奇效!Kookeey⚡️100%独享⚡️原生住宅IP
⚡IPFoxy住宅代理全场88折⚡全球虚拟卡, 支持U充值免账户投放 FB 广告(送项目)2024做什么 - Media buy 项目库
免费黑五教程(持续更新、欢迎交流)Facebook 批量上广告Bridgeway - 联盟营销网络IPCola 全新住宅代理 ⚡️ 免费试用
各种主页、账单户、BM户(优势)⚡️个人户,bm户不限额,账单户Adsterra 的CPA/CPM/CPC 网站流量在线注册美国/英国/香港等海外公司
EU KETO/CBD - JumbleberryFB二三解1元/个9Proxy ⚡️ $0.04/IP, 无限带宽 cloak斗篷/ss/nutra/cpa/Dating
E.PN 虚拟卡Asocks代理服务器$3/GB高薪诚求实力FB投手(独立站)《全新虚拟卡+全球收付款》
广告位出租全球低价纯净住宅/移动IP-免费试用广告代投, 东南亚物流, 虚拟信用卡VMLogin指纹浏览器+多账号防关联
查看: 8642|回复: 13

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

[复制链接]

13

主题

276

广告币

434

积分

中级会员

Rank: 3Rank: 3

积分
434

社区QQ达人

QQ
发表于 2013-4-14 03:37:23 | 显示全部楼层 |阅读模式
adsterra
  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. ?>
复制代码
相关帖子
回复

使用道具 举报

1601

主题

1万

广告币

2万

积分

管理员

宇宙无敌河马天神

Rank: 9Rank: 9Rank: 9

积分
28696

社区QQ达人

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

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

使用道具 举报

2

主题

27

广告币

139

积分

初级会员

Rank: 2

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

使用道具 举报

42

主题

1049

广告币

1408

积分

高级会员

Rank: 4

积分
1408

社区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

主题

141

广告币

169

积分

初级会员

Rank: 2

积分
169

社区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

主题

289

广告币

531

积分

中级会员

Rank: 3Rank: 3

积分
531

社区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

主题

782

广告币

1820

积分

高级会员

Rank: 4

积分
1820

社区QQ达人

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-25 12:15 , Processed in 0.058246 second(s), 13 queries , Gzip On, MemCache On.

Copyright © 2001-2023, AdvertCN

Proudly Operating in Hong Kong.

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