PHP 利用 Curl 可以完成各种传送文件操作,比如模拟浏览器发送GET,POST请求等等。

然而因为php语言本身不支持多线程,所以开发爬虫程序效率并不高,一般采集数据可以利用 phpQuery类来采集数据库,

在此之外也可以用 Curl ,借助Curl 这个功能实现并发多线程的访问多个url地址以实现并发多线程抓取网页或者下载文件。

如果需要了解curl所有函数可以看这里:函数列表查看

下面是多线程使用到的curl相关函数:

curl_multi_add_handle — 向curl批处理会话中添加单独的curl句柄

curl_multi_close — 关闭一组cURL句柄

curl_multi_exec — 运行当前 cURL 句柄的子连接

curl_multi_getcontent — 如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流

curl_multi_info_read — 获取当前解析的cURL的相关传输信息

curl_multi_init — 返回一个新cURL批处理句柄

curl_multi_remove_handle — 移除curl批处理句柄资源中的某个句柄资源

curl_multi_select — 等待所有cURL批处理中的活动连接

curl_multi_setopt — 为 cURL 并行处理设置一个选项

curl_multi_strerror — Return string describing error code

实现步骤如下:

1、调用 curl_multi_init,初始化一个批处理handle
2、循环调用 curl_multi_add_handle,往1中的批处理handle 添加curl_init来的子handle
3、持续调用 curl_multi_exec,直到所有子handle执行完毕。
4、根据需要循环调用 curl_multi_getcontent 获取结果
5、调用 curl_multi_remove_handle,并为每个字handle调用curl_close
6、调用 curl_multi_close

一般来说,使用多线程curl获取网页源码或下载图片等都是针对多个网址操作的,而不是每次都请求一次,那不如去循环 curl_exec。

接下来直接放封装好的函数:

/*多线程获取网页源码@param array $urls@return array
*/function curl_multi($urls)
{if (!is_array($urls) or count($urls) == 0) {return false;}$num = count($urls);$curl = $curl2 = $text = array();$handle = curl_multi_init();function createCh($url){$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Linux; U; Android 4.4.1; zh-cn; R815T Build/JOP40D) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/4.5 Mobile Safari/533.1');//设置头部curl_setopt($ch, CURLOPT_REFERER, $url); //设置来源curl_setopt($ch, CURLOPT_ENCODING, "gzip"); // 编码压缩curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //是否采集301、302之后的页面curl_setopt($ch, CURLOPT_MAXREDIRS, 5); //查找次数,防止查找太深curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // 对认证证书来源的检查curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // 从证书中检查SSL加密算法是否存在curl_setopt($ch, CURLOPT_TIMEOUT, 20);curl_setopt($ch, CURLOPT_HEADER, 0); //输出头部return $ch;}//准备分配线程foreach ($urls as $k => $v) {$url = $urls[$k];$curl[$k] = createCh($url);//向curl批处理会话中添加单独的curl句柄curl_multi_add_handle($handle, $curl[$k]);}$active = null;do {//运行当前 cURL 句柄的子连接$mrc = curl_multi_exec($handle, $active);} while ($mrc == CURLM_CALL_MULTI_PERFORM);while ($active && $mrc == CURLM_OK) {//等待所有cURL批处理中的活动连接if (curl_multi_select($handle) != -1) {usleep(100);}do {//运行当前 cURL 句柄的子连接$mrc = curl_multi_exec($handle, $active);} while ($mrc == CURLM_CALL_MULTI_PERFORM);}foreach ($curl as $k => $v) {if (curl_error($curl[$k]) == "") {//如果没有报错则将获取到的字符串添加到数组中$text[$k] = (string) curl_multi_getcontent($curl[$k]);}//移除并关闭curl该句柄资源curl_multi_remove_handle($handle, $curl[$k]);curl_close($curl[$k]);}//关闭cURL句柄curl_multi_close($handle);//将数组返回return $text;
}

函数的使用示例:

<?php$arr=['http://baidu.com','http://taobao.com','http://jd.com','http://wslmf.com'];$res=curl_multi($arr);var_dump($res);

到这里基本就结束了。此外,继续简单的封装了单线程 curl 访问(等同于file_get_contents)一样的函数:

/*访问网站源码@param string $url@return string
*/function curl_get($url)
{$ch = curl_init($url);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Linux; U; Android 4.4.1; zh-cn; R815T Build/JOP40D) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/4.5 Mobile Safari/533.1');curl_setopt($ch, CURLOPT_TIMEOUT, 10);$content = curl_exec($ch);curl_close($ch);return ($content);
}

最后,大家尽可能使用curl去爬取网站,因为 file_get_contents 效率太低了,curl 大概能提升 40%

curl 伪造 ip 方法及可选 post/get 提交方式

