簡體   English   中英

刮取 web 頁面內容

[英]Scrape web page contents

我正在開發一個項目,我想在后台抓取網站的內容並從該抓取的網站中獲取一些有限的內容。 例如,在我的頁面中,我有“userid”和“password”字段,通過使用這些字段,我將訪問我的郵件並抓取我的收件箱內容並將其顯示在我的頁面中。

我通過單獨使用 javascript 完成了上述操作。 But when I click the sign in button the URL of my page ( http://localhost/web/Login.html ) is changed to the URL ( http://mail.in.com/mails/inbox.php?nomail= ... .) 我被刮了。 但是我在不更改 url 的情況下廢棄了細節。

絕對是 go 和PHP 簡單 HTML DOM 解析器 它快速、簡單且超級靈活。 它基本上將整個 HTML 頁面粘貼到 object 中,然后您可以訪問該 object 中的任何元素。

像官方網站的例子一樣,獲取谷歌主頁上的所有鏈接:

// 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>';

HTTP 請求

首先,您發出 HTTP 請求以獲取頁面內容。 有幾種方法可以做到這一點。

開放

發送 HTTP 請求的最基本方法是使用fopen 一個主要優點是您可以設置一次讀取多少個字符,這在讀取非常大的文件時很有用。 但是,正確地做這件事並不是最容易的事情,除非您正在閱讀非常大的文件並且擔心遇到 memory 問題,否則不建議這樣做。

$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 if 和 fopen 差不多,但是你有更少的選擇。 這里的一個主要優點是它只需要一行代碼。

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

sockets

如果您需要對發送到服務器的標頭進行更多控制,可以將 sockets 與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;

或者,您也可以使用流。 流類似於 sockets 並且可以與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; 

圖書館

或者,您可以使用許多 PHP 庫之一。 不過,我不建議使用庫,因為它可能會矯枉過正。 在大多數情況下,最好使用 cURL 在引擎蓋下編寫自己的 HTTP class。


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 字符串解析為DomDocumentsymfony/DomCrawler以將 CSS 選擇器轉換為 ZB6454D4984635BEED10A13EA8 它始終使用相同的DomDocument ,即使將一個 object 傳遞給另一個,以確保良好的性能。

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

你試過 OutWit Hub 嗎? 這是一個完整的抓取環境。 您可以讓它嘗試猜測結構或開發自己的刮板。 我真的建議你看看它。 它讓我的生活變得簡單多了。 ZR

You can use the cURL extension of PHP to do HTTP requests to another web site from within your PHP page script. 請參閱此處的文檔。

當然,這里的缺點是您的站點會響應緩慢,因為您必須先抓取外部 web 站點,然后才能將完整頁面/輸出呈現給用戶。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM