1
|
|
|
<?php |
2
|
|
|
// +---------------------------------------------------------------------- |
3
|
|
|
// | PHPSpider [ A PHP Framework For Crawler ] |
4
|
|
|
// +---------------------------------------------------------------------- |
5
|
|
|
// | Copyright (c) 2006-2014 https://doc.phpspider.org All rights reserved. |
6
|
|
|
// +---------------------------------------------------------------------- |
7
|
|
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) |
8
|
|
|
// +---------------------------------------------------------------------- |
9
|
|
|
// | Author: Seatle Yang <[email protected]> |
10
|
|
|
// +---------------------------------------------------------------------- |
11
|
|
|
|
12
|
|
|
// +---------------------------------------------------------------------- |
13
|
|
|
// | GET请求 |
14
|
|
|
// | requests::get('http://www.test.com'); |
15
|
|
|
// | SERVER |
16
|
|
|
// | $_GET |
17
|
|
|
// +---------------------------------------------------------------------- |
18
|
|
|
// | POST请求 |
19
|
|
|
// | $data = array('name'=>'request'); |
20
|
|
|
// | requests::post('http://www.test.com', $data); |
21
|
|
|
// | SERVER |
22
|
|
|
// | $_POST |
23
|
|
|
// +---------------------------------------------------------------------- |
24
|
|
|
// | POST RESTful请求 |
25
|
|
|
// | $data = array('name'=>'request'); |
26
|
|
|
// | $data_string = json_encode($data); |
27
|
|
|
// | requests::set_header("Content-Type", "application/json"); |
28
|
|
|
// | requests::post('http://www.test.com', $data_string); |
29
|
|
|
// | SERVER |
30
|
|
|
// | file_get_contents('php://input') |
31
|
|
|
// +---------------------------------------------------------------------- |
32
|
|
|
// | POST 文件上传 |
33
|
|
|
// | $data = array('file1'=>''./data/phpspider.log''); |
34
|
|
|
// | requests::post('http://www.test.com', null, $data); |
35
|
|
|
// | SERVER |
36
|
|
|
// | $_FILES |
37
|
|
|
// +---------------------------------------------------------------------- |
38
|
|
|
// | 代理 |
39
|
|
|
// | requests::set_proxy(array('223.153.69.150:42354')); |
40
|
|
|
// | $html = requests::get('https://www.test.com'); |
41
|
|
|
// +---------------------------------------------------------------------- |
42
|
|
|
|
43
|
|
|
//---------------------------------- |
44
|
|
|
// PHPSpider请求类文件 |
45
|
|
|
//---------------------------------- |
46
|
|
|
|
47
|
|
|
namespace phpspider\core; |
48
|
|
|
|
49
|
|
|
if (!function_exists('curl_file_create')) |
50
|
|
|
{ |
51
|
|
|
function curl_file_create($filename, $mimetype = '', $postname = '') |
52
|
|
|
{ |
53
|
|
|
return "@$filename;filename=" |
54
|
|
|
. ($postname ?: basename($filename)) |
55
|
|
|
. ($mimetype ? ";type=$mimetype" : ''); |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
class requests |
60
|
|
|
{ |
61
|
|
|
const VERSION = '2.0.1'; |
62
|
|
|
|
63
|
|
|
protected static $ch = null; |
64
|
|
|
|
65
|
|
|
/**** Public variables ****/ |
66
|
|
|
|
67
|
|
|
/* user definable vars */ |
68
|
|
|
|
69
|
|
|
public static $timeout = 15; |
70
|
|
|
public static $encoding = null; |
71
|
|
|
public static $input_encoding = null; |
72
|
|
|
public static $output_encoding = null; |
73
|
|
|
public static $cookies = array(); // array of cookies to pass |
74
|
|
|
// $cookies['username'] = "seatle"; |
75
|
|
|
public static $rawheaders = array(); // array of raw headers to send |
76
|
|
|
public static $domain_cookies = array(); // array of cookies for domain to pass |
77
|
|
|
public static $hosts = array(); // random host binding for make request faster |
78
|
|
|
public static $headers = array(); // headers returned from server sent here |
79
|
|
|
public static $useragents = array("requests/2.0.0"); // random agent we masquerade as |
80
|
|
|
public static $client_ips = array(); // random ip we masquerade as |
81
|
|
|
public static $proxies = array(); // random proxy ip |
82
|
|
|
public static $raw = ""; // head + body content returned from server sent here |
83
|
|
|
public static $head = ""; // head content |
84
|
|
|
public static $content = ""; // The body before encoding |
85
|
|
|
public static $text = ""; // The body after encoding |
86
|
|
|
public static $info = array(); // curl info |
87
|
|
|
public static $history = 302; // http request status before redirect. ex:30x |
88
|
|
|
public static $status_code = 0; // http request status |
89
|
|
|
public static $error = ""; // error messages sent here |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* set timeout |
93
|
|
|
* $timeout 为数组时会分别设置connect和read |
94
|
|
|
* |
95
|
|
|
* @param init or array $timeout |
|
|
|
|
96
|
|
|
* @return |
97
|
|
|
*/ |
98
|
|
|
public static function set_timeout($timeout) |
99
|
|
|
{ |
100
|
|
|
self::$timeout = $timeout; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* 设置代理 |
105
|
|
|
* 如果代理有多个,请求时会随机使用 |
106
|
|
|
* |
107
|
|
|
* @param mixed $proxies |
108
|
|
|
* array ( |
109
|
|
|
* 'socks5://user1:pass2@host:port', |
110
|
|
|
* 'socks5://user2:pass2@host:port' |
111
|
|
|
*) |
112
|
|
|
* @return void |
113
|
|
|
* @author seatle <[email protected]> |
114
|
|
|
* @created time :2016-09-18 10:17 |
115
|
|
|
*/ |
116
|
|
|
public static function set_proxy($proxy) |
117
|
|
|
{ |
118
|
|
|
self::$proxies = is_array($proxy) ? $proxy : array($proxy); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* 删除代理 |
123
|
|
|
* 因为每个链接信息里面都有代理信息,有的链接需要,有的不需要,所以必须提供一个删除功能 |
124
|
|
|
* |
125
|
|
|
* @return void |
126
|
|
|
* @author seatle <[email protected]> |
127
|
|
|
* @created time :2018-07-16 17:59 |
128
|
|
|
*/ |
129
|
|
|
public static function del_proxy() |
130
|
|
|
{ |
131
|
|
|
self::$proxies = array(); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* 自定义请求头部 |
136
|
|
|
* 请求头内容可以用 requests::$rawheaders 来获取 |
137
|
|
|
* 比如获取Content-Type:requests::$rawheaders['Content-Type'] |
138
|
|
|
* |
139
|
|
|
* @param string $headers |
140
|
|
|
* @return void |
141
|
|
|
*/ |
142
|
|
|
public static function set_header($key, $value) |
143
|
|
|
{ |
144
|
|
|
self::$rawheaders[$key] = $value; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* 设置全局COOKIE |
149
|
|
|
* |
150
|
|
|
* @param string $cookie |
151
|
|
|
* @return void |
152
|
|
|
*/ |
153
|
|
|
public static function set_cookie($key, $value, $domain = '') |
154
|
|
|
{ |
155
|
|
|
if (empty($key)) |
156
|
|
|
{ |
157
|
|
|
return false; |
|
|
|
|
158
|
|
|
} |
159
|
|
|
if (!empty($domain)) |
160
|
|
|
{ |
161
|
|
|
self::$domain_cookies[$domain][$key] = $value; |
162
|
|
|
} |
163
|
|
|
else |
164
|
|
|
{ |
165
|
|
|
self::$cookies[$key] = $value; |
166
|
|
|
} |
167
|
|
|
return true; |
|
|
|
|
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* 批量设置全局cookie |
172
|
|
|
* |
173
|
|
|
* @param mixed $cookies |
174
|
|
|
* @param string $domain |
175
|
|
|
* @return void |
176
|
|
|
* @author seatle <[email protected]> |
177
|
|
|
* @created time :2017-08-03 18:06 |
178
|
|
|
*/ |
179
|
|
|
public static function set_cookies($cookies, $domain = '') |
180
|
|
|
{ |
181
|
|
|
$cookies_arr = explode(';', $cookies); |
182
|
|
|
if (empty($cookies_arr)) |
183
|
|
|
{ |
184
|
|
|
return false; |
|
|
|
|
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
foreach ($cookies_arr as $cookie) |
188
|
|
|
{ |
189
|
|
|
$cookie_arr = explode('=', $cookie, 2); |
190
|
|
|
$key = $cookie_arr[0]; |
191
|
|
|
$value = empty($cookie_arr[1]) ? '' : $cookie_arr[1]; |
192
|
|
|
|
193
|
|
|
if (!empty($domain)) |
194
|
|
|
{ |
195
|
|
|
self::$domain_cookies[$domain][$key] = $value; |
196
|
|
|
} |
197
|
|
|
else |
198
|
|
|
{ |
199
|
|
|
self::$cookies[$key] = $value; |
200
|
|
|
} |
201
|
|
|
} |
202
|
|
|
return true; |
|
|
|
|
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* 获取单一Cookie |
207
|
|
|
* |
208
|
|
|
* @param mixed $name cookie名称 |
209
|
|
|
* @param string $domain 不传则取全局cookie,就是手动set_cookie的cookie |
210
|
|
|
* @return void |
211
|
|
|
* @author seatle <[email protected]> |
212
|
|
|
* @created time :2017-08-03 18:06 |
213
|
|
|
*/ |
214
|
|
|
public static function get_cookie($name, $domain = '') |
215
|
|
|
{ |
216
|
|
|
if (!empty($domain) && !isset(self::$domain_cookies[$domain])) |
217
|
|
|
{ |
218
|
|
|
return ''; |
|
|
|
|
219
|
|
|
} |
220
|
|
|
$cookies = empty($domain) ? self::$cookies : self::$domain_cookies[$domain]; |
221
|
|
|
return isset($cookies[$name]) ? $cookies[$name] : ''; |
|
|
|
|
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* 获取Cookie数组 |
226
|
|
|
* |
227
|
|
|
* @param string $domain 不传则取全局cookie,就是手动set_cookie的cookie |
228
|
|
|
* @return void |
229
|
|
|
* @author seatle <[email protected]> |
230
|
|
|
* @created time :2017-08-03 18:06 |
231
|
|
|
*/ |
232
|
|
|
public static function get_cookies($domain = '') |
233
|
|
|
{ |
234
|
|
|
if (!empty($domain) && !isset(self::$domain_cookies[$domain])) |
235
|
|
|
{ |
236
|
|
|
return array(); |
|
|
|
|
237
|
|
|
} |
238
|
|
|
return empty($domain) ? self::$cookies : self::$domain_cookies[$domain]; |
|
|
|
|
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* 删除Cookie |
243
|
|
|
* |
244
|
|
|
* @param string $domain 不传则删除全局Cookie |
245
|
|
|
* @return void |
246
|
|
|
* @author seatle <[email protected]> |
247
|
|
|
* @created time :2017-08-03 18:06 |
248
|
|
|
*/ |
249
|
|
|
public static function del_cookie($key, $domain = '') |
250
|
|
|
{ |
251
|
|
|
if (empty($key)) |
252
|
|
|
{ |
253
|
|
|
return false; |
|
|
|
|
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
if (!empty($domain) && !isset(self::$domain_cookies[$domain])) |
257
|
|
|
{ |
258
|
|
|
return false; |
|
|
|
|
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
if (!empty($domain)) |
262
|
|
|
{ |
263
|
|
|
if (isset(self::$domain_cookies[$domain][$key])) |
264
|
|
|
{ |
265
|
|
|
unset(self::$domain_cookies[$domain][$key]); |
266
|
|
|
} |
267
|
|
|
} |
268
|
|
|
else |
269
|
|
|
{ |
270
|
|
|
if (isset(self::$cookies[$key])) |
271
|
|
|
{ |
272
|
|
|
unset(self::$cookies[$key]); |
273
|
|
|
} |
274
|
|
|
} |
275
|
|
|
return true; |
|
|
|
|
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
/** |
279
|
|
|
* 删除Cookie |
280
|
|
|
* |
281
|
|
|
* @param string $domain 不传则删除全局Cookie |
282
|
|
|
* @return void |
283
|
|
|
* @author seatle <[email protected]> |
284
|
|
|
* @created time :2017-08-03 18:06 |
285
|
|
|
*/ |
286
|
|
|
public static function del_cookies($domain = '') |
287
|
|
|
{ |
288
|
|
|
if (!empty($domain) && !isset(self::$domain_cookies[$domain])) |
289
|
|
|
{ |
290
|
|
|
return false; |
|
|
|
|
291
|
|
|
} |
292
|
|
|
if ( empty($domain) ) |
293
|
|
|
{ |
294
|
|
|
self::$cookies = array(); |
295
|
|
|
} |
296
|
|
|
else |
297
|
|
|
{ |
298
|
|
|
if (isset(self::$domain_cookies[$domain])) |
299
|
|
|
{ |
300
|
|
|
unset(self::$domain_cookies[$domain]); |
301
|
|
|
} |
302
|
|
|
} |
303
|
|
|
return true; |
|
|
|
|
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* 设置随机的user_agent |
308
|
|
|
* |
309
|
|
|
* @param string $useragent |
310
|
|
|
* @return void |
311
|
|
|
*/ |
312
|
|
|
public static function set_useragent($useragent) |
313
|
|
|
{ |
314
|
|
|
self::$useragents = is_array($useragent) ? $useragent : array($useragent); |
|
|
|
|
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* set referer |
319
|
|
|
* |
320
|
|
|
*/ |
321
|
|
|
public static function set_referer($referer) |
322
|
|
|
{ |
323
|
|
|
self::$rawheaders['Referer'] = $referer; |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* 设置伪造IP |
328
|
|
|
* 传入数组则为随机IP |
329
|
|
|
* @param string $ip |
330
|
|
|
* @return void |
331
|
|
|
*/ |
332
|
|
|
public static function set_client_ip($ip) |
333
|
|
|
{ |
334
|
|
|
self::$client_ips = is_array($ip) ? $ip : array($ip); |
|
|
|
|
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
/** |
338
|
|
|
* 删除伪造IP |
339
|
|
|
* |
340
|
|
|
* @return void |
341
|
|
|
* @author seatle <[email protected]> |
342
|
|
|
* @created time :2018-07-16 17:59 |
343
|
|
|
*/ |
344
|
|
|
public static function del_client_ip() |
345
|
|
|
{ |
346
|
|
|
self::$client_ips = array(); |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* 设置中文请求 |
351
|
|
|
* |
352
|
|
|
* @param string $lang |
353
|
|
|
* @return void |
354
|
|
|
*/ |
355
|
|
|
public static function set_accept_language($lang = 'zh-CN') |
356
|
|
|
{ |
357
|
|
|
self::$rawheaders['Accept-Language'] = $lang; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* 设置Hosts |
362
|
|
|
* 负载均衡到不同的服务器,如果对方使用CDN,采用这个是最好的了 |
363
|
|
|
* |
364
|
|
|
* @param string $hosts |
365
|
|
|
* @return void |
366
|
|
|
*/ |
367
|
|
|
public static function set_hosts($host, $ips = array()) |
368
|
|
|
{ |
369
|
|
|
$ips = is_array($ips) ? $ips : array($ips); |
370
|
|
|
self::$hosts[$host] = $ips; |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
/** |
374
|
|
|
* 分割返回的header和body |
375
|
|
|
* header用来判断编码和获取Cookie |
376
|
|
|
* body用来判断编码,得到编码前和编码后的内容 |
377
|
|
|
* |
378
|
|
|
* @return void |
379
|
|
|
* @author seatle <[email protected]> |
380
|
|
|
* @created time :2017-08-03 18:06 |
381
|
|
|
*/ |
382
|
|
|
public static function split_header_body() |
383
|
|
|
{ |
384
|
|
|
$head = $body = ''; |
|
|
|
|
385
|
|
|
$head = substr(self::$raw, 0, self::$info['header_size']); |
386
|
|
|
$body = substr(self::$raw, self::$info['header_size']); |
387
|
|
|
// http header |
388
|
|
|
self::$head = $head; |
389
|
|
|
// The body before encoding |
390
|
|
|
self::$content = $body; |
391
|
|
|
|
392
|
|
|
//$http_headers = array(); |
393
|
|
|
//// 解析HTTP数据流 |
394
|
|
|
//if (!empty(self::$raw)) |
395
|
|
|
//{ |
396
|
|
|
//self::get_response_cookies($domain); |
397
|
|
|
//// body里面可能有 \r\n\r\n,但是第一个一定是HTTP Header,去掉后剩下的就是body |
398
|
|
|
//$array = explode("\r\n\r\n", self::$raw); |
399
|
|
|
//foreach ($array as $k=>$v) |
400
|
|
|
//{ |
401
|
|
|
//// post 方法会有两个http header:HTTP/1.1 100 Continue、HTTP/1.1 200 OK |
402
|
|
|
//if (preg_match("#^HTTP/.*? 100 Continue#", $v)) |
403
|
|
|
//{ |
404
|
|
|
//unset($array[$k]); |
405
|
|
|
//continue; |
406
|
|
|
//} |
407
|
|
|
//if (preg_match("#^HTTP/.*? \d+ #", $v)) |
408
|
|
|
//{ |
409
|
|
|
//$header = $v; |
410
|
|
|
//unset($array[$k]); |
411
|
|
|
//$http_headers = self::get_response_headers($v); |
412
|
|
|
//} |
413
|
|
|
//} |
414
|
|
|
//$body = implode("\r\n\r\n", $array); |
415
|
|
|
//} |
416
|
|
|
|
417
|
|
|
// 设置了输出编码的转码,注意: xpath只支持utf-8,iso-8859-1 不要转,他本身就是utf-8 |
418
|
|
|
$body = self::encoding($body); //自动转码 |
419
|
|
|
// 转码后 |
420
|
|
|
self::$encoding = self::$output_encoding; |
421
|
|
|
|
422
|
|
|
// The body after encoding |
423
|
|
|
self::$text = $body; |
424
|
|
|
return array($head, $body); |
|
|
|
|
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
/** |
428
|
|
|
* 获得域名相对应的Cookie |
429
|
|
|
* |
430
|
|
|
* @param mixed $header |
431
|
|
|
* @param mixed $domain |
432
|
|
|
* @return void |
433
|
|
|
* @author seatle <[email protected]> |
434
|
|
|
* @created time :2017-08-03 18:06 |
435
|
|
|
*/ |
436
|
|
|
public static function get_response_cookies($header, $domain) |
437
|
|
|
{ |
438
|
|
|
// 解析Cookie并存入 self::$cookies 方便调用 |
439
|
|
|
preg_match_all("/.*?Set\-Cookie: ([^\r\n]*)/i", $header, $matches); |
440
|
|
|
$cookies = empty($matches[1]) ? array() : $matches[1]; |
441
|
|
|
|
442
|
|
|
// 解析到Cookie |
443
|
|
|
if (!empty($cookies)) |
444
|
|
|
{ |
445
|
|
|
$cookies = implode(';', $cookies); |
446
|
|
|
$cookies = explode(';', $cookies); |
447
|
|
|
foreach ($cookies as $cookie) |
448
|
|
|
{ |
449
|
|
|
$cookie_arr = explode('=', $cookie, 2); |
450
|
|
|
// 过滤 httponly、secure |
451
|
|
|
if (count($cookie_arr) < 2) |
452
|
|
|
{ |
453
|
|
|
continue; |
454
|
|
|
} |
455
|
|
|
$cookie_name = !empty($cookie_arr[0]) ? trim($cookie_arr[0]) : ''; |
456
|
|
|
if (empty($cookie_name)) |
457
|
|
|
{ |
458
|
|
|
continue; |
459
|
|
|
} |
460
|
|
|
// 过滤掉domain路径 |
461
|
|
|
if (in_array(strtolower($cookie_name), array('path', 'domain', 'expires', 'max-age'))) |
462
|
|
|
{ |
463
|
|
|
continue; |
464
|
|
|
} |
465
|
|
|
self::$domain_cookies[$domain][trim($cookie_arr[0])] = trim($cookie_arr[1]); |
466
|
|
|
} |
467
|
|
|
} |
468
|
|
|
} |
469
|
|
|
|
470
|
|
|
/** |
471
|
|
|
* 获得response header |
472
|
|
|
* 此方法占时没有用到 |
473
|
|
|
* |
474
|
|
|
* @param mixed $header |
475
|
|
|
* @return void |
476
|
|
|
* @author seatle <[email protected]> |
477
|
|
|
* @created time :2017-08-03 18:06 |
478
|
|
|
*/ |
479
|
|
|
public static function get_response_headers($header) |
480
|
|
|
{ |
481
|
|
|
$headers = array(); |
482
|
|
|
$header_lines = explode("\n", $header); |
483
|
|
|
if (!empty($header_lines)) |
484
|
|
|
{ |
485
|
|
|
foreach ($header_lines as $line) |
486
|
|
|
{ |
487
|
|
|
$header_arr = explode(':', $line, 2); |
488
|
|
|
$key = empty($header_arr[0]) ? '' : trim($header_arr[0]); |
489
|
|
|
$val = empty($header_arr[1]) ? '' : trim($header_arr[1]); |
490
|
|
|
if (empty($key) || empty($val)) |
491
|
|
|
{ |
492
|
|
|
continue; |
493
|
|
|
} |
494
|
|
|
$headers[$key] = $val; |
495
|
|
|
} |
496
|
|
|
} |
497
|
|
|
self::$headers = $headers; |
498
|
|
|
return self::$headers; |
|
|
|
|
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
/** |
502
|
|
|
* 获取编码 |
503
|
|
|
* @param $string |
504
|
|
|
* @return string |
505
|
|
|
*/ |
506
|
|
|
public static function get_encoding($string) |
507
|
|
|
{ |
508
|
|
|
$encoding = mb_detect_encoding($string, array('UTF-8', 'GBK', 'GB2312', 'LATIN1', 'ASCII', 'BIG5', 'ISO-8859-1')); |
509
|
|
|
return strtolower($encoding); |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
/** |
513
|
|
|
* 移除页面head区域代码 |
514
|
|
|
* @param $html |
515
|
|
|
* @return mixed |
516
|
|
|
*/ |
517
|
|
|
private static function _remove_head($html) |
|
|
|
|
518
|
|
|
{ |
519
|
|
|
return preg_replace('/<head.+?>.+<\/head>/is', '<head></head>', $html); |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
/** |
523
|
|
|
* 简单的判断一下参数是否为一个URL链接 |
524
|
|
|
* @param string $str |
525
|
|
|
* @return boolean |
526
|
|
|
*/ |
527
|
|
|
private static function _is_url($url) |
528
|
|
|
{ |
529
|
|
|
//$pattern = '/^http(s)?:\\/\\/.+/'; |
530
|
|
|
$pattern = "/\b(([\w-]+:\/\/?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/)))/"; |
531
|
|
|
if (preg_match($pattern, $url)) |
532
|
|
|
{ |
533
|
|
|
return true; |
534
|
|
|
} |
535
|
|
|
return false; |
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
/** |
539
|
|
|
* 初始化 CURL |
540
|
|
|
* |
541
|
|
|
*/ |
542
|
|
|
public static function init() |
543
|
|
|
{ |
544
|
|
|
if (!is_resource ( self::$ch )) |
545
|
|
|
{ |
546
|
|
|
self::$ch = curl_init (); |
547
|
|
|
curl_setopt( self::$ch, CURLOPT_RETURNTRANSFER, true ); |
|
|
|
|
548
|
|
|
curl_setopt( self::$ch, CURLOPT_HEADER, false ); |
549
|
|
|
curl_setopt( self::$ch, CURLOPT_USERAGENT, "phpspider-requests/".self::VERSION ); |
550
|
|
|
// 如果设置了两个时间,就分开设置 |
551
|
|
|
if (is_array(self::$timeout)) |
|
|
|
|
552
|
|
|
{ |
553
|
|
|
curl_setopt( self::$ch, CURLOPT_CONNECTTIMEOUT, self::$timeout[0] ); |
554
|
|
|
curl_setopt( self::$ch, CURLOPT_TIMEOUT, self::$timeout[1]); |
555
|
|
|
} |
556
|
|
|
else |
557
|
|
|
{ |
558
|
|
|
curl_setopt(self::$ch, CURLOPT_CONNECTTIMEOUT, ceil(self::$timeout / 2)); |
559
|
|
|
curl_setopt(self::$ch, CURLOPT_TIMEOUT, self::$timeout); |
560
|
|
|
} |
561
|
|
|
curl_setopt(self::$ch, CURLOPT_MAXREDIRS, 5); //maximum number of redirects allowed |
562
|
|
|
// 在多线程处理场景下使用超时选项时,会忽略signals对应的处理函数,但是无耐的是还有小概率的crash情况发生 |
563
|
|
|
curl_setopt( self::$ch, CURLOPT_NOSIGNAL, true); |
564
|
|
|
} |
565
|
|
|
return self::$ch; |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
/** |
569
|
|
|
* get 请求 |
570
|
|
|
*/ |
571
|
|
|
public static function get($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
572
|
|
|
{ |
573
|
|
|
self::init (); |
574
|
|
|
return self::request($url, 'get', $fields, NULL, $allow_redirects, $cert); |
|
|
|
|
575
|
|
|
} |
576
|
|
|
|
577
|
|
|
/** |
578
|
|
|
* post 请求 |
579
|
|
|
* $fields 有三种类型:1、数组;2、http query;3、json |
580
|
|
|
* 1、array('name'=>'yangzetao') |
581
|
|
|
* 2、http_build_query(array('name'=>'yangzetao')) |
582
|
|
|
* 3、json_encode(array('name'=>'yangzetao')) |
583
|
|
|
* 前两种是普通的post,可以用$_POST方式获取 |
584
|
|
|
* 第三种是post stream( json rpc,其实就是webservice ) |
585
|
|
|
* 虽然是post方式,但是只能用流方式 http://input 后者 $HTTP_RAW_POST_DATA 获取 |
586
|
|
|
* |
587
|
|
|
* @param mixed $url |
588
|
|
|
* @param array $fields |
589
|
|
|
* @param mixed $proxies |
590
|
|
|
* @static |
591
|
|
|
* @access public |
592
|
|
|
* @return void |
593
|
|
|
*/ |
594
|
|
|
public static function post($url, $fields = array(), $files = array(), $allow_redirects = true, $cert = NULL) |
595
|
|
|
{ |
596
|
|
|
self::init (); |
597
|
|
|
return self::request($url, 'POST', $fields, $files, $allow_redirects, $cert); |
|
|
|
|
598
|
|
|
} |
599
|
|
|
|
600
|
|
|
public static function put($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
601
|
|
|
{ |
602
|
|
|
self::init (); |
603
|
|
|
return self::request($url, 'PUT', $fields, $allow_redirects, $cert); |
|
|
|
|
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
public static function delete($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
607
|
|
|
{ |
608
|
|
|
self::init (); |
609
|
|
|
return self::request($url, 'DELETE', $fields, $allow_redirects, $cert); |
|
|
|
|
610
|
|
|
} |
611
|
|
|
|
612
|
|
|
// 响应HTTP头域里的元信息 |
613
|
|
|
// 此方法被用来获取请求实体的元信息而不需要传输实体主体(entity-body) |
614
|
|
|
// 此方法经常被用来测试超文本链接的有效性,可访问性,和最近的改变。. |
615
|
|
|
public static function head($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
616
|
|
|
{ |
617
|
|
|
self::init (); |
618
|
|
|
self::request($url, 'HEAD', $fields, $allow_redirects, $cert); |
619
|
|
|
} |
620
|
|
|
|
621
|
|
|
public static function options($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
622
|
|
|
{ |
623
|
|
|
self::init (); |
624
|
|
|
return self::request($url, 'OPTIONS', $fields, $allow_redirects, $cert); |
|
|
|
|
625
|
|
|
} |
626
|
|
|
|
627
|
|
|
public static function patch($url, $fields = array(), $allow_redirects = true, $cert = NULL) |
628
|
|
|
{ |
629
|
|
|
self::init (); |
630
|
|
|
return self::request($url, 'PATCH', $fields, $allow_redirects, $cert); |
|
|
|
|
631
|
|
|
} |
632
|
|
|
|
633
|
|
|
/** |
634
|
|
|
* request |
635
|
|
|
* |
636
|
|
|
* @param mixed $url 请求URL |
637
|
|
|
* @param string $method 请求方法 |
638
|
|
|
* @param array $fields 表单字段 |
639
|
|
|
* @param array $files 上传文件 |
640
|
|
|
* @param mixed $cert CA证书 |
641
|
|
|
* @return void |
642
|
|
|
* @author seatle <[email protected]> |
643
|
|
|
* @created time :2017-08-03 18:06 |
644
|
|
|
*/ |
645
|
|
|
public static function request($url, $method = 'GET', $fields = array(), $files = array(), $allow_redirects = true, $cert = NULL) |
|
|
|
|
646
|
|
|
{ |
647
|
|
|
$method = strtoupper($method); |
648
|
|
|
if(!self::_is_url($url)) |
649
|
|
|
{ |
650
|
|
|
self::$error = "You have requested URL ({$url}) is not a valid HTTP address"; |
651
|
|
|
return false; |
|
|
|
|
652
|
|
|
} |
653
|
|
|
|
654
|
|
|
// 如果是 get 方式,直接拼凑一个 url 出来 |
655
|
|
|
if ($method == 'GET' && !empty($fields)) |
656
|
|
|
{ |
657
|
|
|
$url = $url.(strpos($url, '?') === false ? '?' : '&').http_build_query($fields); |
658
|
|
|
} |
659
|
|
|
|
660
|
|
|
$parse_url = parse_url($url); |
661
|
|
|
if (empty($parse_url) || empty($parse_url['host']) || !in_array($parse_url['scheme'], array('http', 'https'))) |
662
|
|
|
{ |
663
|
|
|
self::$error = "No connection adapters were found for '{$url}'"; |
664
|
|
|
return false; |
|
|
|
|
665
|
|
|
} |
666
|
|
|
$scheme = $parse_url['scheme']; |
667
|
|
|
$domain = $parse_url['host']; |
668
|
|
|
|
669
|
|
|
// 随机绑定 hosts,做负载均衡 |
670
|
|
|
if (self::$hosts) |
|
|
|
|
671
|
|
|
{ |
672
|
|
|
if (isset(self::$hosts[$domain])) |
673
|
|
|
{ |
674
|
|
|
$hosts = self::$hosts[$domain]; |
675
|
|
|
$key = rand(0, count($hosts)-1); |
676
|
|
|
$ip = $hosts[$key]; |
677
|
|
|
$url = str_replace($domain, $ip, $url); |
678
|
|
|
self::$rawheaders['Host'] = $domain; |
679
|
|
|
} |
680
|
|
|
} |
681
|
|
|
|
682
|
|
|
curl_setopt( self::$ch, CURLOPT_URL, $url ); |
683
|
|
|
|
684
|
|
|
if ($method != 'GET') |
685
|
|
|
{ |
686
|
|
|
// 如果是 post 方式 |
687
|
|
|
if ($method == 'POST') |
688
|
|
|
{ |
689
|
|
|
//curl_setopt( self::$ch, CURLOPT_POST, true ); |
690
|
|
|
$tmpheaders = array_change_key_case(self::$rawheaders, CASE_LOWER); |
691
|
|
|
// 有些RESTful服务只接受JSON形态的数据 |
692
|
|
|
// CURLOPT_POST会把上傳的文件类型设为 multipart/form-data |
693
|
|
|
// 把CURLOPT_POSTFIELDS的内容按multipart/form-data 的形式编码 |
694
|
|
|
// CURLOPT_CUSTOMREQUEST可以按指定内容上传 |
695
|
|
|
if ( isset($tmpheaders['content-type']) && $tmpheaders['content-type'] == 'application/json' ) |
696
|
|
|
{ |
697
|
|
|
curl_setopt( self::$ch, CURLOPT_CUSTOMREQUEST, $method ); |
698
|
|
|
} |
699
|
|
|
else |
700
|
|
|
{ |
701
|
|
|
curl_setopt( self::$ch, CURLOPT_POST, true ); |
702
|
|
|
} |
703
|
|
|
|
704
|
|
|
$file_fields = array(); |
705
|
|
|
if (!empty($files)) |
706
|
|
|
{ |
707
|
|
|
foreach ($files as $postname => $file) |
708
|
|
|
{ |
709
|
|
|
$filepath = realpath($file); |
710
|
|
|
// 如果文件不存在 |
711
|
|
|
if (!file_exists($filepath)) |
712
|
|
|
{ |
713
|
|
|
continue; |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
$filename = basename($filepath); |
717
|
|
|
$type = self::get_mimetype($filepath); |
718
|
|
|
$file_fields[$postname] = curl_file_create($filepath, $type, $filename); |
719
|
|
|
// curl -F "name=seatle&file=@/absolute/path/to/image.png" htt://localhost/uploadfile.php |
720
|
|
|
//$cfile = '@'.realpath($filename).";type=".$type.";filename=".$filename; |
721
|
|
|
} |
722
|
|
|
} |
723
|
|
|
} |
724
|
|
|
else |
725
|
|
|
{ |
726
|
|
|
self::$rawheaders['X-HTTP-Method-Override'] = $method; |
727
|
|
|
curl_setopt( self::$ch, CURLOPT_CUSTOMREQUEST, $method ); |
728
|
|
|
} |
729
|
|
|
|
730
|
|
|
if ( $method == 'POST' ) |
731
|
|
|
{ |
732
|
|
|
// 不是上传文件的,用http_build_query, 能实现更好的兼容性,更小的请求数据包 |
733
|
|
|
if ( empty($file_fields) ) |
734
|
|
|
{ |
735
|
|
|
// post方式 |
736
|
|
|
if ( is_array($fields) ) |
737
|
|
|
{ |
738
|
|
|
$fields = http_build_query($fields); |
739
|
|
|
} |
740
|
|
|
} |
741
|
|
|
else |
742
|
|
|
{ |
743
|
|
|
// 有post数据 |
744
|
|
|
if ( is_array($fields) && !empty($fields) ) |
745
|
|
|
{ |
746
|
|
|
// 某些server可能会有问题 |
747
|
|
|
$fields = array_merge($fields, $file_fields); |
748
|
|
|
} |
749
|
|
|
else |
750
|
|
|
{ |
751
|
|
|
$fields = $file_fields; |
752
|
|
|
} |
753
|
|
|
} |
754
|
|
|
|
755
|
|
|
// 不能直接传数组,不知道是什么Bug,会非常慢 |
756
|
|
|
curl_setopt( self::$ch, CURLOPT_POSTFIELDS, $fields ); |
757
|
|
|
} |
758
|
|
|
} |
759
|
|
|
|
760
|
|
|
$cookies = self::get_cookies(); |
|
|
|
|
761
|
|
|
$domain_cookies = self::get_cookies($domain); |
|
|
|
|
762
|
|
|
$cookies = array_merge($cookies, $domain_cookies); |
|
|
|
|
763
|
|
|
// 是否设置了cookie |
764
|
|
|
if (!empty($cookies)) |
765
|
|
|
{ |
766
|
|
|
foreach ($cookies as $key=>$value) |
767
|
|
|
{ |
768
|
|
|
$cookie_arr[] = $key.'='.$value; |
769
|
|
|
} |
770
|
|
|
$cookies = implode('; ', $cookie_arr); |
|
|
|
|
771
|
|
|
curl_setopt(self::$ch, CURLOPT_COOKIE, $cookies); |
772
|
|
|
} |
773
|
|
|
|
774
|
|
|
if (!empty(self::$useragents)) |
775
|
|
|
{ |
776
|
|
|
$key = rand(0, count(self::$useragents) - 1); |
777
|
|
|
self::$rawheaders['User-Agent'] = self::$useragents[$key]; |
778
|
|
|
} |
779
|
|
|
|
780
|
|
|
if (!empty(self::$client_ips)) |
781
|
|
|
{ |
782
|
|
|
$key = rand(0, count(self::$client_ips) - 1); |
783
|
|
|
self::$rawheaders['CLIENT-IP'] = self::$client_ips[$key]; |
784
|
|
|
self::$rawheaders['X-FORWARDED-FOR'] = self::$client_ips[$key]; |
785
|
|
|
} |
786
|
|
|
|
787
|
|
|
if (self::$rawheaders) |
|
|
|
|
788
|
|
|
{ |
789
|
|
|
$http_headers = array(); |
790
|
|
|
foreach (self::$rawheaders as $k=>$v) |
791
|
|
|
{ |
792
|
|
|
$http_headers[] = $k.': '.$v; |
793
|
|
|
} |
794
|
|
|
curl_setopt( self::$ch, CURLOPT_HTTPHEADER, $http_headers ); |
795
|
|
|
} |
796
|
|
|
|
797
|
|
|
curl_setopt( self::$ch, CURLOPT_ENCODING, 'gzip' ); |
798
|
|
|
|
799
|
|
|
// 关闭验证 |
800
|
|
|
if ($scheme == 'https') |
801
|
|
|
{ |
802
|
|
|
curl_setopt(self::$ch, CURLOPT_SSL_VERIFYPEER, false); |
803
|
|
|
curl_setopt(self::$ch, CURLOPT_SSL_VERIFYHOST, false); |
804
|
|
|
} |
805
|
|
|
|
806
|
|
|
if (self::$proxies) |
|
|
|
|
807
|
|
|
{ |
808
|
|
|
$key = rand(0, count(self::$proxies) - 1); |
809
|
|
|
$proxy = self::$proxies[$key]; |
810
|
|
|
curl_setopt( self::$ch, CURLOPT_PROXY, $proxy ); |
811
|
|
|
} |
812
|
|
|
|
813
|
|
|
// header + body,header 里面有 cookie |
814
|
|
|
curl_setopt( self::$ch, CURLOPT_HEADER, true ); |
815
|
|
|
// 请求跳转后的内容 |
816
|
|
|
if ($allow_redirects) |
817
|
|
|
{ |
818
|
|
|
curl_setopt( self::$ch, CURLOPT_FOLLOWLOCATION, true); |
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
self::$raw = curl_exec ( self::$ch ); |
822
|
|
|
// 真实url |
823
|
|
|
//$location = curl_getinfo( self::$ch, CURLINFO_EFFECTIVE_URL); |
824
|
|
|
self::$info = curl_getinfo( self::$ch ); |
825
|
|
|
//print_r(self::$info); |
826
|
|
|
self::$status_code = self::$info['http_code']; |
827
|
|
|
if (self::$raw === false) |
828
|
|
|
{ |
829
|
|
|
self::$error = 'Curl error: ' . curl_error( self::$ch ); |
830
|
|
|
//trigger_error(self::$error, E_USER_WARNING); |
831
|
|
|
} |
832
|
|
|
|
833
|
|
|
// 关闭句柄 |
834
|
|
|
curl_close( self::$ch ); |
835
|
|
|
|
836
|
|
|
// 请求成功之后才把URL存起来 |
837
|
|
|
list($header, $text) = self::split_header_body(); |
|
|
|
|
838
|
|
|
self::$history = self::get_history($header); |
839
|
|
|
self::$headers = self::get_response_headers($header); |
|
|
|
|
840
|
|
|
self::get_response_cookies($header, $domain); |
841
|
|
|
//$data = substr($data, 10); |
842
|
|
|
//$data = gzinflate($data); |
843
|
|
|
return $text; |
844
|
|
|
} |
845
|
|
|
|
846
|
|
|
public static function get_history($header) |
847
|
|
|
{ |
848
|
|
|
$status_code = 0; |
849
|
|
|
$lines = explode("\n", $header); |
850
|
|
|
foreach ($lines as $line) |
851
|
|
|
{ |
852
|
|
|
$line = trim($line); |
853
|
|
|
if (preg_match("#^HTTP/.*? (\d+) Found#", $line, $out)) |
854
|
|
|
{ |
855
|
|
|
$status_code = empty($out[1]) ? 0 : intval($out[1]); |
856
|
|
|
} |
857
|
|
|
} |
858
|
|
|
return $status_code; |
859
|
|
|
} |
860
|
|
|
|
861
|
|
|
// 获取 mimetype |
862
|
|
|
public static function get_mimetype($filepath) |
863
|
|
|
{ |
864
|
|
|
$fp = finfo_open(FILEINFO_MIME); |
865
|
|
|
$mime = finfo_file($fp, $filepath); |
866
|
|
|
finfo_close($fp); |
867
|
|
|
$arr = explode(';', $mime); |
868
|
|
|
$type = empty($arr[0]) ? '' : $arr[0]; |
869
|
|
|
return $type; |
870
|
|
|
} |
871
|
|
|
|
872
|
|
|
/** |
873
|
|
|
* 拼凑文件和表单 |
874
|
|
|
* 占时没有用到 |
875
|
|
|
* |
876
|
|
|
* @param mixed $post_fields |
877
|
|
|
* @param mixed $file_fields |
878
|
|
|
* @return void |
879
|
|
|
* @author seatle <[email protected]> |
880
|
|
|
* @created time :2017-08-03 18:06 |
881
|
|
|
*/ |
882
|
|
|
public static function get_postfile_form($post_fields, $file_fields) |
883
|
|
|
{ |
884
|
|
|
// 构造post数据 |
885
|
|
|
$data = ''; |
886
|
|
|
$delimiter = '-------------' . uniqid(); |
887
|
|
|
// 表单数据 |
888
|
|
|
foreach ($post_fields as $name => $content) |
889
|
|
|
{ |
890
|
|
|
$data .= '--'.$delimiter."\r\n"; |
891
|
|
|
$data .= 'Content-Disposition: form-data; name = "'.$name.'"'; |
892
|
|
|
$data .= "\r\n\r\n"; |
893
|
|
|
$data .= $content; |
894
|
|
|
$data .= "\r\n"; |
895
|
|
|
} |
896
|
|
|
|
897
|
|
|
foreach ($file_fields as $input_name => $file) |
898
|
|
|
{ |
899
|
|
|
$data .= '--'.$delimiter."\r\n"; |
900
|
|
|
$data .= 'Content-Disposition: form-data; name = "'.$input_name.'";'. |
901
|
|
|
' filename="'.$file['filename'].'"'."\r\n"; |
902
|
|
|
$data .= "Content-Type: {$file['type']}\r\n"; |
903
|
|
|
$data .= "\r\n"; |
904
|
|
|
$data .= $file['content']; |
905
|
|
|
$data .= "\r\n"; |
906
|
|
|
} |
907
|
|
|
|
908
|
|
|
// 结束符 |
909
|
|
|
$data .= '--'.$delimiter."--\r\n"; |
910
|
|
|
|
911
|
|
|
//return array( |
912
|
|
|
//CURLOPT_HTTPHEADER => array( |
913
|
|
|
//'Content-Type:multipart/form-data;boundary=' . $delimiter, |
914
|
|
|
//'Content-Length:' . strlen($data) |
915
|
|
|
//), |
916
|
|
|
//CURLOPT_POST => true, |
917
|
|
|
//CURLOPT_POSTFIELDS => $data, |
918
|
|
|
//); |
919
|
|
|
return array($delimiter, $data); |
|
|
|
|
920
|
|
|
} |
921
|
|
|
|
922
|
|
|
/** |
923
|
|
|
* html encoding transform |
924
|
|
|
* |
925
|
|
|
* @param string $html |
926
|
|
|
* @param string $in |
927
|
|
|
* @param string $out |
928
|
|
|
* @param string $content |
929
|
|
|
* @param string $mode |
930
|
|
|
* auto|iconv|mb_convert_encoding |
931
|
|
|
* @return string |
932
|
|
|
*/ |
933
|
|
|
public static function encoding($html, $in = null, $out = null, $mode = 'auto') |
934
|
|
|
{ |
935
|
|
|
$valid = array( |
936
|
|
|
'auto', |
937
|
|
|
'iconv', |
938
|
|
|
'mb_convert_encoding', |
939
|
|
|
); |
940
|
|
|
if (isset(self::$output_encoding)) |
941
|
|
|
{ |
942
|
|
|
$out = self::$output_encoding; |
943
|
|
|
} |
944
|
|
|
if ( ! isset($out)) |
945
|
|
|
{ |
946
|
|
|
$out = 'UTF-8'; |
947
|
|
|
} |
948
|
|
|
if ( ! in_array($mode, $valid)) |
949
|
|
|
{ |
950
|
|
|
throw new Exception('invalid mode, mode='.$mode); |
|
|
|
|
951
|
|
|
} |
952
|
|
|
$if = function_exists('mb_convert_encoding'); |
953
|
|
|
$if = $if && ($mode == 'auto' || $mode == 'mb_convert_encoding'); |
954
|
|
|
if (function_exists('iconv') && ($mode == 'auto' || $mode == 'iconv')) |
955
|
|
|
{ |
956
|
|
|
$func = 'iconv'; |
957
|
|
|
} |
958
|
|
|
elseif ($if) |
959
|
|
|
{ |
960
|
|
|
$func = 'mb_convert_encoding'; |
961
|
|
|
} |
962
|
|
|
else |
963
|
|
|
{ |
964
|
|
|
throw new Exception('charsetTrans failed, no function'); |
965
|
|
|
} |
966
|
|
|
|
967
|
|
|
$pattern = '/(<meta[^>]*?charset=([\"\']?))([a-z\d_\-]*)(\2[^>]*?>)/is'; |
968
|
|
|
if ( ! isset($in)) |
969
|
|
|
{ |
970
|
|
|
$n = preg_match($pattern, $html, $in); |
971
|
|
|
if ($n > 0) |
972
|
|
|
{ |
973
|
|
|
$in = $in[3]; |
974
|
|
|
} |
975
|
|
|
else |
976
|
|
|
{ |
977
|
|
|
$in = null; |
978
|
|
|
} |
979
|
|
|
if (empty($in) and function_exists('mb_detect_encoding')) |
980
|
|
|
{ |
981
|
|
|
$in = mb_detect_encoding($html, array('UTF-8', 'GBK', 'GB2312', 'LATIN1', 'ASCII', 'BIG5', 'ISO-8859-1')); |
982
|
|
|
} |
983
|
|
|
} |
984
|
|
|
|
985
|
|
|
if (isset($in)) |
986
|
|
|
{ |
987
|
|
|
if ($in == 'ISO-8859-1') |
988
|
|
|
{ |
989
|
|
|
$in = 'UTF-8'; |
990
|
|
|
} |
991
|
|
|
$old = error_reporting(error_reporting() & ~E_NOTICE); |
992
|
|
|
$html = call_user_func($func, $in, $out.'//IGNORE', $html); |
993
|
|
|
error_reporting($old); |
994
|
|
|
$html = preg_replace($pattern, "\\1$out\\4", $html, 1); |
995
|
|
|
} |
996
|
|
|
return $html; |
997
|
|
|
} |
998
|
|
|
} |
999
|
|
|
|
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths