PHP抓取網頁和分析

有些網頁的內容是常常變動的,但是又不可能一直盯著看,所以研究看看怎麼用 PHP 抓取網頁內容。
From:http://my.opera.com/kmgocc/blog/show.dml/322416
http://272586.blogspot.com/2007/05/php.html
http://www.fantxi.com/blog/show-618-1.html
http://www.inote.tw/2009/04/php-curl.html

譯者:limodou
抓取和分析一個文件是非常簡單的事。這個教程將通過一個例子帶領你一步一步地去實現它。讓我們開始吧!
首先,首先必須決定我們將抓取的URL地址。可以通過在腳本中設定或通過$QUERY_STRING傳遞。為了簡單起見,讓我們將變量直接設在腳本中。

<?
$url = 'http://www.php.net';
?>

第二步,我們抓取指定文件,並且通過file()函數將它存在一個數組裡。

<?
$url = 'http://www.php.net';
$lines_array = file($url);
?>

好了,現在在數組裡已經有了文件了。但是,我們想分析的文本可能不全在一行裡面。為瞭解決這個文件,我們可以簡單地將數組$lines_array轉化成一個字符串。我們可以使用implode(x,y)函數來實現它。如果在後面你想用explode(將字符串變量數組),將x設成"|"或"!"或其它類似的分隔符可能會更好。但是出於我們的目的,最好將x設成空格。y是另一個必要的參數,因為它是你想用implode()處理的數組。

<?
$url = 'http://www.php.net';
$lines_array = file($url);
$lines_string = implode('', $lines_array);
?>

現在,抓取工作就做完了,下面該進行分析了。出於這個例子的目的,我們想得在<head>到</head>之間的所有東西。為了分析出字符串,我們還需要叫做正規表達式的東西。

<?
$url = 'http://www.php.net';
$lines_array = file($url);
$lines_string = implode('', $lines_array);
eregi("<head>(.*)</head>", $lines_string, $head);
?>

讓我們看一下代碼。正如你所見,eregi()函數按下面的格式執行:

eregi("<head>(.*)</head>", $lines_string, $head);

"(.*)"表示所有東西,可以解釋為,"分析在<head>和</head>間的所以東西"。$lines_string是我們正在分析的字符串,$head是分析後的結果存放的數組。
最後,我們可以輸數據。因為僅在<head>和</head>間存在一個實例,我們可以安全的假設數組中僅存在著一個元素,而且就是我們想要的。讓我們把它打印出來吧。

<?
$url = 'http://www.php.net';
$lines_array = file($url);
$lines_string = implode('', $lines_array);
eregi("<head>(.*)</head>", $lines_string, $head);
echo $head[0];
?>

轉自WeberDev.com
如何抓取網站的內容,並解析其內容

<?
$http="http://272586.blogspot.com"; //您想抓取的網址
$buffer = file($http); //將網址讀入buffer變數
for($i=0;$i<sizeof($buffer);$i++) //將每段文字讀出來,以換行為單位,sizeof會傳回共有幾筆
{
$n1=strpos(" ".$buffer[$i],"<title>"); //檢查你要找的字,是否存在,假設我想找<title>中的內容為何,為什麼前面要加空白,因為如果找到位置如果是第一個位置是0,0跟找不到在判斷會有問題
if($n1>0)
{
$n2=strrpos($buffer[$i],"</title>"); //找出</title>的位置
$title=substr($buffer[$i],$n1+6,$n2-$n1-6); //+6的意思是<title>的長度減掉前面的一個空白,-6的話是把長度減掉
//utf-8 轉 big5
$title=iconv("UTF-8","big5",$title);
echo $title."<br>n"; //將title的內容值印出n代表顯示原始碼的時候會換行,<BR>是brower顯示會換行
}
}
?>

PHP抓網頁內容
1.file_get_contents

<?
$url = http://www.xxx.com/;
$contents = file_get_contents($url);
//如果出現中文亂碼使用下面代碼
//$getcontent = iconv("gb2312", "utf-8",file_get_contents($url));
//echo $getcontent;
echo $contents;
?>

2.curl
我們必須先建立一個「curl」的連線,也因此,必須使用到「$ch = curl_init()」這個函式。而為了怕建立連線忘了關閉。因此,必須先寫好關閉的函式,「curl_close($ch)」。
接下來,你可以設定他截取網頁的選項,一般來說常用的有「CURLOPT_RETURNTRANSFER」、「CURLOPT_URL」、「CURLOPT_HEADER」、「CURLOPT_FOLLOWLOCATION」、「CURLOPT_USERAGENT」這幾個選項。而這幾個選項分別代表「將結果回傳成字串」、「設定截取網址」、 「是否截取header的資訊」、「是否抓取轉址」及「瀏覽器的user agent」。最後,再執行「curl_exec($ch)」以取出結果就可以了。

