2013-02-06 82 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