2013-02-06 80 views
2

我想抓取一個網站搜索信息,我的腳本適用於正常頁面,但如何抓取登錄受保護的頁面?我有登錄信息,我如何發送這個信息與網址? 我的代碼:如何抓取登錄保護頁面?

crawl_page("http://www.site.com/v3/search/results?start=1&sortCol=MyDefault"); 
function crawl_page($url) { 
    $html = file_get_contents($url); 
    preg_match_all('~<a.*?href="(.*?)".*?>~', $html, $matches); 
    $str = "http://www.site.com/v3/features/id?Profile="; 
    foreach($matches[1] as $newurl) { 
     if (strpos($newurl, $str) !== false) { 
     $my_file = 'link.txt'; 
     $handle = fopen($my_file, 'a') or die('Cannot open file: '.$my_file); 
     $numberNewline = $newurl . PHP_EOL; 
     fwrite($handle, $numberNewline); 
     } 
    } 
} 

任何幫助 感謝。

+1

將用戶名和密碼組合功能放入您的搜尋器中。隨着一個非常長的隨機不可猜測的密碼。很確定,如果不登錄,您無法抓取安全網頁。這會打破目的。 – PenguinCoder

+7

自動調情?聽起來就像你試圖濫用這個系統。 – Joe

+0

我有用戶名和密碼 – Shawon

回答

1

這在很大程度上取決於所使用的身份驗證方法。最簡單的是HTTP基本身份驗證。對於這種方法,你只需要建立一個背景是這樣的:

$context = stream_context_create(array(
    'http' => array(
     'header' => "Authorization: Basic " . base64_encode("$username:$password") 
    ) 
)); 
$data = file_get_contents($url, false, $context); 

這樣一來,會的file_get_contents使用HTTP基本身份驗證。

其他auth方法可能需要更多的工作,例如通過POST發送密碼登錄頁面和存儲會話cookie。

0

我的答案只適用於表單身份驗證(這是最常見的身份驗證形式)。

基本上,當你瀏覽一個網站時,你會在其上打開一個「會話」。當你在網站上登錄時,你的會話將被「認證」,並且基於此你將被授予訪問權限。

由於存儲在cookie中的會話ID,您的瀏覽器可以識別與服務器相應的會話。

所以你必須瀏覽登錄頁面,然後瀏覽你想要的頁面,而不忘記在這個過程中發送cookie。 Cookie是您瀏覽的所有網頁之間的鏈接。

我實際上遇到了你剛剛做的同樣的問題,並寫了一個類來做到這一點,而不必記住這個cookie的事情。

快速看看課堂,這不重要,但請看下面的例子。它允許您提交實施CSRF保護的表單。

該類基本上具有以下功能: - 符合基於CSRF令牌的保護 - 發送「通用」用戶代理。某些網站拒絕不與用戶代理通信的查詢 - 發送推薦頭。一些網站拒絕不通信的引用(這是另一個反CSRF保護) 查詢 - 各地的商店中調用

文件餅乾:WebClient.php

<?php 
/** 
* Webclient 
* 
* Helper class to browse the web 
* 
* @author Bgi 
*/ 

class WebClient 
{ 
    private $ch; 
    private $cookie = ''; 
    private $html; 

    public function Navigate($url, $post = array()) 
    { 
     curl_setopt($this->ch, CURLOPT_URL, $url); 
     curl_setopt($this->ch, CURLOPT_COOKIE, $this->cookie); 
     if (!empty($post)) { 
      curl_setopt($this->ch, CURLOPT_POST, TRUE); 
      curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post); 
     } 
     $response = $this->exec(); 
     if ($response['Code'] !== 200) { 
      return FALSE; 
     } 
     //echo curl_getinfo($this->ch, CURLINFO_HEADER_OUT); 
     return $response['Html']; 
    } 

    public function getInputs() 
    { 
     $return = array(); 

     $dom = new DOMDocument(); 
     @$dom->loadHtml($this->html); 
     $inputs = $dom->getElementsByTagName('input'); 
     foreach($inputs as $input) 
     { 
      if ($input->hasAttributes() && $input->attributes->getNamedItem('name') !== NULL) 
      { 
       if ($input->attributes->getNamedItem('value') !== NULL) 
        $return[$input->attributes->getNamedItem('name')->value] = $input->attributes->getNamedItem('value')->value; 
       else 
        $return[$input->attributes->getNamedItem('name')->value] = NULL; 
      } 
     } 

     return $return; 
    } 

    public function __construct() 
    { 
     $this->init(); 
    } 

    public function __destruct() 
    { 
     $this->close(); 
    } 

    private function init() 
    { 
     $this->ch = curl_init(); 
     curl_setopt($this->ch, CURLOPT_USERAGENT, "Mozilla/6.0 (Windows NT 6.2; WOW64; rv:16.0.1) Gecko/20121011 Firefox/16.0.1"); 
     curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, TRUE); 
     curl_setopt($this->ch, CURLOPT_MAXREDIRS, 5); 
     curl_setopt($this->ch, CURLINFO_HEADER_OUT, TRUE); 
     curl_setopt($this->ch, CURLOPT_HEADER, TRUE); 
     curl_setopt($this->ch, CURLOPT_AUTOREFERER, TRUE); 
    } 

    private function exec() 
    { 
     $headers = array(); 
     $html = ''; 

     ob_start(); 
     curl_exec($this->ch); 
     $output = ob_get_contents(); 
     ob_end_clean(); 

     $retcode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE); 

     if ($retcode == 200) { 
      $separator = strpos($output, "\r\n\r\n"); 

      $html = substr($output, $separator); 

      $h = trim(substr($output,0,$separator)); 
      $lines = explode("\n", $h); 
      foreach($lines as $line) { 
       $kv = explode(':',$line); 

       if (count($kv) == 2) { 
        $k = trim($kv[0]); 
        $v = trim($kv[1]); 
        $headers[$k] = $v; 
       } 
      } 
     } 

     // TODO: it would deserve to be tested extensively. 
     if (!empty($headers['Set-Cookie'])) 
      $this->cookie = $headers['Set-Cookie']; 

     $this->html = $html; 

     return array('Code' => $retcode, 'Headers' => $headers, 'Html' => $html); 
    } 

    private function close() 
    { 
     curl_close($this->ch); 
    } 
} 

我如何使用它?

在這個例子中,我登錄到網站,然後瀏覽到包含一個表單來上傳文件的頁面,然後我上傳的文件:

<?php 
    require_once('WebClient.php'); 
    $url = 'http://example.com/administrator/index.php'; // This a Joomla admin 

    $wc = new WebClient(); 
    $page = $wc->Navigate($url); 
    if ($page === FALSE) { 
     die('Failed to load login page.'); 
    } 

    echo('Logging in...'); 

    $post = $wc->getInputs(); 
    $post['username'] = $username; 
    $post['passwd'] = $passwd; 

    $page = $wc->Navigate($url, $post); 
    if ($page === FALSE) { 
     die('Failed to post credentials.'); 
    } 

    echo('Initializing installation...'); 

    $page = $wc->Navigate($url.'?option=com_installer'); 
    if ($page === FALSE) { 
     die('Failed to access installer.'); 
    } 

    echo('Installing...'); 

    $post = $wc->getInputs(); 
    $post['install_package'] = '@'.$file; // The @ specifies we are sending a file 

    $page = $wc->Navigate($url.'?option=com_installer&view=install', $post); 
    if ($page === FALSE) { 
     die('Failed to upload file.'); 
    } 

    echo('Done.'); 

的導航()方法將返回FALSE要麼瀏覽頁面的HTML內容。

呵呵,還有最後一件事:不要用正則表達式來解析HTML,這是錯誤的。有一個傳說中的StackOverflow答案:請參閱here

+0

我使用您的代碼,但其顯示'無法發佈憑證。'有什麼方法可以使用瀏覽器cookie嗎? – Shawon

+0

你確定你正確識別了輸入的名稱(在我的情況下,它是用戶名和密碼,但它可能在你的網站上不同)...你應該嘗試調試標題 – Bgi