web-dev-qa-db-ja.com

Webページのコンテンツをこする

私は、バックグラウンドでWebサイトのコンテンツを削り取り、その削られたWebサイトから限られたコンテンツを取得したいプロジェクトを開発しています。たとえば、私のページには「userid」フィールドと「password」フィールドがあり、それらを使用してメールにアクセスし、受信トレイのコンテンツをスクレイピングして、ページに表示します。

私は、JavaScriptだけを使用して上記を行いました。しかし、サインインボタンをクリックすると、自分のページのURL( http://localhost/web/Login.html )がURL( http://mail.in .com/mails/inbox.php?nomail = ... 。)私はかき集められます。ただし、URLを変更せずに詳細をスクラップします。

15
Sakthivel

間違いなく PHP Simple HTML DOM Parser を使用してください。高速で、簡単で、非常に柔軟です。基本的には、HTMLページ全体をオブジェクトに貼り付け、そのオブジェクトから任意の要素にアクセスできます。

公式サイトの例のように、メインのGoogleページのすべてのリンクを取得するには、次のようにします。

// Create DOM from URL or file
$html = file_get_html('http://www.google.com/');

// Find all images 
foreach($html->find('img') as $element) 
       echo $element->src . '<br>';

// Find all links 
foreach($html->find('a') as $element) 
       echo $element->href . '<br>';
36
givp

HTTPリクエスト

最初に、ページのコンテンツを取得するためにHTTPリクエストを作成します。それにはいくつかの方法があります。

fopen

HTTPリクエストを送信する最も基本的な方法は、fopenを使用することです。主な利点は、一度に読み取る文字数を設定できることです。これは、非常に大きなファイルを読み取るときに役立ちます。ただし、これは正しく行うのが最も簡単なことではありません。非常に大きなファイルを読み取り、メモリの問題が発生するのを恐れない限り、これを行うことはお勧めしません。

$fp = fopen("http://www.4wtech.com/csp/web/Employee/Login.csp", "rb");
if (FALSE === $fp) {
    exit("Failed to open stream to URL");
}

$result = '';

while (!feof($fp)) {
    $result .= fread($fp, 8192);
}
fclose($fp);
echo $result;

file_get_contents

最も簡単な方法は、file_get_contentsを使用することです。 ifはfopenとほぼ同じですが、選択できるオプションが少なくなります。ここでの主な利点は、1行のコードしか必要としないことです。

$result = file_get_contents('http://www.4wtech.com/csp/web/Employee/Login.csp');
echo $result;

ソケット

サーバーに送信するヘッダーをさらに制御する必要がある場合は、fopenと組み合わせてソケットを使用できます。

$fp = fsockopen("www.4wtech.com/csp/web/Employee/Login.csp", 80, $errno, $errstr, 30);
if (!$fp) {
    $result = "$errstr ($errno)<br />\n";
} else {
    $result = '';
    $out = "GET / HTTP/1.1\r\n";
    $out .= "Host: www.4wtech.com/csp/web/Employee/Login.csp\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp, $out);
    while (!feof($fp)) {
        $result .= fgets($fp, 128);
    }
    fclose($fp);
}
echo $result;

ストリーム

または、ストリームを使用することもできます。ストリームはソケットに似ており、fopenfile_get_contentsの両方と組み合わせて使用​​できます。

$opts = array(
  'http'=>array(
    'method'=>"GET",
    'header'=>"Accept-language: en\r\n" .
              "Cookie: foo=bar\r\n"
  )
);

$context = stream_context_create($opts);

$result = file_get_contents('http://www.4wtech.com/csp/web/Employee/Login.csp', false, $context);
echo result;

cURL

サーバーがcURLをサポートしている(通常はサポートしている)場合は、cURLを使用することをお勧めします。 cURLを使用する主な利点は、他のプログラミング言語で一般的に使用されている一般的なCライブラリに依存していることです。また、リクエストヘッダーを作成するための便利な方法を提供し、エラーが発生した場合にシンプルなインターフェースでレスポンスヘッダーを自動解析します。

$defaults = array( 
    CURLOPT_URL, "http://www.4wtech.com/csp/web/Employee/Login.csp"
    CURLOPT_HEADER=> 0
);

$ch = curl_init(); 
curl_setopt_array($ch, ($options + $defaults)); 
if( ! $result = curl_exec($ch)) { 
    trigger_error(curl_error($ch)); 
} 
curl_close($ch); 
echo $result; 

図書館

または、 many PHP libraries のいずれかを使用できます。ただし、ライブラリの使用はお勧めしませんが、ほとんどの場合、内部でcURLを使用して独自のHTTPクラスを記述した方がよいでしょう。


HTML解析

PHPには、HTMLをDOMDocumentにロードする便利な方法があります。

$pagecontent = file_get_contents('http://www.4wtech.com/csp/web/Employee/Login.csp');
$doc = new DOMDocument();
$doc->loadHTML($pagecontent);
echo $doc->saveHTML();

残念ながら、PHP HTML5のサポートは制限されています。ページのコンテンツを解析しようとしてエラーが発生した場合は、サードパーティのライブラリを使用することを検討してください。そのため、 Masterminds/html5-php 。このライブラリを使用したHTMLファイルの解析は、DOMDocumentを使用したHTMLファイルの解析とよく似ています。

use Masterminds\HTML5;

$pagecontent = file_get_contents('http://www.4wtech.com/csp/web/Employee/Login.csp');
$html5 = new HTML5();
$dom = $html5->loadHTML($html);
echo $html5->saveHTML($dom);

代わりに、例えばを使用することができます。私のライブラリ PHPPowertools/DOM-Query 。カスタマイズされたバージョンの Masterminds/html5-php を使用して、HTML5文字列をDomDocumentおよび symfony/DomCrawler CSSセレクターからXPathセレクターへの変換用。適切なパフォーマンスを確保するために、1つのオブジェクトを別のオブジェクトに渡す場合でも、常に同じDomDocumentを使用します。

namespace PowerTools;

// Get file content
$pagecontent = file_get_contents( 'http://www.4wtech.com/csp/web/Employee/Login.csp' );

// Define your DOMCrawler based on file string
$H = new DOM_Query( $pagecontent );

// Define your DOMCrawler based on an existing DOM_Query instance
$H = new DOM_Query( $H->select('body') );

// Passing a string (CSS selector)
$s = $H->select( 'div.foo' );

// Passing an element object (DOM Element)
$s = $H->select( $documentBody );

// Passing a DOM Query object
$s = $H->select( $H->select('p + p') );

// Select the body tag
$body = $H->select('body');

// Combine different classes as one selector to get all site blocks
$siteblocks = $body->select('.site-header, .masthead, .site-body, .site-footer');

// Nest your methods just like you would with jQuery
$siteblocks->select('button')->add('span')->addClass('icon icon-printer');

// Use a lambda function to set the text of all site blocks
$siteblocks->text(function( $i, $val) {
    return $i . " - " . $val->attr('class');
});

// Append the following HTML to all site blocks
$siteblocks->append('<div class="site-center"></div>');

// Use a descendant selector to select the site's footer
$sitefooter = $body->select('.site-footer > .site-center');

// Set some attributes for the site's footer
$sitefooter->attr(array('id' => 'aweeesome', 'data-val' => 'see'));

// Use a lambda function to set the attributes of all site blocks
$siteblocks->attr('data-val', function( $i, $val) {
    return $i . " - " . $val->attr('class') . " - photo by Kelly Clark";
});

// Select the parent of the site's footer
$sitefooterparent = $sitefooter->parent();

// Remove the class of all i-tags within the site's footer's parent
$sitefooterparent->select('i')->removeAttr('class');

// Wrap the site's footer within two nex selectors
$sitefooter->wrap('<section><div class="footer-wrapper"></div></section>');
19
John Slegers

OutWit Hubを試しましたか?それは全体の削り取り環境です。構造を推測したり、独自のスクレーパーを開発したりできます。ぜひご覧ください。それは私の人生をずっと単純にしました。 ZR

0
Zee Rottis

PHPのcURL拡張機能を使用して、PHPページスクリプト内から別のWebサイトにHTTPリクエストを送信できます。 こちらのドキュメントを参照してください。

もちろん、ここでの欠点は、ページ全体や出力をユーザーに提示する前に外部のWebサイトを削る必要があるため、サイトの応答が遅いことです。

0
cruizer