3

サイト検索情報をクロールしたいのですが、スクリプトは通常のページでは正常に動作しますが、ログイン保護されたページをクロールするにはどうすればよいですか? ログイン情報がありますが、この情報を URL で送信するにはどうすればよいですか? 私のコード:

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);
       }
    }
}

助けてくれてありがとう。

4

2 に答える 2

1

私の答えは、フォーム認証にのみ適用されます (これは、認証の最も一般的な形式です)。

基本的に、Web サイトを閲覧するときは、その Web サイトで「セッション」を開きます。Web サイトにログインすると、セッションが「認証」され、それに基づいてあらゆる場所へのアクセスが許可されます。

ブラウザは、Cookie に保存されたセッション ID のおかげで、サーバーへの対応するセッションを識別します。

そのため、ログイン ページを参照してから、その過程で Cookie を送信することを忘れずに、必要なページを参照する必要があります。Cookie は、閲覧するすべてのページ間のリンクです。

私は実際にあなたが少し前にしたのと同じ問題に直面し、このクッキーのことを覚えておく必要なしにそれを行うためのクラスを書きました.

クラスをざっと見てください。それは重要ではありませんが、以下の例をよく見てください。CSRF 保護を実装するフォームを送信できます。

このクラスには、基本的に次の機能があります。 - CSRF トークン ベースの保護に準拠 - 「共通」ユーザー エージェントを送信します。一部の Web サイトは、ユーザー エージェントと通信しないクエリを拒否します - Referrer ヘッダーを送信します。一部の Web サイトは、リファラーと通信しないクエリを拒否します (これは別の csrf 対策です) - 呼び出し間で Cookie を保存します

ファイル: 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);
    }
}

どうやって使うの?

この例では、Web サイトにログインし、ファイルをアップロードするためのフォームを含むページを参照してから、ファイルをアップロードします。

<?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.');

Navigate() メソッドは、閲覧したページの HTML コンテンツまたは FALSE を返します。

ああ、最後に 1 つ: HTML の解析に正規表現を使用しないでください。これは誤りです。それについては、伝説的な StackOverflow の回答があります。こちらを参照してください。

于 2013-02-06T15:22:40.500 に答える
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 基本認証を使用します。

他の認証方法では、パスワードを POST 経由でログイン ページに送信したり、セッション Cookie を保存したりするなど、より多くの作業が必要になる場合があります。

于 2013-02-06T15:11:28.993 に答える