近年来,随着互联网的普及,网络爬虫逐渐成为了信息采集的主要手段之一,然而,常规的爬虫技术不稳定、难以维护,市面上的纯web网页爬虫也只能在静态页面上进行操作。而php结合selenium可达到动态爬虫的效果,具有稳定性高、数据采集全面等优点,被广泛应用于爬虫开发中。本文将介绍如何使用php和selenium快速构建自己的网络爬虫系统。
一、Selenium和ChromeDriver的安装
Selenium是一个自动化测试工具,可以对Web应用程序进行自动化测试,其中将浏览器与操作系统分离式地处理,无强制插入代码实现页面渲染。ChromeDriver则是Selenium中调用Chrome浏览器的驱动程序,可以使Selenium直接操作Chrome,从而实现动态页面的爬取。
首先需要在本地安装Chrome浏览器和PHP环境。接着,我们需要安装相应版本的Selenium和ChromeDriver,在命令行中输入以下代码即可安装:
1 | composer require facebook/webdriver |
然后将ChromeDriver二进制文件(根据自己的本地Chrome版本下载相应版本的ChromeDrive)置于系统Path变量环境中,代码如下:
1 2 3 | $webdriver = FacebookWebDriverRemoteRemoteWebDriver::create( 'http://localhost:9515' , FacebookWebDriverChromeChromeOptions:: class ); |
二、构建Selenium和ChromeDriver的封装类
Selenium封装类主要用来维护Selenium和ChromeDriver,避免重复创建、销毁,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | class Selenium { private static $driver ; private static $selenium ; public static function getInstance() { if (null === self:: $selenium ) { $options = new ChromeOptions(); $options ->addArguments([ '--no-sandbox' , '--disable-extensions' , '--headless' , '--disable-gpu' ]); self:: $driver = RemoteWebDriver::create( 'http://localhost:9515' , DesiredCapabilities::chrome()->setCapability( ChromeOptions::CAPABILITY, $options ) ); self:: $selenium = new self(); } return self:: $selenium ; } public function __destruct() { self:: $driver ->quit(); self:: $selenium = null; } public function getDriver() { return self:: $driver ; } } |
注意,参数中的ChromeOptions主要是为了在无GUI(图形化界面)下仍能稳定运行,--no-sandbox参数是为了防止在linux系统下运行时报错。
三、创建网页源码解析类
爬虫系统的核心在于解析非静态页面,这里需要创建源码解析类,使用正则表达式或XPath表达式来定位和获取目标节点信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | class PageParser { private $pageSource ; public function __construct(string $pageSource ) { $this ->pageSource = $pageSource ; } public function parse(string $expression , $list = false) { if ( $list ) { return $this ->parseList( $expression ); } return $this ->parseSingle( $expression ); } private function parseList(string $expression ) { $domXpath = new DOMXPath(@DOMDocument::loadHTML( $this ->pageSource)); $items = $domXpath ->query( $expression ); $result = []; foreach ( $items as $item ) { array_push ( $result ,trim( $item ->nodeValue)); } return $result ; } private function parseSingle(string $expression ) { $domXpath = new DOMXPath(@DOMDocument::loadHTML( $this ->pageSource)); $item = $domXpath ->query( $expression )->item(0); if ( $item ) { return trim( $item ->nodeValue); } return '' ; } } |
这里主要用到了DOMXPath类和DOMDocument类来解析页面中的HTML节点,分别通过parseList和parseSingle方法来定位和获取多个和一个目标节点的内容。
四、创建爬虫类
最后,我们需要构建一个专门爬取页面内容的爬虫类,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Spider { private $selenium ; private $url ; public function __construct( $url ) { $this ->selenium = Selenium::getInstance(); $this ->url = $url ; $this ->selenium->getDriver()->get( $url ); sleep(1); } public function __destruct() { $this ->selenium->getDriver()->close(); $this ->selenium = null; } public function getContent( $expression , $list = false) { $pageSource = $this ->selenium->getDriver()->getPageSource(); $parser = new PageParser( $pageSource ); return $parser ->parse( $expression , $list ); } } |
该类的getContent方法接收两个参数,一个是目标节点的XPath表达式,另一个是是否获取多个内容。 getModelContent函数请求URL并解析节点来获取所需内容,该函数获取结束后关闭浏览器进程。
五、使用示例
最后,我们使用实际例子来说明如何使用这个爬虫类。假设我们需要从一个拥有多个a标签的网页上,爬取a标签中的href属性和文本信息。我们可以通过以下代码来实现:
1 2 3 4 5 6 7 8 | $spider = new Spider( 'https://www.example.com' ); $aTags = $spider ->getContent( '//a' , true); foreach ( $aTags as $a ) { $href = $a ->getAttribute( 'href' ); $text = $a ->nodeValue; echo " $href -> $text "; } |
在以上代码中,首先使用Spider类获取页面源码,然后通过XPath表达式获取多个a标签的节点信息,最后通过getAttribute和nodeValue方法获取每个a标签的href属性和文本。
六、总结
综上所述,本文通过介绍如何使用PHP和Selenium构建网页爬虫系统,并通过实际示例说明如何获取页面中的节点信息,该爬虫具有稳定性高、数据采集全面等优点,具有一定的应用价值。但同时需要注意的是,爬取数据时需要注意合法性和道德性,并遵守相关法律法规。
发表评论 取消回复