1. 程式人生 > >qq群裡分享的一個不錯的curl多執行緒處理抓取網頁資訊類

qq群裡分享的一個不錯的curl多執行緒處理抓取網頁資訊類

<?php
// +----------------------------------------------------------------------
// | Leaps Framework [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2011-2014 Leaps Team (http://www.tintsoft.com)
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author XuTongle <
[email protected]
> // +---------------------------------------------------------------------- namespace Leaps\HttpClient\Adapter; use Leaps\HttpClient\MimeType; class Curl extends \Leaps\HttpClient\Adapter implements \Leaps\HttpClient\AdapterInterface { /** * 設定認證帳戶和密碼 * * @param string $username * @param string $password */ public function setAuthorization($username, $password) { $this->authorizationToken = "[$username]:[$password]"; } /** * 設定curl引數 * * @param string $key * @param value $value * @return \Leaps\HttpClient\Adapter\Curl */ public function setOption($key, $value) { if ($key === CURLOPT_HTTPHEADER) { $this->header = array_merge ( $this->header, $value ); } else { $this->option [$key] = $value; } return $this; } /** * 新增上傳檔案 * * @param $file_name string 檔案路徑 * @param $name string 檔名 * @return $this */ public function _addFile($name, $fileName = '', $mimeType = '') { if (class_exists ( '\CURLFile' )) { $this->files [$name] = new \CURLFile ( realpath ( $fileName ), MimeType::getMimeType ( $fileName ), basename ( $fileName ) ); $this->setOption ( CURLOPT_SAFE_UPLOAD, true ); } else { $this->files [$name] = '@' . realpath ( $fileName ); } return $this; } /** * GET方式獲取資料,支援多個URL * * @param string/array $url * @return string, false on failure */ public function getRequest($url) { if ($this->method == 'POST') { $this->setOption ( CURLOPT_POST, true ); } else if ($this->method == 'PUT') { $this->setOption ( CURLOPT_PUT, true ); } else if ($this->method) { $this->setOption ( CURLOPT_CUSTOMREQUEST, $this->method ); } if (is_array ( $url )) { $data = $this->requestUrl ( $url ); $this->reset (); return $data; } else { $data = $this->requestUrl ( [ $url ] ); $this->reset (); return $data; // [$url]; } } /** * 用POST方式提交,支援多個URL $urls = array ( 'http://www.baidu.com/', * 'http://mytest.com/url', * 'http://www.abc.com/post', ); $data = array ( * array('k1'=>'v1','k2'=>'v2'), * array('a'=>1,'b'=>2), 'aa=1&bb=3&cc=3', ); * * @param $url * @param string/array $vars * @return string, false on failure */ public function postRequest($url, $vars) { // POST模式 $this->setMethod ( 'POST' ); $this->setOption ( CURLOPT_HTTPHEADER, [ 'Expect:' ] ); if (is_array ( $url )) { $myVars = [ ]; foreach ( $url as $k => $u ) { if (isset ( $vars [$k] )) { if (! is_array ( $vars [$k] )) { parse_str ( $vars [$k], $tmp ); $vars [$k] = $tmp; } $myVars [$u] = $vars [$k]; if ($this->files) { $myVars [$u] = array_merge ( $myVars [$u], $this->files ); } } } } else { if (! is_array ( $vars )) { parse_str ( $vars, $tmp ); $vars = $tmp; } if ($this->files) { $vars = array_merge ( $vars, $this->files ); } $myVars [$url] = $vars; } $this->postData = $myVars; return $this->getRequest ( $url ); } /** * PUT方式獲取資料,支援多個URL * * @param string/array $url * @param string/array $vars * @return string, false on failure */ public function putRequest($url, $vars) { $this->setMethod ( 'PUT' ); $this->setOption ( CURLOPT_HTTPHEADER, [ 'Expect:' ] ); if (is_array ( $url )) { $myvars = [ ]; foreach ( $url as $k => $u ) { if (isset ( $vars [$k] )) { if (! is_array ( $vars [$k] )) { parse_str ( $vars [$k], $tmp ); $vars [$k] = $tmp; } $myvars [$u] = $vars [$k]; } } } else { if (! is_array ( $vars )) { parse_str ( $vars, $tmp ); $vars = $tmp; } $myvars [$url] = $vars; } $this->postData = $myvars; return $this->getRequest ( $url ); } /** * DELETE方式獲取資料,支援多個URL * * @param string/array $url * @return string, false on failure */ public function deleteRequest($url) { $this->setMethod ( 'DELETE' ); $this->getRequest ( $url ); } /** * 建立一個CURL物件 * * @param string $url URL地址 * @param int $timeout 超時時間 * @return curl_init() */ public function _create($url) { $matches = parse_url ( $url ); $host = $matches ['host']; if ($this->hostIp) { $this->header [] = 'Host: ' . $host; $url = str_replace ( $host, $this->hostIp, $url ); } $ch = curl_init (); curl_setopt ( $ch, CURLOPT_URL, $url ); curl_setopt ( $ch, CURLOPT_HEADER, true ); // 抓取跳轉後的頁面 curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, true ); curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true ); curl_setopt ( $ch, CURLOPT_ENCODING, 'gzip, deflate' ); curl_setopt ( $ch, CURLOPT_TIMEOUT, $this->timeout ); curl_setopt ( $ch, CURLOPT_CONNECTTIMEOUT_MS, $this->connectTimeout ); if (! is_null ( $this->authorizationToken )) { // 認證 curl_setopt ( $ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ); curl_setopt ( $ch, CURLOPT_USERPWD, $this->authorizationToken ); } if ($matches ['scheme'] == 'https') { curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, false ); curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false ); } if (! empty ( $this->proxyHost ) && ! empty ( $this->proxyPort )) { curl_setopt ( $ch, CURLOPT_PROXY, $this->proxyHost ); curl_setopt ( $ch, CURLOPT_PROXYPORT, $this->proxyPort ); } if ($this->cookie) { if (is_array ( $this->cookie )) { curl_setopt ( $ch, CURLOPT_COOKIE, http_build_query ( $this->cookie, '', ';' ) ); } else { curl_setopt ( $ch, CURLOPT_COOKIE, $this->cookie ); } } if ($this->referer) { curl_setopt ( $ch, CURLOPT_REFERER, $this->referer ); } else { curl_setopt ( $ch, CURLOPT_AUTOREFERER, true ); } if ($this->userAgent) { curl_setopt ( $ch, CURLOPT_USERAGENT, $this->userAgent ); } elseif (array_key_exists ( 'HTTP_USER_AGENT', $_SERVER )) { curl_setopt ( $ch, CURLOPT_USERAGENT, $_SERVER ['HTTP_USER_AGENT'] ); } else { curl_setopt ( $ch, CURLOPT_USERAGENT, "PHP/" . PHP_VERSION . " HttpClient/1.2.5" ); } foreach ( $this->option as $k => $v ) { curl_setopt ( $ch, $k, $v ); } if ($this->header) { $header = [ ]; foreach ( $this->header as $item ) { // 防止有重複的header if (preg_match ( '#(^[^:]*):.*$#', $item, $m )) { $header [$m [1]] = $item; } } curl_setopt ( $ch, CURLOPT_HTTPHEADER, array_values ( $header ) ); } // 設定POST資料 if (isset ( $this->postData [$url] )) { print_r ( $this->postData ); curl_setopt ( $ch, CURLOPT_POSTFIELDS, $this->postData [$url] ); } return $ch; } /** * 支援多執行緒獲取網頁 * * @see http://cn.php.net/manual/en/function.curl-multi-exec.php#88453 * @param Array/string $urls * @param Int $timeout * @return Array */ public function requestUrl($urls) { // 去重 $urls = array_unique ( $urls ); if (! $urls) return [ ]; $mh = curl_multi_init (); // 監聽列表 $listenerList = [ ]; // 返回值 $result = [ ]; // 總列隊數 $listNum = 0; // 排隊列表 $multiList = [ ]; foreach ( $urls as $url ) { // 建立一個curl物件 $current = $this->_create ( $url ); if ($this->multiExecNum > 0 && $listNum >= $this->multiExecNum) { // 加入排隊列表 $multiList [] = $url; } else { // 列隊數控制 curl_multi_add_handle ( $mh, $current ); $listenerList [$url] = $current; $listNum ++; } $result [$url] = null; $this->httpData [$url] = null; } unset ( $current ); $running = null; // 已完成數 $doneNum = 0; do { //當棧中的控制代碼還有資料需要傳送時,就會返回 CURLM_CALL_MULTI_PERFORM 無資料傳送時候返回 CURLM_OK while ( ($execrun = curl_multi_exec ( $mh, $running )) == CURLM_CALL_MULTI_PERFORM ) ; if ($execrun != CURLM_OK) { break; } //重複呼叫這個函式,它每次都會返回一個新的結果,直到這時沒有更多資訊返回時,FALSE 被當作一個訊號返回。 while ( true == ($done = curl_multi_info_read ( $mh )) ) { foreach ( $listenerList as $doneUrl => $listener ) { if ($listener === $done ['handle']) { // 獲取內容 $this->httpData [$doneUrl] = $this->getData ( curl_multi_getcontent ( $done ['handle'] ), $done ['handle'] ); if ($this->httpData [$doneUrl] ['code'] != 200) { // \Leaps\Debug::error ( 'URL:' . $doneUrl . ' ERROR,TIME:' . $this->httpData [$doneUrl] ['time'] . ',CODE:' . $this->httpData [$doneUrl] ['code'] ); $result [$doneUrl] = false; } else { // 返回內容 $result [$doneUrl] = $this->httpData [$doneUrl] ['data']; // \Leaps\Debug::info ( 'URL:' . $doneUrl . ' OK.TIME:' . $this->httpData [$doneUrl] ['time'] ); } curl_close ( $done ['handle'] ); curl_multi_remove_handle ( $mh, $done ['handle'] ); // 把監聽列表裡移除 unset ( $listenerList [$doneUrl], $listener ); $doneNum ++; // 如果還有排隊列表,則繼續加入 if ($multiList) { // 獲取列隊中的一條URL $currentUrl = array_shift ( $multiList ); // 建立CURL物件 $current = $this->_create ( $currentUrl ); // 加入到列隊 curl_multi_add_handle ( $mh, $current ); // 更新監聽列隊資訊 $listenerList [$currentUrl] = $current; unset ( $current ); // 更新列隊數 $listNum ++; } break; } } } if ($doneNum >= $listNum) break; } while ( true ); // 關閉列隊 curl_multi_close ( $mh ); return $result; } /** * 獲取資料 * * @param unknown $data * @param unknown $ch * @return mixed */ protected function getData($data, $ch) { $headerSize = curl_getinfo ( $ch, CURLINFO_HEADER_SIZE ); $result ['code'] = curl_getinfo ( $ch, CURLINFO_HTTP_CODE ); $result ['data'] = substr ( $data, $headerSize ); $result ['rawHeader'] = substr ( $data, 0, $headerSize ); $result ['header'] = explode ( "\r\n", $result ['rawHeader'] ); $result ['time'] = curl_getinfo ( $ch, CURLINFO_TOTAL_TIME ); return $result; } }

相關推薦

qq分享一個不錯curl執行處理網頁資訊

<?php // +---------------------------------------------------------------------- // | Leaps Framework [ WE CAN DO IT JUST THINK IT ] /

執行快速網頁

一段簡單的程式碼,用於抓取wiki百科資料,簡單的多執行緒程式設計例子,很少佔記憶體,執行緒數開大了後效率很高。import sys, thread, threading, time; import commands finish_num = 0; mutex = thr

用Python BeautifulSoup寫的一份執行圖片的指令碼

最近一個做設計的妹子需要從一個素材的網站(https://www.goodfon.su)下載各種圖片原圖作為設計的素材,但是苦於境外網站,而且只能單張下載,而且單張圖片需要兩個路徑才能到達原圖的下載地址。 幾年沒寫過Python的我決定從操就業幫她寫一份批量下載的指令碼。由於是國外網站

php使用pthreads v3執行新浪新聞資訊

<?php class DB extends Worker { private static $db; private $dsn; private $root; private $pwd; public function __constr

C++:蟻演算法解決TSP(C++執行版)

TSP問題:旅行商問題,最短迴路。 這裡採用att48資料,鄰接矩陣全部取整數,原資料放在文後。 解決程式碼如下: //#define TEST_INPUT //#define TEST_T //#define TEST_ANT //#define TEST_VALUE #

秒殺執行第四篇 一個經典的執行同步問題

上一篇《秒殺多執行緒第三篇原子操作 Interlocked系列函式》中介紹了原子操作在多程序中的作用,現在來個複雜點的。這個問題涉及到執行緒的同步和互斥,是一道非常有代表性的多執行緒同步問題,如果能將這個問題搞清楚,那麼對多執行緒同步也就打下了良好的基礎。程式描述:主執行緒啟

linux下一個程序中執行的資源共享

在說執行緒資源共享之前,我們先來說來說一下執行緒的概念,執行緒是程序內部的一條執行序列(即執行流),一個程序至少有一個執行緒,即main函式代表的執行流。當然我們也可以通過執行緒庫來建立新的執行緒,這種執行緒我們稱之為函式執行緒,同一個程序中的所有普執行緒是併發執行的。而這些

java 執行處理一個list的集合

2016年08月03日 09:16:20 package A; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import j

Java每天一個知識點+Demo-執行相關命令

一 多執行緒相關命令介紹 1 wait()  sleep()  (1)這兩個方法來自不同的類分別是wait()來自Thread,sleep()來自Object。  (2) 最主要是sleep方法沒有釋放鎖,sleep使當前執行緒進入停滯狀態(阻塞當前執行緒),讓出cpu

聊實現(tcp和執行

服務端程式碼 package com.cyj.tcp.chat2; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import ja

PHP Curl執行原理例項詳解

<?php  // 建立一對cURL資源  $ch1 = curl_init();  $ch2 = curl_init();  // 設定URL和相應的選項  curl_setopt($ch1, CURLOPT_URL, "http://www.jb51.net/");  curl_setopt($

執行處理一個list的集合

import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurren

深入理解tomcat是怎樣執行處理http請求並將程式碼執行到controller

徹底理解tomcat是怎樣多執行緒處理的http請求並將程式碼執行到controller裡的 1.執行緒池:thread=threadPool.getThread().thread.executeHttp(httprequest),thread的start方法執行行裡面呼叫

curl執行大批量分片下載大檔案原始碼示例

這段時間,一直在探索使用curl多執行緒來下載一系列的大檔案的可行性方法。下面是我探索的結果: 1.將大檔案分為許多小片段,比如20M一個片段(當然這個值可以配置,比如100M一個片段,取決於你的業務需求),使用http range來下載這些片段; 2.使用預先生成的執行緒

curl執行批量請求

測試經常遇到檢視大資料量URL請求是否正常。單執行緒跑的太慢 可以自定義執行緒數進行跑,細節不多說,其實我也是上網上湊的,拿下來修修改改能用即可。 #!/bin/bash ttime=`date +"%Y-%m-%d %H:%M:%S"` #允許的執行緒數 THREAD_

執行處理慢sql查詢小筆記~

多執行緒處理慢sql查詢以及List(Array)的拆分 系統資料量不大,但是訪問速度特別慢,使用多執行緒優化一下!!! 優化結果:訪問時間縮短了十幾秒  25s --> 8s 一、List的拆分:Iterables.partition 注意: 引入的包為google名下的   &n

HTML5學習之WebWork執行處理

  多執行緒技術在服務端技術中已經發展的很成熟了,而在Web端的應用中卻一直是雞肋 在新的標準中,提供的新的WebWork API,讓前端的非同步工作變得異常簡單。 使用:建立一個Worker物件,指向一個js檔案,然後通過Worker

執行處理list

package com.zhx.web.invoice.service; import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import

python 執行處理佇列

轉載自: https://blog.csdn.net/u011655220/article/details/79037032 from threading import Thread import time import random from queue import Queue from co

[SimplePlayer] 7. 執行處理

在前面的文章中,我們分別實現了視訊影象解碼、播放,音訊解碼、播放,現在則需要把這些功能組合起來。總體上來說,整個程式的功能可以分為兩條線路:視訊以及音訊,兩條線之間除了後續的同步操作之外基本沒有任何關聯。而線上路當中,各個模組之間並沒有太緊密的耦合,只要上游模組提供了原料,下游模組就可以執行處理。因此,我們可