項目中經常用到頁面抓取的功能,頁面抓取的過程往往會出現兩種常見的問題
1、頁面編碼不統一,本地是utf-8,抓取的頁面是gbk等,導致抓取過來的出現亂碼
2、有些網站用了壓縮技術,針對頁面進行壓縮,gzip壓縮,這也導致抓取結果就異常
經過在網上搜尋相關解決方案及本地測試,現整理一下相關功能,便後繼使用。同時也放到了github上,地址:https://github.com/lock-upme/Spider
主程式簡單說明一下:
先是用file_get_contents抓取,如果抓取不到,則再用Snoopy來抓取,最後進行編碼轉換。
程式見下:
/** * 抓取頁面內容 * * $obj = new spider() * $result = $obj->spider('http://www.test.com/1.html'); * * @author lock */class Spider {/** *抓取頁面內容 * * @param string $url * @return string */public function spider($url) {set_time_limit(10);$result = self::fileGetContents($url);if (empty($result)) {$result = self::snoopy($url);}if (empty($result)) {return false;}$result = self::array_iconv($result);if (empty($result)) {return false;}$result = str_replace("\n", "", $result);return $result;}/** * 擷取頁面內容 * * @param string $url * @return string */public function fileGetContents($url) {//唯讀2位元組 如果為(16進位)1f 8b (10進位)31 139則開啟了gzip ;$file = @fopen($url, 'rb');$bin = @fread($file, 2);@fclose($file);$strInfo = @unpack('C2chars', $bin);$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);$url = ($typeCode==31139) ? 'compress.zlib://'.$url:$url; // 三元運算式return @file_get_contents($url);}/** * 擷取頁面內容 * * @param string $url * @return string */public function snoopy($url){require_once 'Snoopy.class.php';$snoopy = new Snoopy;$snoopy->agent = 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36';$snoopy->_fp_timeout = 10;$urlSplit = self::urlSimplify($url);$snoopy->referer = $urlSplit['domain'];$result = $snoopy->fetch($url);return $snoopy->results; }/** *對資料進行編碼轉換(來自網路) * * @param array/string $data 數組 * @param string $output 轉換後的編碼 * @return 返回編碼後的資料 */public function array_iconv($data, $output = 'utf-8') {$encodeArr = array('UTF-8', 'ASCII', 'GBK', 'GB2312', 'BIG5', 'JIS', 'eucjp-win', 'sjis-win', 'EUC-JP');$encoded = mb_detect_encoding($data, $encodeArr);if (empty($encoded)) { $encoded='UTF-8'; }if (!is_array($data)) {return @mb_convert_encoding($data, $output, $encoded);} else {foreach ($data as $key=>$val) {$key = self::array_iconv($key, $output);if (is_array($val)) {$data[$key] = self::array_iconv($val, $output);} else {$data[$key] = @mb_convert_encoding($data, $output, $encoded);}}return $data;}}}