/*** 请求html页面源码接口数据方法* @param string $url 请求地址* @param int 访问方式 1:post  0:get 默认 get方式* @param string 上传文件* @param string cookie文件* @param bool 请求头* @return string 数据*/function getHtml($url, $ifpost = 0, $datafields = '', $cookiefile = '', $v = false){// 伪造IP$xforip = rand(1, 254) . "." . rand(1, 254) . "." . rand(1, 254) . "." . rand(1, 254);$header = array("Connection: Keep-Alive", "Accept: application/json, text/javascript, */*; q=0.01", "Pragma: no-cache", "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3", "User-Agent: Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14", 'CLIENT-IP:' . $xforip, 'X-FORWARDED-FOR:' . $xforip); // 请求头信息$ch = curl_init();// 使用伪造代理IPcurl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_HEADER, $v);curl_setopt($ch, CURLOPT_HTTPHEADER, $header);$ifpost && curl_setopt($ch, CURLOPT_POST, $ifpost);$ifpost && curl_setopt($ch, CURLOPT_POSTFIELDS, $datafields);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');$cookiefile && curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);$cookiefile && curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile);$r = curl_exec($ch);curl_close($ch);return $r;}

PHP CURL实现单线程、多线程方法相关推荐

  1. 单线程-多线程-高并发

    什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又是由多个线程所组成的. 什么是线程? 线程是程序中的一个执行流,每个线程都有自己的 ...

  2. Python|并发编程|爬虫|单线程|多线程|异步I/O|360图片|Selenium及JavaScript|Scrapy框架|BOM 和 DOM 操作简介|语言基础50课:学习(12)

    文章目录 系列目录 原项目地址 第37课:并发编程在爬虫中的应用 单线程版本 多线程版本 异步I/O版本 总结 第38课:抓取网页动态内容 Selenium 介绍 使用Selenium 加载页面 查找 ...

  3. 同步异步单线程多线程初级理解

    对于我开始接触同步异步单线程多线程的概念的时候,都是分别理解同步和异步.单线程和多线程概念,当看到"使用同步方法保证线程安全"时愚昧的理解为那就是单线程咯:于是就陷入了困惑,同步等 ...

  4. php curl 下载图片 花,PHP curl下载图片的方法

    PHP curl下载图片的方法 $images = [ 'http://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKPkia3rxjuBoSQ1sUSmqYXDazibuI ...

  5. curl命令php,php生成curl命令行的方法

    本文实例讲述了php生成curl命令行的方法.分享给大家供大家参考,具体如下: 示例: curl "http://localhost/other/serverInfo.php?dd=ddd& ...

  6. QSerialport多线程方法

    QSerialport多线程方法 使用Qt也已经有一段时间了,虽然使用过继承QThread重写run函数,以及继承QObject然后使用MoveToThread两种方法实现多线程,但是在QSerial ...

  7. php curl修改ip,php中curl设置ip的方法

    php中curl设置ip的方法 发布时间:2020-08-28 09:44:57 来源:亿速云 阅读:84 作者:小新 php中curl设置ip的方法?这个问题可能是我们日常学习或工作经常见到的.希望 ...

  8. php采集单线程卡死,php - 为什么我这段curl采集,单线程比多线程还快?

    我这里写了个简单的curl采集,但是执行后发现单线程执行的方式比多线程执行要快很多. 是我的写法又问题吗? $images = [ "http://pic.91taojin.com.cn/d ...

  9. 简谈单线程多线程的理解

    JS的单线程 JS语言的特点之一就是单线程,简而言之就是同一时间只能做一件事,假设JS是多线程,一个线程在某个节点上添加内容,另一个线程删除了这个节点,这时就看到了问题所在了,但是H5提出了Web W ...

最新文章

  1. 最短路径 - dijkstra
  2. CS专业读PhD是否有意义?附CS奖学金项目清单
  3. Eclipse遇到的错误
  4. windows下配置ssh(FreeSSHD + putty)
  5. 泊松方程与拉普拉斯方程数值解
  6. Graph Attention Networks
  7. java当中递归打印目录树
  8. 前端学习(3183):ant-design的button介绍按钮属性
  9. 第四章语法分析和语法分析程序
  10. (转)Spring的bean管理(注解方式)
  11. python 简单检索器_python实现文件搜索工具(简易版)
  12. layer mvc json 中文乱码处理
  13. thinkphp5 图片压缩旋转_26套经典压缩机结构设计:有多少人知道内部结构是这样的...
  14. 电商直播数据的简单总结
  15. devc语言图形编程教程_C语言编程工具:Dev - C++ 简单安装和使用!新手福利!
  16. 抖音seo源码,抖音seo矩阵系统源码技术搭建
  17. 数据库系统(软件设计师备考笔记)
  18. python词云库——wordcloud
  19. Verilog数字系统基础设计-数据转换器
  20. 工具管理(资源管理)

热门文章

  1. 遥感影像波段与波段合成
  2. css+js解决文本两端对齐以及分散对齐
  3. Maven 中跳过单元测试方法
  4. 如何学习爬虫技术(问答版)
  5. 功能点算法及在软件测试中的应用Part3
  6. 企业对接钉钉流程(企业内部应用-H5)
  7. 第2章 C语言的数值数据与非数值数据 (二)
  8. Firefly ROC-RK3588S-PC板卡详细介绍
  9. android fuse 检测原理,fuse 原理总结
  10. git 和 phabricator arc 常用 命令解析