symfony/dom-crawler+guzzlehttp/guzzle
1.安装两个组件
composer require guzzlehttp/guzzle
composer require symfony/dom-crawler
Guzzle插件简介
Guzzle 是一个 PHP 的 HTTP 客户端,用来轻而易举地发送请求,并集成到我们的 WEB 服务上。
接口简单:构建查询语句、POST 请求、分流上传下载大文件、使用 HTTP cookies、上传 JSON 数据等等。
发送同步或异步的请求均使用相同的接口。
使用 PSR-7 接口来请求、响应、分流,允许你使用其他兼容的 PSR-7 类库与 Guzzle 共同开发。
抽象了底层的 HTTP 传输,允许你改变环境以及其他的代码,如:对 cURL与 PHP 的流或 socket 并非重度依赖,非阻塞事件循环。
中间件系统允许你创建构成客户端行为。
symfony和dom-crawler
symfony我就不多说了,怎么形容,实在不好说,国内生态弱,一个朋友说:Symfony 和 ZendFramework 基本上是为企业应用,大型复杂互联网应用准备的。核心的思想大部分都是 Copy 了 Java 生态圈中一些成熟的模式等, 比如模块化,企业应用架构模式。Doctrine 甚至 Copy 了 Hibernate,Bean Validation 等。就连 PSR 也是来自 JSR 的灵感,不得不说的 Symfony 为现在 PHP 框架 /组件互通互用作了很大贡献。不懂 OOP,和不了解马大叔的企业架构模式这些可能觉得 Symfony 太难了。但对于熟悉这些的 Java 程序员,Symfony 太友好了,上手几乎不费吹灰之力。
dom-crawler:官方翻译比较蹩脚:Crawler 类提供的方法用于查询和操作HTML以及XML文档。Crawler实例呈现的是一组 DOMElement 对象,它们是你可以轻松遍历的基本节点:总之是可以遍历节点的读取dom的组件咯。
以下是我写的一个demo参考一下
<?php
require_once './vendor/autoload.php';
header('Content-type:text/html;charset=UTF-8');
$Crawler = new \Symfony\Component\DomCrawler\Crawler();
class Command
{
//抓取地址
const URL = 'http://www.ccgp-liaoning.gov.cn/bulletin.do?method=showbulletin&bulletin_id=';
//当前最大数据
private $max_page = 0;
//初始化获取最大id
public function __construct ()
{
$url = 'http://www.ccgp-liaoning.gov.cn/bulletininfo.do?method=bdetail&treenum=05&treenumfalse=';
$client = new \GuzzleHttp\Client([
'timeout' => 10 ,
]);
$response = $client->request('GET' ,$url);
// 转换成页面使用的编码,默认为UTF-8,此网站乱码。
$type = $response->getHeader('content-type');
$parsed = \GuzzleHttp\Psr7\parse_header($type);
$original_body = (string)$response->getBody()->getContents();;
$utf8_body = mb_convert_encoding($original_body ,'UTF-8' ,$parsed[0]['charset'] ? : 'UTF-8');
$crawler = new \Symfony\Component\DomCrawler\Crawler();
$crawler->addHtmlContent($utf8_body);
$err = $crawler->filterXPath('//tbody/tr')->first()->attr('id');
if (!empty($err)) {
$this->max_page = $err;
} else {
echo '暂无数据';
exit;
}
}
/**
* @throws \GuzzleHttp\Exception\GuzzleException
* 执行抓取
*/
public function execute ()
{
header('Content-type:text/html;charset=UTF-8');
//需要爬取的页面
$url = self::URL;
//下载网页内容
$client = new \GuzzleHttp\Client([
'timeout' => 10 ,
]);
$data = [];
//默认抓取30条
for ($i = $this->max_page; $i >= $this->max_page - 30; $i--) {
$response = $client->request('GET' ,$url . $i);
// 转换成页面使用的编码,默认为UTF-8,此网站乱码。
$type = $response->getHeader('content-type');
$parsed = \GuzzleHttp\Psr7\parse_header($type);
$original_body = (string)$response->getBody()->getContents();;
$utf8_body = mb_convert_encoding($original_body ,'UTF-8' ,$parsed[0]['charset'] ? : 'UTF-8');
$crawler = new \Symfony\Component\DomCrawler\Crawler();
$crawler->addHtmlContent($utf8_body);
try {
$err = $crawler->filterXPath('//*[@class="newinfotr1"]')->text();
if (!empty($err)) {
//TODO 你的业务逻辑
}
} catch (\Exception $e) {
}
}
print_r($data);
exit;
}
/**
* @param $str
* @return string
* 删除字符串中的空格
*/
private function clearHtml ($str)
{
$str = trim($str); //清除字符串两边的空格
$str = preg_replace("/\t/" ,"" ,$str); //使用正则表达式替换内容,如:空格,换行,并将替换为空。
$str = preg_replace("/\r\n/" ,"" ,$str);
$str = preg_replace("/\r/" ,"" ,$str);
$str = preg_replace("/\n/" ,"" ,$str);
$str = preg_replace("/ /" ,"" ,$str);
$str = preg_replace("/ /" ,"" ,$str); //匹配html中的空格
return trim($str); //返回字符串
}
}
//执行
$obj = new Command();
$obj->execute();