写在前面

个人总是觉得代码的目的就是要解决实际问题,这次分享的示例和上次分享的一样也是我实际使用过的。最初是因为女朋友在买菜的时候除了草莓,对其他价格一无所知,经常被宰了也乐呵呵的付钱,于是我就写了此程序来查询每天菜价,来规避这种情况。当我把成品献宝给女朋友时,女朋友非常高兴地把买菜这个事永久性的托付给了我。我裂开了...

本次目的

从实战的方式学习php解析html类库simple_html_dom,并实现对官方公布民生商品价格公示信息的爬取。

实战

首先引用simple_html_dom

include("simple_html_dom.php");

其实simple_html_dom里面内置了file_get_content函数 ,那么秉着学习的目的,我们这次改用curl,其优势在于可以设置请求头,模拟ip模拟,设置reffer,模拟登录等。

function curlHttp($url) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        $head = array(
            'Content-Type: application/x-www-form-urlencoded',
            'user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
        );
        curl_setopt($curl, CURLOPT_HTTPHEADER, $head);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_NOBODY, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        //curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        $response = curl_exec($curl);
        curl_close($curl);
        return $response;
    }

分析一下目标网站
先分析详情页:
商品价格详情页
信息是以图片的形式展示的,那么我们整个页面需要提取的就是名称和图片地址,上次分享的时候我们使用的正则表达式,可能有的朋友对正则比较头大,这回引入了simple_html_dom就简单的多基本看了示例代码就可以直接上手。

$htmlson = str_get_html(curlHttp("http://124.93.228.152:8090/view-0ee2ebc5431a486d8533c27f3b3e41c6.jhtml));
$title = $htmlson->find("div[class=article-content] h2",0)->innertext;
$img = $htmlson->find("div[class=article-content] img",0)->src;
$image = curlHttp('http://124.93.228.152:8090'.$img);

这里curlHttp是我们封装的curl获取目标网页的,str_get_html则是simple_html_dom内根据字符串创建DOM,定位到元素的方法很简单,(使用类似jQuery选择器的写法同样也可以识别)。把提取的内容保存到本地还是可以使用fwrite。

分析一下列表页,这里做简单演示只爬取第一页,(很奇怪的列表,竟然是post分页)
商品价格列表页

$url = "http://124.93.228.152:8090/html/NongMaoShiChang/";
$html = str_get_html(curlHttp($url));
foreach($html->find('ul[class=bmxx-list mb-mar] li a') as $e){
    echo $e->href;
}

可以看到引入了simple_html_dom后可以非常简单的定位到元素。

我们简单整合一下代码,就可以使用了。

<?php
include("simple_html_dom.php");
function curlHttp($url) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        $head = array(
            'Content-Type: application/x-www-form-urlencoded',
            'user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
        );
        curl_setopt($curl, CURLOPT_HTTPHEADER, $head);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_NOBODY, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        //curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        $response = curl_exec($curl);
        curl_close($curl);
        return $response;
    }
$dir = './data/images/';
if (!file_exists($dir)){
    mkdir ($dir,0777,true);
}
$url = "http://124.93.228.152:8090/html/NongMaoShiChang/";
$html = str_get_html(curlHttp($url));
foreach($html->find('ul[class=bmxx-list mb-mar] li a') as $e){
    //echo $e->href;
    //echo '<br>';
    $htmlson = str_get_html(curlHttp("http://124.93.228.152:8090".$e->href));
    $title = $htmlson->find("div[class=article-content] h2",0)->innertext;
    $img = $htmlson->find("div[class=article-content] img",0)->src;
    $image = curlHttp('http://124.93.228.152:8090'.$img);
    $file = fopen($dir.$title.".png","w");
    if(fwrite($file, $image)){
        echo "下载".$title."成功。<br>";
    }else{
        echo "下载".$title."失败。<br>";
    }
    fclose($file);
}

效果1

效果2

写在后面

爬虫学习部分结束,于整个项目和上次一样还有需要完善的地方,我简单描述一下后续的改进和我的实际应用,首先是爬取完整数据
,其次是设置定时任务每天爬取,改进成增量式爬虫,节约资源。至此爬虫部分结束,额外的改进,每日定时发送最新价格信息到邮箱或者微信,由于图片不太适合手机阅读,使用百度AI的表格文字识别接口生成excel,在转换成json方便搜索查询。