CURL fopen file_get_contents
fopen /file_get_contents 每次请求都会重新做DNS查询,并不对DNS信息进行缓存。但是CURL会自动对DNS信息进行缓存。对同一域名下的网页或者图片的请求只需要一次DNS查询。这大大减少了DNS查询的次数。所以CURL的性能比fopen /file_get_contents 好很多。fopen /file_get_contents在请求HTTP时,使用的是http_fopen_wrapper,不会keeplive。而curl却可以。这样在多次请求多个链接时,curl效率会好一些。
fopen / file_get_contents函数会受到php.ini文件中allow_url_open选项配置的影响。如果该配置关闭了,则该函数也就失效了。而curl不受该配置的影响。
curl可以模拟多种请求,而fopen / file_get_contents只能使用get方式获取数据。
PS:file_get_contents()函数获取https链接内容的时候,需要php 中mod_ssl的支持(或安装opensll)。
一 什么是CURL
curl是一个利用URL语法在命令行方式下工作的文件传输工具。curl是一个利用URL语法在命令行方式下工作的文件传输工具。它支持很多协议:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP。curl同样支持HTTPS认证,HTTP POST方法, HTTP PUT方法, FTP上传, kerberos认证, HTTP上传, 代理服务器, cookies, 用户名/密码认证, 下载文件断点续传,上载文件断点续传, http代理服务器管道( proxy tunneling), 甚至它还支持IPv6, socks5代理服务器, 通过http代理服务器上传文件到FTP服务器等等,功能十分强大。
修改php.ini文件,找到;extension= php_curl.dll行 ,去掉前面的;号,保存,重启服务器
基本结构
在学习更为复杂的功能之前,先来看一下在PHP中建立cURL请求的基本步骤:
// 1. 初始化
$ch = curl_init();
// 2. 设置选项,包括URL
curl_setopt($ch, CURLOPT_URL, "http://www.nettuts.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
// 3. 执行并获取HTML文档内容
$output = curl_exec($ch);
// 4. 释放curl句柄
curl_close($ch);
第二步(也就是 curl_setopt() )最为重要,一切玄妙均在此 。有一长串CURL参数可供设置,它们能指定URL请求的各个细节。要一次性全部看完并理解可能比较困难,所以今天我们只试一下那些更常用也更有用的选项。
检查错误
你可以加一段检查错误的语句(虽然这并不是必需的):
// ...
$output = curl_exec($ch);
// 返回最后一次的错误号
$err_code = curl_errno($ch);
if ($err_code) {
echo "cURL Error: " . curl_error($ch);
}
// ...
请注意,比较的时候我们用的是“=== FALSE”,而非“== FALSE”。因为我们得区分 空输出 和 布尔值FALSE,后者才是真正的错误。
获取信息
这是另一个可选的设置项,能够在cURL执行后获取这一请求的有关信息:
// ...
curl_exec($ch);
$info = curl_getinfo($ch);
echo '获取'. $info['url'] . '耗时'. $info['total_time'] . '秒';
// ...
基于浏览器的重定向
在第一个例子中,我们将提供一段用于侦测服务器是否有基于浏览器的重定向的代码。例如,有些网站会根据是否是手机浏览器甚至用户来自哪个国家来重定向网页。
我们利用 CURLOPT_HTTPHEADER 选项来设定我们发送出的HTTP请求头信息(http headers),包括user agent信息和默认语言。然后我们来看看这些特定网站是否会把我们重定向到不同的URL。
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"User-Agent: {$browser['user_agent']}",
"Accept-Language: {$browser['language']}"
));
首先,我们建立一组需要测试的URL,接着指定一组需要测试的浏览器信息。最后通过循环测试各种URL和浏览器匹配可能产生的情况。
因为我们指定了cURL选项,所以返回的输出内容则只包括HTTP头信息(被存放于 $output 中)。利用一个简单的正则,我们检查这个头信息中是否包含了“Location:”字样。
运行这段代码应该会返回如下结果:
cURL批处理(multi cURL)http://hudeyong926.iteye.com/blog/1635386
抓取一些有页面访问控制的页面
如果某个URL请求需要基于 HTTP 的身份验证,你可以使用下面的代码:
代码:
$url = "http://www.somesite.com/members/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// 发送用户名和密码
curl_setopt($ch, CURLOPT_USERPWD, "myusername:mypassword");
// 你可以允许其重定向
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
// 下面的选项让 cURL 在重定向后
// 也能发送用户名和密码
curl_setopt($ch, CURLOPT_UNRESTRICTED_AUTH, 1);
$output = curl_exec($ch);
curl_close($ch);
FTP 上传
PHP 自带有 FTP 类库, 但你也能用 cURL:
// 开一个文件指针
$file = fopen("/path/to/file", "r");
// url里包含了大部分所需信息
$url = "ftp://username:password@mydomain.com:21/path/to/new/file";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// 上传相关的选项
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize("/path/to/file"));
// 是否开启ASCII模式 (上传文本文件时有用)
curl_setopt($ch, CURLOPT_FTPASCII, 1);
$output = curl_exec($ch);
curl_close($ch);
使用代理进行抓取
你可以用代理发起cURL请求:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// 指定代理地址
curl_setopt($ch, CURLOPT_PROXY, '11.11.11.11:8080');
// 如果需要的话,提供用户名和密码
curl_setopt($ch, CURLOPT_PROXYUSERPWD,'user:pass');
$output = curl_exec($ch);
curl_close ($ch);
回调函数
可以在一个URL请求过程中,让cURL调用某指定的回调函数。例如,在内容或者响应下载的过程中立刻开始利用数据,而不用等到完全下载完。
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://net.tutsplus.com');
curl_setopt($ch, CURLOPT_WRITEFUNCTION,"progress_function");
curl_exec($ch);
curl_close ($ch);
function progress_function($ch,$str) {
echo $str;
return strlen($str);
}
这个回调函数必须返回字串的长度,不然此功能将无法正常使用。
在URL响应接收的过程中,只要收到一个数据包,这个函数就会被调用。
PHP中CURL使用POST提交XML数据
$header[] = "Content-type: text/xml";//定义content-type为xml
$header[] = 'Accept-Charset: utf-8';
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);//定义请求类型
得到curl HTTP请求码.分离header和body信息。一是通过curl自带的curl_getinfo()方法获取头的长度,然后使用substr来分割字符串。示例代码如下:
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') {
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
}
上面的基本用法了解了,下面我就实例演示一次:
先通过浏览器正常访问网址https://www.innotree.cn/inno/database/totalDatabase,拿到伪装信息header,参数等
$ch = curl_init();
$url = "https://www.innotree.cn/inno/search/ajax/getAllSearchResult?query=&tagquery=&st=1&ps=10&areaName=&rounds=&show=0&idate=&edate=&cSEdate=-1&cSRound=-1&cSFdate=1&cSInum=-1&iSNInum=1&iSInum=-1&iSEnum=-1&iSEdate=-1&fchain=";
// 设置浏览器的特定header
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Host: www.innotree.cn",
"Connection: keep-alive",
"X-Requested-With: XMLHttpRequest",
"Referer: https://www.innotree.cn/inno/database/totalDatabase",
"Accept: application/json, text/javascript, */*; q=0.01",
"Cookie:_user_identify_=134a6349-e4db-3ac1-83a2-9c42a59c265c; JSESSIONID=aaao4DPqtMQZV49BIjBdw; Hm_lvt_37854ae85b75cf05012d4d71db2a355a=1515503368; Hm_lpvt_37854ae85b75cf05012d4d71db2a355a=1515507433; Hm_lvt_ddf0d99bc06024e29662071b7fc5044f=1515503368; Hm_lpvt_ddf0d99bc06024e29662071b7fc5044f=1515507433; uID=462030; sID=4527c630998f758cdee8031ce8a256d2",
));
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0');
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_ENCODING, "gzip, deflate, br");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //302redirect
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
$html = curl_exec($ch);
curl_close($ch);
exit(json_decode($html, 1));
使用非80端口
curl_setopt($ch, CURLOPT_PORT, 46961);
Linux curl命令请求
curl -X POST 'http://localhost:10080/api/test/demo' \
-H 'content-type: application/json;charset=utf-8' \
-H 'sig: tcQXEQBod75YlZPueaycfiEc7/1PHi++n6vBhhOqKNs69lNc+GEmgp81rOXOaV19JOx0orUN+OyASikEjehFRDIl7TpObtXC9U+xvjyArMafna4MnTStWk1AvYJ47n1Vi95G3fdXkDZ4c+soob3RxuwgyQnJ/V6pbHFAVhZQIaJy/+JmPqghbJprWPqkCVH9QhPiYhWYNvLdg14XtQhER68GkQssoGyOPz/tMkteD0apcq+eJ/TDLp9sBbrtVhdeRYRNI8gT5CQ=' \
-d '{
"dataId": "5pYXCeSVqP9bpY8Jso6",
"aaa": "123456",
"bbb": "12"
}'