用PHP进行网络爬虫
如果要从名为“ふぁぼるっく”的网站中获取每个“ふぁぼ”的内容、’推文’、’链接到个别页面’以及’点赞数’,我会这样做。
<?php
use Diggin\Scraper\Scraper;
$scraper = new Scraper;
$scraper->process(
'#postlist li', array('postlist[]' => (new Scraper)
->process('//div[@itemprop="articleBody"]', 'articleBody', 'html')
->process('//div[@class="name"]/a', 'author_page', '@href', function($uri) { return $uri->toString();})
->process('//ul["favlist"]//p[@class="fav"]', 'fav', 'raw', function($v) {return (int) $v;})
)
);
$ret = $scraper->scrape('http://favlook.osa-p.net/index.html');
var_dump($ret['postlist']);
只需要给出一个选项,以下是中文的同义表达:
执行结果是,
array(30) {
[0] =>
array(3) {
'articleBody' =>
string(51) "3個めに手が伸びた瞬間、蘇る記憶。"
'author_page' =>
string(68) "http://favlook.osa-p.net:80/status.html?status_id=337187558524063745"
'fav' =>
int(4)
}
[6] =>
array(3) {
'articleBody' =>
这是一个返回值。
好的,本篇帖子将记录以下内容:
– 在进行网络数据抓取时需要注意什么
– Diggin的各个组件是如何进行处理的
– PHP网络数据抓取相关的事宜
在进行网络爬虫时,需要注意什么?
用PHP创建Web应用程序的东西
你所制作的网站可能会包含以下这些页面:
– 根据请求返回响应
– 在响应中添加诸如Content-Type等的头信息
– 使用gzip等方式进行压缩
– 根据认证返回响应
– HTML可能距离或接近XML valid
– 链接使用相对路径,只要浏览器能够判断即可
– 更动态的页面,使用了js等技术。
如果我们从发送请求并处理的角度来考虑,而不是从返回响应的角度来考虑的话,是可以的。。。
好麻煩啊!!!!!!!!!!!!
我将在下面的代码中使用的PHP爬虫组件Diggin来解释它是如何在内部处理这种繁琐的情况的。
挖掘的处理内部
在以上的代码中,内部进行了以下类型的处理。
请求(Zend\Http\Client)
file_get_contents使いません。なぜ?
scrape()メソッドに渡したURLに対し、
Zend\Http\Clientにてリクエストを送信しています。
Zend\Http\Clientをここで用いているfile_get_contentsに対するメリットは、
・Basic認証/Cookie処理
・gzipの場合は自動デコード
・Testアダプタでのデバッグ時のMock化
・レスポンスのオブジェクト化
・(デフォルトで)ソケットクライアント
– 有相关的重定向处理方式等。
自动检测字符编码,并转换为UTF-8(Diggin_Http_Charset)
毎回文字コードを目視してmb_convert_encodingなんて面倒です
・文字コード判定その1
レスポンスヘッダーとメタタグによる
(もちろんShift-JISというContent-Typeは一切信頼せず、
SJIS-winかなどを判定優先します)
・文字コード判定その2 その1の処理に加えmb_detect_encoding
・UTF-8 BOMの除去
・mbstringのサポート外の文字コードの場合はiconv利用
HTML内容的整理(Diggin_Scraper_Adapter_Htmlscraping)。
あなたがブッコ抜きたい情報があるサイトほどHTMLソースは汚いものです
Htmlscrapingクラスは、Http_Requestと密で
レスポンスオブジェクトを個別に切り離して使用できなかったため、
処理を流用しています。
・tidyによる自動整形
・不要なタグの削除
・SimpleXMLElement->asXML()でのダンプに対するエンティティ参照に対するラップ
DSL式的语法(Diggin\Scraper)
スクレイピングのコードから意図を明確にし、重複を減らしましょう
Diggin_ScraperではperlのWeb::Scraperを参考に
process('xpath、cssセレクタ', 'キー', 処理形式, フィルタ)
という形でスクレイピングの命令を集約します
取得多维数组中的值
上記のコードにあるとおり、Scraperオブジェクトに対し、
別のプロセスを持ったScraperオブジェクトをセット
することにより多次元配列として取得できます。
もしかして、foreachで取得した文字列を変換したい?
あらかじめprocess()メソッドにてフィルタを指定しておけば必要はありません。
URL的自动转换
'@href'や'@img'でプロセス指定があったら、
もしHTML中に相対パスで記述されていても、
フルパスのURLに自動変換されたものを取得します。
在Diggin中,我们还准备了Diggin_Service_Wedata,以自动化处理“下一页”链接,并使其可作为Pagerize助手在Scraper对象中使用。
现在,
你认为这篇帖子提供的信息可行/正确吗?
哦,不对吗?你听说还有其他的做法吗?我将在下一节介绍最近关于网络抓取的情况。
最近有关于PHP网页爬取的情况
以前,有一篇关于“PHP爬虫相关的实用库”(http://dxd8.com/archives/85/) 的文章,但是它已经有点陈旧了。
在过去的2、3年中,引起关注的工具有:
・simple_html_dom
・Goutte
・htmlSQL
・phpQuery等。其中,对于htmlSQL,我不太理解为什么作者要介绍它作为一种基于HTML文档树的SQL数据结构的方法,因为他还推荐了其他方法。simple_html_dom在PHP本身提供的DOM之外,还具有编写底层处理的趣味,但我更喜欢使用xpath,而且听说它会消耗大量内存,所以我避免使用它。关于Goutte,可以在http://d.hatena.ne.jp/hnw/20120115 上找到详细信息,但你也应该关注它作为Behat\Mink的包装器和兼容工具。虽然它更像是爬虫而不是仅仅是网页抓取。
最近有关网络抓取的趋势如下:
– HTTP客户端(Guzzle, requests)
– BDD(Behat/Mink)
– 无头浏览器(WebKitGTK/PhantomJS/CasperJS)
– 类似于jQuery的DOM库(请搜索)
具体细节不赘述,最后,当我在看着Doctrine主要开发者创建的https://github.com/beberlei/phpricot时,我不禁对pecl/html_parse产生感慨,于是结束了这篇文章。
请参考链接。
・使用PHP进行网页抓取 http://qiita.com/items/5f26263d9ebf4268d7f3
・Diggin 项目 https://github.com/diggin
・Diggin 参考文档 http://diggin.musicrider.com/manual/diggin.index.html
・Behat\Mink 项目 https://github.com/Behat/Mink
・使用xpath正则表达式(registerXpathPhpFunctions的用法)
http://qiita.com/items/179957d5aefe0e3785ab
・https://twitter.com/everzet/status/333666328521109504