前面发了一帖,《发个原创小工具,下载autohome 论坛帖子离线浏览》,用的C# WINFORM写的,现在来个PHP版的
分析过程就不说了,和前帖是一样,只不过用PHP代码来实现了而已,关键的地方我加了注释。
1 <?php 2 set_time_limit(0);//防止超时 3 /* by longware@gmail.com */ 4 function getHttpContentBySock($url, $referer=""){//获取http请求的内容,包括可以获取html和二进制的图片 5 $info = parse_url($url); 6 $referer = empty($referer) ? $url : $referer; 7 $contents = ''; 8 9 $fp = fsockopen($info['host'], 80, $errno, $errstr, 30); 10 if (!$fp) { 11 echo " $errstr ($errno) <br />\n"; 12 } else { 13 $out = "GET $url HTTP/1.1\r\n"; 14 $out .= "Host: ".$info['host']."\r\n"; 15 $out .= "Connection: Keep-Alive\r\n"; 16 $out .= "User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)\r\n"; 17 $out .= "Accept: */*\r\n"; 18 $out .= "Referer: $referer\r\n";//这个不能少 19 $out .= "Accept-Language: zh-CN,zh;q=0.8\r\n"; 20 $out .= "Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3\r\n\r\n"; 21 22 fwrite($fp, $out); 23 24 $line = 1; $flag = false; 25 while (!feof($fp)) { 26 $tmp = fgets($fp, 2048); 27 if($line>1){ 28 if($flag){ 29 $contents .= $tmp; 30 }else{ 31 if (strlen(trim($tmp))<1) {//去掉http response的头文本 32 $flag = true; 33 } 34 } 35 } 36 $line++; 37 } 38 fclose($fp); 39 } 40 41 return $contents; 42 } 43 44 /* by longware */ 45 function writeContent($url, $page){//写文件 46 $html = getHttpContentBySock($url,$url); 47 48 $pattern = "/src9=\"http:\/\/[a-zA-Z0-9_\.\/]+\"/";//正则匹配图片网址 49 preg_match_all($pattern, $html, $matches, PREG_PATTERN_ORDER); 50 //print_r($matches); 51 52 $search = array('"', 'src9='); 53 foreach ($matches as $matche_array) {//获取真实图片网址 54 foreach ($matche_array as $matche_line) { 55 $imgurl = str_replace($search,'',$matche_line); 56 $path_info = explode("//", $imgurl); 57 $dir = "./".dirname($path_info[1])."/";//按网址的路径建目录 58 if (!is_dir($dir)) { 59 mkdir($dir,0777,true); 60 } 61 $filename = "./".$path_info[1]; 62 file_put_contents($filename, getHttpContentBySock($imgurl,$url) );//获取图片并写文件 63 echo $filename."<br>\r\n"; 64 } 65 } 66 67 //replace href 替换无用代码 68 $html = str_replace('src="http://x.autoimg.cn/club/lazyload.png" src9="','src="', $html); 69 $html = str_replace('http://','./',$html); 70 $html = str_replace('onload=','x1=',$html); 71 $html = str_replace('onerror=','x2=',$html); 72 $html = str_replace('<script','<a style="display:none" ',$html); 73 $html = str_replace('</script','</a',$html); 74 75 $filename = "./threadowner-o-200042-19582947-".$page.".html";//threadowner-o-200042-19582947-2.html 写本地html文件 76 file_put_contents($filename, $html); 77 echo $filename."--------------------------------------------<br>\r\n"; 78 } 79 /* by longware */ 80 //main 81 if( empty($_SERVER['argv'][1]) || empty($_SERVER['argv'][2]) ){die('input args');} 82 $url = "http://club.autohome.com.cn/bbs/threadowner-o-200042-19582947-#.html";//主帖URL规律 83 $min = $_SERVER['argv'][1];//下载起始页 84 $max = $_SERVER['argv'][2];//下载结束页 85 //print_r($_SERVER['argv']); 86 for ($i = $min; $i <= $max; $i++) { 87 writeContent( str_replace('#',$i,$url), $i ); 88 } 89 /* by longware */ 90 ?>
以上代码保存为bbs.php,然后建立一个down.cmd文件,内容如下
d:\WebServer\php\php.exe D:\wwwroot\autohome\bbs.php 1 100
双击down.cmd文件,让他慢慢下载吧。
如果要通过浏览器访问,把其中的$min和$max改为$_REQUEST['min']和$_REQUEST['max']即可,毕竟cmd方式比浏览器要稍稍快一点。
不过PHP的效率比winform要低很多很多,因为PHP中没有现成的多线程。