如何把一個線上的網站抓下來成為全靜態網頁 === 作者:台灣碼農 目的:各位前端設計師是否有這樣的需求?要抓下一整個網站,保留其原本目錄結構,存為全靜態網頁,並且點擊連結要跳到相對應頁面。 一個網站正常成型=>草圖=>設計=>前端工程師:純html切版=>後端工程師套版=>完工 我一個在隔壁公司上班的朋友,估且稱他為,連作品都沒有的前端,我問?你作品都有沒有保留的?他答上線的東西就沒辦法再搞回全靜態網頁了。 原來他不會!ㄎㄎ !有方法的!連那種要登入才能看到的頁面都能抓下來。 1. 使用ChromeCacheView.exe 這個工具 把我瀏覽過的網頁,依照原本的目錄結構抓下來 2. 搭配一個.htaccess檔案 讓抓下來的靜態網頁 點擊連結都能要跳到相對應頁面 ---------------------------------------- ChromeCacheView 工具下載處 [[英文版]](http://www.nirsoft.net/utils/chrome_cache_view.html) [[中文版]](https://freewarehome.tw/pc/chromecacheview/) ![ChromeCacheView](https://i.imgur.com/tI0q7mp.jpg) ![ChromeCacheView3](https://i.imgur.com/eeEBnjY.jpg) ![ChromeCacheView2](https://i.imgur.com/34N2NfZ.jpg) ChromeCacheView 是一款小巧的工具程式,可讀取 Google Chrome 網頁瀏覽器的暫存區或快取 (cache) 資料夾,並顯示目前儲存在快取中的所有檔案。對於快取中的每個檔案,程式會顯示下列資訊:網址、內容類型、檔案大小、最後修改時間、最後存取時間、存取次數、失效時間、伺服器名稱以及其他資料。 因此,您可以輕易地選取快取清單中一個或多個項目,然後將這些檔案 保存下來 ---------------------------------------- 我舉例網上一個別人的網站網址結構如下 ---------------------------------------- 首頁 https://coinp2p.io/ 登入 https://coinp2p.io/Login 註冊 https://coinp2p.io/Register 所有刊登 https://coinp2p.io/ItemList/ 刊登內容頁 https://coinp2p.io/ItemDetail?Item_id=121576994 我要刊登 https://coinp2p.io/PostItem 幫助 參考現價 https://coinp2p.io/CoinPrice 問題回報 https://coinp2p.io/Report 帳號設定 https://coinp2p.io/AccountSettings ---------------------------------------- 使用ChromeCacheView.exe 這個工具 抓下來的檔案結構會是 ---------------------------------------- 首頁 / 登入 /Login.html 註冊 /Register/Report.html 所有刊登 /ItemList/ItemList.html 刊登內容頁 /ItemDetail.html 我要刊登 /PostItem/PostItem.html 幫助 參考現價 /CoinPrice/CoinPrice.html 問題回報 /Report/Report.html 帳號設定 /AccountSettings/AccountSettings.html ---------------------------------------- 該如何做呢-我們要利用 .htaccess 簡化網址的原理 === ``` 為了簡化網址或是為了安全理由, 會希望將副檔名隱藏. 也就是說原本 http://www.xxx.yyy/test.php 只需要 http://www.xxx.yyy/test 就可以連上, 這樣可以讓網站所有連結都不出現副檔名 這就像yahoo的新服務 知識+ 一樣裡頭的連結完全沒出現.php 下面講一下我找到的設定方法 1. 到apache的http.conf找到下面這行 #LoadModule rewrite_module modules/mod_rewrite.so 這一行註解拿掉 LoadModule rewrite_module modules/mod_rewrite.so 於是rewrite_mod模組啟動了! (他的功用請參考官方資訊) 2. 在 http.conf加入 AllowOverride all #這行的意思是說, 允許 .htaccess 檔的內容覆蓋這邊的設定 Order allow,deny Allow from all 3. 新增一個 .htaccess檔在剛剛的目錄底下, 在裡頭寫入 Options +FollowSymlinks #下行是設定要不要啟用rewrite engine, 這是runtime的設定檔,不需restartserver RewriteEngine on #下行是將檔名中沒有slash 和 . 的檔名, 轉向到 .php的檔案 RewriteRule ^([^./]+)/?$ $1.php [L] 4. 剛剛已經針對某個目錄做設定, 之後若底下的子目錄也要有同樣功能 ,請再將 .htaccess檔直接複製到要套用的子目錄即可 ``` 更多關於.htaccess檔案的參數用法 === http://fecbob.pixnet.net/blog/post/38253781-apache-rewrite%E5%AF%A6%E7%8F%BEurl%E7%9A%84%E8%B7%B3%E8%BD%89%E5%92%8C%E5%8A%9F%E8%83%BD%E8%AE%8A%E6%95%B8%E5%90%8D%E7%A8%B1%E8%B7%B3%E8%BD%89- 當然上面的例子是 php 用的 我們html靜態頁面用的.htaccess不一樣 === 方法1 思路 === ``` 無論/app 或 /app/ 都跳=> /app/app.htm http://h61.test.com/miner/?coin=btc 會=> http://h61.test.com/miner/miner.htm?coin=btc ``` ## .htaccess檔案 內容 修改如下 ``` #超級模擬原網站結構 # 打開重寫引擎 RewriteEngine on # 設定基準目錄,從根目錄開始比對 RewriteBase / #要排除不比對的目錄 RewriteRule ^(application|system) - [F,L] # 重新比對網址,若請求的檔案不存在。 RewriteCond %{REQUEST_FILENAME} !-f # 重新比對網址,倘若請求網址是資料夾。只有當目標的檔名不是一個資料夾時,才讓下方的改寫規則作用。 #RewriteCond %{REQUEST_FILENAME} !-d # INDEX.HTML的規則保留 不用打副檔名可以呼叫到的規則保留 # 無論/app 或 /app/ 都跳=> /app/app.htm RewriteRule ^(.*)/$ $1/$1.htm [L] #http://h61.test.com/miner/?coin=btc 會=>http://h61.test.com/miner/miner.htm?coin=btc ``` 方法2 思路 === ``` -單層目錄結構處理法 把單層目錄的檔案拷貝到根目錄下 1.打/ 跳到首頁 index.html 2.http://h62.test.com/ItemList/ => http://h62.test.com/ItemList ``` ## .htaccess檔案 內容 修改如下 ``` Options +FollowSymlinks #超級模擬原網站結構 # 打開重寫引擎 RewriteEngine on # 設定基準目錄,從根目錄開始比對 RewriteBase / #要排除不比對的目錄 RewriteRule ^(application|system) - [F,L] # 重新比對網址,若請求的檔案不存在。 RewriteCond %{REQUEST_FILENAME} !-f # 重新比對網址,倘若請求網址是資料夾。只有當目標的檔名不是一個資料夾時,才讓下方的改寫規則作用。 RewriteCond %{REQUEST_FILENAME} !-d # INDEX.HTML的規則保留 不用打副檔名可以呼叫到的規則保留 # 把網址的/去掉 RewriteRule ^(.*)[/]$ $1 [R] ``` 我後來又把檔案修改如下 ## .htaccess檔案 內容 修改如下 ``` <IfModule rewrite_module> RewriteEngine On # 去吧 強制走https .* #RewriteCond %{HTTPS} !=on #RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [END,R=301] # 找看看 .htm 檔案 RewriteCond %{REQUEST_FILENAME}.htm -s RewriteRule . %{REQUEST_FILENAME}.htm [END] RewriteCond %{REQUEST_FILENAME}.html -s RewriteRule . %{REQUEST_FILENAME}.html [END] # 再找看看 .php 檔案 RewriteCond %{REQUEST_FILENAME}.php -s RewriteRule . %{REQUEST_FILENAME}.php [END] </IfModule> ``` ## 這個方法還要搭配一支移動檔案的程式 動作會把所有*.html 拷貝到上1層目錄,最多處理3層目錄 好處:可以刪掉多餘的子目錄 壞處:這支程式只能執行一次,不行執行2次 php判斷並刪除空目錄及空子目錄的方法 ```php <?php /* 2017/10/05 動作會把所有*.html 拷貝到上1層目錄,最多處理3層目錄 好處:可以刪掉多餘的子目錄 壞處:這支程式只能執行一次,不行執行2次 php判斷並刪除空目錄及空子目錄的方法 */ header("Content-Type:text/html;charset=utf-8");//全程式總編碼指定 date_default_timezone_set('Asia/Taipei');//設定系統時區 $brn="<br>\n"; $thisDir = "."; //config.inc.php檔的相對路徑 $_file = basename(__FILE__); //自行取得本程式名稱 $config['sdir']=dirname(__FILE__);// 將目前的目錄變更為 dirname(__FILE__) $dirall_a=array(); $dirall=array(); $dirall3=array(); //函式功能 列出該路徑下所有的檔案包含子目錄 function get_dir_list($dir){//&$a 檔案加總變數 傳址參數,$dir 資料夾路徑 global $dirall_a;//注意這行 if(is_dir($dir)){//如果是資料夾才執行 $dh = opendir($dir);//打開資料夾 chdir ($dir);//指定目錄 while (($file = readdir($dh)) !== false) {//列出該目錄的所有檔案 $fileb=pathinfo ( $file , PATHINFO_EXTENSION );// =>取得副檔名 if (is_dir($file) && basename($file)!='.' && basename($file)!='..'){//若是資料夾 且非 . .. 就在呼叫自已一次 get_dir_list2($file); }else if($file != "." && $file != ".." && empty($fileb)){//若非 . .. 又沒有副檔名 $dirall_a[]=$file;//輸出 完整檔案路徑檔名 } } closedir($dh);//關閉資料夾 } } //函式功能 列出該路徑下所有的檔案包含子目錄 function get_dir_list2($dir){//&$a 檔案加總變數 傳址參數,$dir 資料夾路徑 global $dirall;//注意這行 $files = array(); if($handle = opendir($dir)) { while(false !== ($file = readdir($handle))){ $fileb=pathinfo ( $file , PATHINFO_EXTENSION );// =>取得副檔名 $curfile = $dir.'/'.$file; // 當前目錄 //print_r($file);exit; if((string)$file === "." or (string)$file === ".."){ }elseif(is_dir($curfile)){ //print_r($file);echo"|"; get_dir_list3($curfile); }else if($fileb=='html' or $fileb=='htm' ){ $dirall[]=$curfile;//輸出 完整檔案路徑檔名 //移動到上1層目錄 $fb=dirname(dirname($curfile))."/".$file; phprename($curfile,$fb);//更名 }else if( empty($fileb) ){ //沒副檔名的 $dirall[]=$curfile;//輸出 完整檔案路徑檔名 phprename($curfile,$curfile.".html");//更名 }else{ } } closedir($handle); } } //子子目錄 function get_dir_list3($dir){//&$a 檔案加總變數 傳址參數,$dir 資料夾路徑 global $dirall3;//注意這行 //echo "運行第3層目錄".$dir."|"; if($handle3 = opendir($dir)) { while(false !== ($file = readdir($handle3))){ $fileb=pathinfo ( $file , PATHINFO_EXTENSION );// =>取得副檔名 //print_r($fileb); $curfile = $dir.'/'.$file; // 當前目錄加檔案名 if((string)$file === "." or (string)$file === ".."){ }else if(is_dir($curfile)){ //還是目錄不處理 }else if($fileb=='html' or $fileb=='htm' ){ $dirall3[]=$curfile;//輸出 完整檔案路徑檔名 //移動到上1層目錄 $fb=dirname(dirname($curfile))."/".$file; phprename($curfile,$fb);//更名 }else if( empty($fileb) ){ //沒副檔名的 $dirall3[]=$curfile;//輸出 完整檔案路徑檔名 phprename($curfile,$curfile.".html");//更名 }else{ } } closedir($handle3); } } //php判斷並刪除空目錄及空子目錄的方法 /** 刪除所有空目錄 * @param String $path 目錄路徑 */ function rm_empty_dir($path){ if(is_dir($path) && ($handle = opendir($path))!==false){ while(($file=readdir($handle))!==false){ // 遍歷文件夾 if($file!='.' && $file!='..'){ $curfile = $path.'/'.$file; // 當前目錄 if(is_dir($curfile)){ // 目錄 rm_empty_dir($curfile); // 如果是目錄則繼續遍歷 if(count(scandir($curfile))==2){ // 目錄為空,=2是因為. 和 ..存在 rmdir($curfile); // 刪除空目錄 } } } } closedir($handle); } } //複製檔案 function phpcopy($path1,$path2){ if (copy($path1, $path2)) { // 檔案複製成功 } else { // 檔案複製失敗 } } //複製更名檔案 function phprename($path1,$path2){ if (rename($path1, $path2)) { // 檔案複製成功 echo "移動檔案".$path1."=>".$path2."<br>\n"; } else { echo "移動檔案失敗"; } } get_dir_list($config['sdir']); echo "根目錄檔案"; print_r($dirall_a); if(count($dirall_a)>0){ for($i=0;$i<count($dirall_a);$i++){ $a=$dirall_a[$i]; $b=$a.".html"; echo "修改檔名".$a."=>".$b; phprename($a,$b); } } //echo "子目錄檔案"; //print_r($dirall); echo "第1層目錄".$brn; echo "<pre>\n"; print_r($dirall); echo "</pre>\n"; echo "第2層目錄".$brn; echo "<pre>\n"; print_r($dirall3); echo "</pre>\n"; echo "將.html檔案全部移動到上一層目錄".$brn; echo "刪除所有空目錄".$brn; rm_empty_dir($config['sdir']);//刪除所有空目錄 ?> ``` 失敗的原因 === 1.你的伺服器根本不吃.htaccess 設定 2.apache 沒有 httpd的rewrite模組(mod_rewrite) # httpd.conf 設定有問題 ``` win版有此行 LoadModule rewrite_module modules/mod_rewrite.so LINUX版有如何在CentOS 7 Apache设置mod_rewrite httpd -M 如果rewrite_module不会在输出里出现,通过编辑使它00-base.conf文件vi编辑: [https://www.howtoing.com/how-to-set-up-mod-rewrite-for-apache-on-centos-7/](https://www.howtoing.com/how-to-set-up-mod-rewrite-for-apache-on-centos-7/) <Directory /var/www/html> AllowOverride All </Directory> <IfModule dir_module> DirectoryIndex index.php index.html index.htm </IfModule> ``` 成功範例 === [http://h63.bkk.tw/](http://h63.bkk.tw/) ## 將線上的網站抓下來成為全靜態網頁的方法 這只是我想出方法3個當中其中一個,在LINE台灣工程師快滿500人的群中,3個月來僅有碼農,瓜瓜,凱大,Eddie 少數人分享過教學,讓我感覺台灣工程師技術交流的程度遠不及對岸,特此拋磚引玉,看有沒有人可以提出其他種寫法。(使用hackmd共享筆記會比較容易打字) 本筆記hackmd網址 === https://hackmd.io/s/SycHsoznZ 本筆記github位置 === https://github.com/suffixbig/ChromeCacheView