PHP 爬蟲 抓取 HTML 內容
Table of Contents
#
Intro
又是久違的寫爬蟲…
這次是接手大大們的 code
寫的是 PHP 版本
研究了一下寫法
才發現現在可以不使用第三方套件就可以處理了
所以這裡紀錄一下
#
取得 HTML 內容
- 使用 curl
- 使用 file_get_contents
curl 是我常用的方式 看了大大們的 code 才知道原來 file_get_contents 也可以取 http/https 內容…
這邊簡單貼一下兩種作法的範例
##
curl
function httpGet($url)
{
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_HEADER, [
'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
]);
$output=curl_exec($ch);
curl_close($ch);
return $output;
}
##
file_get_contents
function htmlContentGet($url) {
$opts = [
"http" => [
"method" => "GET",
"header" => "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36\r\n"
]
];
return file_get_contents($url, false, stream_context_create($opts));
}
如果需要一些特別的 header 或是 querystring 就在各自處理
另外提一下, 用 file_get_contents 也可以抓取本地檔案, 所以也可以打開本地的 html file(至少我以前用 file_get_contents 都是用來打開本地檔案的)
refer - PHP: file_get_contents - Manual
#
抓取 DOM
研究了一下也有不少方式可以做
因為上面方法回來的是 string
所以接下來最重要的事情是如何擷取出想要的內容
大致有兩種方式
- 用 preg_replace, str_replace, strpos, substr 等方法處理
- 針對 DOM 轉成物件來處理
各有優缺點
就看最後決定要怎麼做
這裡針對 2 的處理方式來處理
$dom = new DOMDocument();
$dom->loadHTML($html_string, LIBXML_NOERROR);
這裡又細分兩種處理方式
- DOM HTML
- XPath
##
DOM HTML
$dom = new DOMDocument();
$dom->loadHTML($html_string, LIBXML_NOERROR);
$documentElement = $dom->documentElement;
##
XPath
$dom = new DOMDocument();
$dom->loadHTML($html_string, LIBXML_NOERROR);
$xpath = new DOMXpath($dom);
這兩種的差別就在於支援的取 DOM 的方式不同
documentElement 這個 Class 底下取得 DOM 物件的方法名稱大多和 JavaScript 的名稱一樣
可以參考以下文件
refer - PHP: DOMElement - Manual
以下列舉一些範例
$span = $documentElement->getElementsByTagName('span');
foreach( $span as $item ) {
echo $item->textContent . "\n";
}
$img = $documentElement->getElementsByTagName('img');
foreach( $img as $item ) {
echo $item->getAttribute('src') . "\n";
}
比較可惜的是它沒有抓取 class 的方式
這種情況就可以用取 XPath 的方式來做
基本上我個人是比較喜歡 XPath 的方式
因為相對比較好用
後續要調整也相對容易, 只要改動 XPath 就可以了
$xpath = new DOMXpath($dom);
$desc = $xpath->query("/html/body/div[2]/div[2]/div/div[1]/a/img");
foreach( $desc as $item ) {
echo $item->getAttribute('src') . "\n";
}
refer - How to Parse HTML using PHP Native Classes
refer - PHP: DOMDocument - Manual
#
結語
以上的方式都只適用於 SSR 的頁面
如果內容是動態產生的一律建議直接用打 API 的方式去拿內容