天天看点

php抓取网页信息

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();