<?
$url = "http://www.xxx.com/";
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
//在需要用戶檢測的網頁裡需要增加下面兩行
//curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
//curl_setopt($ch, CURLOPT_USERPWD, US_NAME.":".US_PWD);
$contents = curl_exec($ch);
curl_close($ch);
echo $contents;
?>

以抓取yahoo為例,若我們要偽裝成google bot去抓取,那麼我們可以寫成下列的樣子:

$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, "www.yahoo.com.tw");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_USERAGENT, "Google Bot");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$output = curl_exec($ch);
curl_close($ch);
echo $output;

也可以將選項們設定一個陣列,以增加設定時的閱讀度。這時就得動用「curl_setopt_array()」這個函式了:

$ch = curl_init();
$options = array(CURLOPT_URL => 'www.yahoo.com.tw',
                 CURLOPT_HEADER => false,
   CURLOPT_RETURNTRANSFER => true,
   CURLOPT_USERAGENT => "Google Bot",
   CURLOPT_FOLLOWLOCATION => true
           );
curl_setopt_array($ch, $options);
$output = curl_exec($ch);
curl_close($ch);
echo $output;

3.fopen->fread->fclose

<?
$handle = fopen ("http://www.xxx.com/", "rb");
$contents = "";
do {
   $data = fread($handle, 8192);
   if (strlen($data) == 0) {
   break;
   }
   $contents .= $data;
} while(true);
fclose ($handle);
echo $contents;
?>
Please follow and like us:

35 comments on “PHP抓取網頁和分析

  1. 補充: 我也試著用其他的方式如SNOOPY
    參考這邊的 http://www.ptt.cc/man/EZsoft/D973/M.1178202364.A.0BB.html 不過結果是一片白
    就連跑最基本的
    include "Snoopy.class.php";
    $snoopy = new Snoopy;
    $snoopy->fetchtext("http://www.php.net/");
    print $snoopy->results;
    $snoopy->fetchlinks("http://www.phpbuilder.com/");
    print $snoopy->results;
    也是完全沒有畫面
    PHP確定測試正常 PHPinfo(); 是有資料的
    url
    cURL support enabled
    cURL Information 7.19.7
    Age 3
    Features
    AsynchDNS No
    Debug No
    GSS-Negotiate Yes
    IDN Yes
    IPv6 Yes
    Largefile Yes
    NTLM Yes
    SPNEGO No
    SSL Yes
    SSPI No
    krb4 No
    libz Yes
    CharConv No
    Protocols tftp, ftp, telnet, dict, ldap, ldaps, http, file, https, ftps, scp, sftp
    Host x86_64-redhat-linux-gnu
    SSL Version NSS/3.14.0.0
    ZLib Version 1.2.3
    libSSH Version libssh2/1.4.2
    我不斷的找釣竿 卻連一隻魚都釣不起來 🙁

    • 其實,用 PHP 登入算是機器人程式,很多網站都會盡量防止(最簡單的就是圖形驗證),這本來就是比較困難的一部分。
      因為我用的是 Unix Server,所以我通常會先用 lynx 這種類型的純文字瀏覽器 先連線登入看看,看對方的網站登入是怎麼運作的。如果純文字瀏覽器會有問題,那可能就比較難用 PHP 寫成自動登入程式了(也可能是我功力太差...XD)

  2. 您好 已經依據您說得 用 lynx 確認可以正常登入
    請問這我還可以提供什麼資訊 讓您可以幫助到我
    謝謝!!! 😉
    172.30.34.254 cookie:PHPSESSID=c5fd9a26bfd47842da6274f0087e0169 是否接受? (Y/N/Always/neVer)
    172.30.34.254 cookie:cookie_test=1381989432 是否接受? (Y/N/Always/neVer)
    Username:
    ____________________
    Password:
    ____________________
    Enter username and password to login.
    Login
    transparent
    webConfigurator
    pfsense
    * System
    + Advanced
    + Cert Manager
    + Firmware
    + General Setup
    + High Avail. Sync
    + Logout
    + Packages
    + Routing
    + Setup Wizard
    + User Manager
    * Interfaces

    • 這樣看起來是 cookie 沒錯,因為我沒有試過,可能要請您自己試試看了。^^"

  3. 不好意思 在可以在請問 您知道怎麼把 WGET 轉為CURL嗎
    # wget -qO/dev/null --keep-session-cookies --save-cookies cookies.txt \
    --post-data 'login=Login&usernamefld=admin&passwordfld=pfsense' \
    --no-check-certificate https://192.168.1.1/diag_backup.php
    # wget --keep-session-cookies --load-cookies cookies.txt \
    --post-data 'Submit=download&donotbackuprrd=yes' https://192.168.1.1/diag_backup.php \
    --no-check-certificate -O config-router-`date +%Y%m%d%H%M%S`.xml
    source: https://doc.pfsense.org/index.php/Remote_Config_Backup

    • wget 是抓取檔案,curl 只能抓取資料。
      所以您是想將 wget 抓到的檔案內容做處理囉?
      如果是這樣的話,建議固定 wget 的檔案輸出名稱,然後用 PHP 的 file 函數把檔案讀進來就好了。

  4. 對不起 不是耶!!
    我還是要用CURL做處理
    因為WEGET可以把資料抓下來CURL應該也可以
    目前CURL我卡會出現403的問題
    HTTP/1.1 403 Forbidden Expires: Sun, 20 Oct 2013 02:43:00 GMT Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: max-age=180000 Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-type: text/html Transfer-Encoding: chunked Date: Fri, 18 Oct 2013 00:43:00 GMT Server: lighttpd/1.4.32 CSRF check failed. Either your session has expired, this page has been inactive too long, or you need to enable cookies.
    Debug:
    求解= =

  5. // http://000.000.000.000
    // usernamefld admin
    // passwordfld #00000@0#
    //session_start();
    //$username = 'admin';
    //$password = '#abc@123#';
    $loginUrl = 'http://172.30.34.254/index.php';
    $postUrl='http://172.30.34.254/index.php';
    $user_agent="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6";
    $form_data= 'login=Login&usernamefld=admin&passwordfld=#abc@123#';
    //$ckfile = "./Cookiefile.txt";
    $ckfile = tempnam ("/tmp", "CURLCOOKIE");
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $loginUrl);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);
    curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile);
    curl_setopt($ch, CURLOPT_POST, TRUE);
    //curl_setopt($ch, CURLOPT_POSTFIELDS, 'login=Login&usernamefld=admin&passwordfld=#abc@123#');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
    // curl_setopt($ch, CURLOPT_COOKIE, "A=01;B=02;C=03");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $form_data);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
    curl_setopt($ch, CURLOPT_HEADER, TRUE);
    //curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
    //curl_setopt($ch, CURLOPT_REFERER, $postUrl);
    curl_exec($ch);
    /*
    curl_setopt($ch, CURLOPT_URL, $postUrl);
    curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); */
    $store = curl_exec($ch);
    //curl_exec($ch);
    echo $store;
    curl_close($ch);

    • 不好意思~我有點搞混~
      wget 是下載檔案的吧?所以執行完程式得到的是一個檔案
      但是 curl 執行完不會有檔案出現,只會有資料。
      另外,您給的 wget 的指令可能有些沒有辦法用 curl 實現(參數問題)
      所以我才會想說先跑 wget ,儲存下來的檔案再做處理,這樣就不需要用到 curl 了。
      還是您一定要用 curl 來做?那我可能就幫不上忙了(因為我當初也是 curl 做自動登入,結果失敗)

  6. 恩!!
    我就是因為登入失敗才想說用WGET作 ..預先處理之後再想辦法分析裡面的解果.. 最後顯示在網頁上!!
    CSRF check failed 這個錯誤訊息已經確定是pfsense網頁內的保護措施 可能是防盜連吧. 其實我也不知道這個是衝蝦的
    找不道解決方式前只好先把這個功能給關掉
    php 我不熟是硬湊的方式.完全不熟.目前已經亂湊到可以登入了(停用CSRF).
    接下來要開始想辦法 把資料做整合!!
    這一部份可以向您請教嗎? 謝謝!!

  7. 謝謝您 您沒有會錯意
    不過WGET 一樣會有CSRF問題.. 我已經先跳過這個保護了 ˇ ˇ
    順便分享一下我整理資料的方式 雖不優 不會的人也可以參考 懂的人請指教 謝謝
    目的 提取表格 刪除超連結 刪除斷行 移除圖檔
    Code

    • 抱歉~因為好像是 < a>會判斷異常~我修改了~
      感謝您的分享。^^

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *