用PHP进行网络爬虫(尽可能以PHP本地语言简单实现)
一个较长的前言。
网页抓取,藤井聪太。(问候)
「我从来没有下过将棋(´・_・`)」
当然啦,这只是个假冒的。我可不是藤井八段那样的天才,只是一个无冠的普通公司职员兼程序员而已。所以,我打算脚踏实地地赚钱,而不是去追求成为将棋天才,这是理所当然的(´・_・`)。
听说如果要谈赚钱的话。我刚看了一个编程视频,据说最近赚钱的编程技术前三是:1. WebAPI、2. 网络爬虫、3. LINE聊天机器人。由于我不喜欢LINE,所以排除了它,而我正在实际工作中使用WebAPI,因此我想尝试一下剩下的”网络爬虫”,这次打算用PHP挑战一下。成为一个赚钱的程序员,我就可以过上美好的晚年了。
考虑除了PHPQuery之外的选项
顺便一提,在PHP中进行Web页面数据抓取!当我去Google搜索时,只能看到一堆「PHPQuery」这个东西… (´・_・`)
不过,就是那个东西吧?大概已经有十年没有更新过了,真是一个糟糕的库吧?否决,完全否决。
然后,替代的是使用”Simple HTML DOM Parser”,据说它的使用方法类似于PHPQuery,非常易于使用。然而,下面的页面……
PHP原生DOM的网页爬虫入门指南- Qiita
据说,由于在内部多次使用正则表达式对所有元素进行解析,所以速度很慢。还有另一个库叫做”Goutte”,据说它在内部使用了PHP原生的DOM,所以看起来很不错。然而,正好因为有机会(这是我的座右铭),我决定尝试一下之前页面中提到的”不添加库,只使用PHP原生的DOM”的方法。
从简单的开始。
我想从最简单和容易的事情开始尝试。比如只取个标题,因为只有一个要素,所以应该很轻松。
一看就陷入了所谓的“乱码”陷阱(´・_・`)下面的代码是我设法克服乱码问题的解决方案。
<html>
<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$html = file_get_contents("https://b.hatena.ne.jp/hobonichi1101/");
$html = mb_convert_encoding($html, "HTML-ENTITIES", 'auto');
@$dom->loadHTML($html);
$xpath = new DOMXpath($dom);
$title = $xpath->query("//title")->item(0)->nodeValue;
echo $title;
?>
</html>
把这个样本放在 Hatena 里可能是个失败吧。毕竟 HTML 有点难搞呢。
吸收多种要素
改良上述的代码,提取目标网页的「はてブ」链接部分。
<html>
<?php
$dom = new DOMDocument('1.0', 'UTF-8');
$html = file_get_contents("https://b.hatena.ne.jp/hobonichi1101/");
$html = mb_convert_encoding($html, "HTML-ENTITIES", 'auto');
@$dom->loadHTML($html);
$xpath = new DOMXpath($dom);
foreach ($xpath->query("//li[@class='bookmark-item js-user-bookmark-item']") as $node) {
echo '<p>';
echo '<a href="';
echo $xpath->evaluate('string(.//@href)', $node);
echo '">';
echo $xpath->evaluate('string(.//a)', $node);
echo '</a>';
echo '</p>';
}
?>
</html>
简要解释一下,”はてなブックマーク”的链接部分以列表形式呈现,并具有”bookmark-item js-user-bookmark-item”这个class属性。因此,在$xpath->query函数中使用该class属性。
//li[@class=’bookmark-item js-user-bookmark-item’]
//带有’bookmark-item js-user-bookmark-item’类的li元素
我指定了这个选项,你就可以获取到所有的内容。然后,你可以使用foreach循环遍历获取到的元素,分别获取其中包含的A属性的文本和href属性(链接URL)。
$xpath->evaluate('string(.//a)', $node);
$xpath->evaluate('string(.//@href)', $node);
我会努力去完成。谢谢。