Home  >  Article  >  Backend Development  >  curl能否下载115的资源

curl能否下载115的资源

WBOY
WBOYOriginal
2016-06-23 14:09:561120browse

1个300MB的资源,用迅雷下载(非115VIP),已经设置了原始线程1,但是平均速度只有10几KB,下到60%之时就提示错误。分析了一下URL地址规律,发现URL里的 &t=1368261625 是一个变量,估计115根据这个时间来处理下载过期事务。
 
用 Ultraediter 打开.td.cfg,修改了里面的&t=1368261625为当前时间,重新启动迅雷,发现文件被重新下载了(之前的60%木有了)。不知道如何修改迅雷,才可以使得修改了下载URL后可以继续前面的下载。(迅雷应该还有一个文件参数对比的方法,但是没有找到)

于是想到了用php curl下载115的资源(PHP可以任意修改URL地址),但是PHP的默认超时为30秒,如果set_time_limit(0);的话,如何判别115的资源地址已经失效,即这个PHP文件已经运行完毕?
打算用.bat文件,或者直接命令提示符DOS运行该php脚本。

问题:
1.用curl断点保存文件,会不会在第二次下载时,又重新从0%开始?
2.如果问题1可行的话,如果如何写代码,可以在一个长连接后,获知该PHP文件已经运行完毕?(这样重新运行.bat或者DOS进行断点下载)

PS:网上只有115上传类的代码,木有下载类的代码,大虾们帮忙挑战一下,可能的话,就是原创+精华帖,可以拿到CSDN博客里。


回复讨论(解决方案)

忽略掉你其他的内容,只问一句:
既然打算用命令行,为何还要php加载curl?直接用curl.exe不就可以了么?

你先给出下载地址,这样才能有鉴别

你先给出下载地址,这样才能有鉴别
感谢老大,贴个下载地址,U2的专辑
http://119.147.99.31/gdown_group121/M00/07/9C/d5NjH05TqRMAAAAAF2WEJGZScDk3421731/2009_-_No_Line_On_The_Horizon.rar?k=1zD-fJeIwQDpOh4kUbL9IA&t=1368286814&u=1562790934-355643028-ckf4okro&s=51200&file=2009_-_No_Line_On_The_Horizon.rar

&t=1368286814 ,那个好像就是验证时间。信息。

我跟你说说续传的原理,你自己想想能不能完成吧

http续传,少不了http请求头参数
Range:bytes=aaaa-bbbb/cccc
响应头也一定有 Content-Length
aaaa为开始位置,bbbb为结束位置,cccc是文件长度

多线程其实就是把文件切片了,发送N个请求,每个aaaa和bbbb指向不同的段,然后拼接
续传就是把aaaa设在已写入硬盘的文件的位置,继续下载
多线程+续传,一般需要一个记录,记下每个切片的完成位置,等等
所以续传必须满足三方:客户端能发送range,proxy是连接机制而不是转发机制,服务器能接受range请求

如果你用工具下载,一般,工具不会考虑太多,记录文件必然对应一个url和一个本地文件
当url改变时,工具很难“智能”地选择之前的记录文件去确认已下载部分
另一方面如果多线程不是采用预写硬盘的方式就更麻烦了

自己写个socket或者能做到

另外,/M00/07/9C/d5NjH05TqRMAAAAAF2WEJGZScDk3421731/ 这样的路径,凭经验基本可以确认是临时路径,服务器对它的处理方式很难预料,删除or禁止访问or……?

curl 有 CURLOPT_RANGE 属性,完全可以实现断点续传

只不过昨晚还可以返回
    [0] => HTTP/1.1 200 OK
    [Server] => nginx
    [Date] => Sat, 11 May 2013 15:23:43 GMT
    [Content-Type] => application/octet-stream
    [Content-Length] => 392528932
    [Last-Modified] => Tue, 23 Aug 2011 13:20:19 GMT
    [Connection] => close
    [Content-Disposition] => attachment
    [Accept-Ranges] => bytes
今天就只能返回
    [0] => HTTP/1.1 403 Forbidden
    [Server] => nginx
    [Date] => Sun, 12 May 2013 03:20:32 GMT
    [Content-Type] => text/html
    [Content-Length] => 4923
    [Connection] => close

于是这能放弃了
等你找到其他可测试的url时再做

curl 有 CURLOPT_RANGE 属性,完全可以实现断点续传
于是这能放弃了
等你找到其他可测试的url时再做

天,那个URL隔几个小时就变换掉了。一次一次的张贴,太麻烦了。

http://119.147.99.31/gdown_group121/M00/07/9C/d5NjH05TqRMAAAAAF2WEJGZScDk3421731/2009_-_No_Line_On_The_Horizon.rar?k=UlqeD7YQ3hi-tkpdRMXvvA&t=1368352262&u=1562790755-355643028-ckf4okro&s=51200&file=2009_-_No_Line_On_The_Horizon.rar

老大,依照你的经验,写一个大致的运行代码,我自己测试吧,谢谢。
测试以后,我把结果再贴出来。

你那个url不支持断点续传!
我贴段测试代码,供你研究。但要达到实用还很要花点功夫

$url = 'http://blog.51edm.org/content/uploadfile/201303/dc7f1364286796.zip';function curl_get($durl) {  $cookiejar = realpath('cookie.txt');  $t = parse_url($durl);  $ch = curl_init();  curl_setopt($ch, CURLOPT_URL,$durl);//  curl_setopt($ch, CURLOPT_HEADER, 1);  curl_setopt($ch, CURLOPT_RANGE, '0-300'); //从 0 偏移起取 301 的字节//  curl_setopt($ch, CURLOPT_NOBODY, 1);  curl_setopt($ch, CURLOPT_TIMEOUT,5);  curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);  curl_setopt($ch, CURLOPT_REFERER, "http://$t[host]/");  curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiejar);  curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);  curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'head_func');  curl_setopt($ch, CURLOPT_WRITEFUNCTION,"progress_function");  $r = curl_exec($ch);  curl_close($ch);  return $r;}echo '<xmp>';curl_get($url);//回调函数 $str 为读到的内容function progress_function($ch,$str) {//print_r(curl_getinfo($ch));    echo PHP_EOL, strlen($str);//,':',substr($str,0,20);    return strlen($str);}//回调函数,用于获得头信息function head_func($ch, $str) {echo $str;    return strlen($str);}

头信息中类似
Content-Length: 301
Content-Range: bytes 0-300/1806285
这样的玩意就很有用了(不支持断点续传的就没有这个,比如 http://bbs.csdn.net/topics/390455233)

你那个url不支持断点续传!
我贴段测试代码,供你研究。但要达到实用还很要花点功夫

感谢老大指点,基本原理明白了,自己写了一个程序。

function curl_115($durl,$saveto,$range){	$ch = curl_init();	curl_setopt($ch, CURLOPT_URL, $durl);	curl_setopt($ch, CURLOPT_RANGE, ''.(($range-1)*1024*1024).'-'.($range*1024*1024-1).'');//每次保存10MB	curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 	curl_setopt($ch, CURLOPT_HEADER, 0);	$out = curl_exec($ch);	curl_close($ch);	file_put_contents($saveto, $out, FILE_APPEND);}function check_url_115($durl){	$handle = curl_init($durl);	curl_setopt($handle,  CURLOPT_RETURNTRANSFER, TRUE);	curl_setopt($handle, CURLOPT_TIMEOUT,5);	$response = curl_exec($handle);	$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);	curl_close($handle);	return $httpCode;}if(check_url_115($url)=='200'){	curl_115($url,'1.rar',1);}else{	echo '手动更换URL';}


利用file_put_contents的FILE_APPEND来断点保存文件

有一点不很自信,手动更改$range值,即CURLOPT_RANGE   ''.(($range-1)*1024*1024).'-'.($range*1024*1024-1).'', 这个计算对吗?

按照你的注释,
如果$range=1,则 0-1048575 //从 0 偏移起取 1048576 的字节
如果$range=2,则 1048576-2097151 //从 1048576 偏移起取到2097152的字节

这样的话,注释里有2个1048576,会不会重复保存导致最后的rar文件被破坏?


此外 if(check_url_115($url)=='200')  这个判断基本没什么用处,这里还有一个恐怖的问题,即CURLINFO_HTTP_CODE = 200,但下载到一半时URL失效,下一次的CURLOPT_RANGE就不是10M的倍数了。
方案一:保守一点$range每改10次,手动跟新一次URL地址。
方案二:干脆不要限制10M,利用PHP的filesize(),URL失效后读取保存到硬盘的rar大小,然后再手动设置CURLOPT_RANGE,但是害怕filesize()取出的值真的等于CURLOPT_RANGE重新开始的值吗?这个精确到字节的数字,万一有什么偏移,整个rar还是给毁了。


望进一步指点,谢谢。

前面 snmr_com 已经讲了,需要保存 文件的位置
这一点很重要!

不要简单的利用现有函数,计算偏移是成功的前提
覆盖没有关系,错位就事关重大了

你可以用手工或工具下载一个,用程序下载一个。对比两个文件的 md5 就知道程序的正确性了

哦,继续测试中……

连夜测试,代码可行,但是很费劲,分10MB保存,分了30多次抓取,每次抓取后害怕出错分别备份...关键是这玩意不支持curl multi,要是能支持的话,迅雷就可以搞定,另外下了个115浏览,居然提示非手机注册不支持。
花了2天时间,就为了一个U2专辑……

总结:PHP还是做服务器端,60秒内可以搞定的事务;像115下载之类的,还是得交给C类语言编译的软件才是正道。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn