本文已参与「新人创作礼」活动,一起开启掘金创作之路。
这篇文章主要分享给经常用于采集的小伙伴们,对于采集,最主要是采集规则,有时候写一个采集规则要尝试很多次,甚至有些不好采集,或者要通过多次匹配才能拿到真实想要的数据!
这里我给大家推荐一个拓展工具:QueryList,他可以让你想使用js一样的选择元素,快速准确的采集到想要的数据。
首先我们先来安装拓展,使用composer进行安装,安装方式如下:
composer require jaeger/querylist
安装好后,如何使用呢?先在控制器里引用QueryList,引用方法如下:
use QL\QueryList;
QueryList如何选择元素?,如果你熟悉jquery的话,会很好入手,通过下面这段代码可以快速选择元素,并且改变元素的值:
use QL\QueryList;
$html =<<<STR
<div>
<a href="https://querylist.cc" alt="abc">QueryList</a>
</div>
STR;
$ql = QueryList::html($html);
// 获取a元素对象
$link = $ql->find('a:eq(0)');
// 设置元素属性值
$link->attr('href','https://baidu.com');
$link->attr('alt','百度');
// 设置元素内容
$link->text('百度一下');
$data = $ql->find('div')->html();
print_r($data);
以上代码,执行结果如下:
Array
(
[parent] => <a href="https://qq.com">QQ</a>
<a class="ql" href="https://querylist.cc" alt="abc">QueryList</a>
<a href="https://baidu.com">百度一下</a>
[next] => 百度一下
[prev] => https://qq.com
)
是不是很简单,如果我们想一次性多次筛选出多个数据出来,该怎么操作呢?
//DOM解析开发者头条
$ql = QueryList::getInstance();
//注册一个myHttp方法到QueryList对象
$ql->bind('myHttp',function ($url){
$html = file_get_contents($url);
$this->setHtml($html);
return $this;
});
//然后就可以通过注册的名字来调用
$data = $ql->myHttp('https://toutiao.io')->find('h3 a')->texts();
print_r($data->all());
//或者这样用
$data = $ql->rules([
'title' => ['h3 a','text'],
'link' => ['h3 a','href']
])->myHttp('https://toutiao.io')->query()->getData();
print_r($data->all());
上面执行结果如下:
Array
(
[0] => 用 500 行 Golang 代码实现高性能的消息回调中间件
[1] => 腾讯大神教你如何解决 Android 内存泄露
[2] => [译] 普通码农入门机器学习,必须掌握这些数据技能
[3] => 教你用 Carthage + RXSwift + MVVM + Moya + Router 写一个小说阅读 App
//...
)
Array
(
[0] => Array
(
[title] => 用 500 行 Golang 代码实现高性能的消息回调中间件
[link] => /k/u6hhfn
)
[1] => Array
(
[title] => 腾讯大神教你如何解决 Android 内存泄露
[link] => /k/abg526
)
[2] => Array
(
[title] => [译] 普通码农入门机器学习,必须掌握这些数据技能
[link] => /k/cnbt4o
)
[3] => Array
(
[title] => 教你用 Carthage + RXSwift + MVVM + Moya + Router 写一个小说阅读 App
[link] => /k/1aaumb
)
//....
)
那么如果内容中有些广告我们该如何过滤呢?
use QL\QueryList;
$html =<<<STR
<div id="content">
<span class="tt">作者:xxx</span>
这是正文内容段落1.....
<span>这是正文内容段落2</span>
<p>这是正文内容段落3......</p>
<span>这是广告</span>
<p>这是版权声明!</p>
</div>
STR;
// DOM解析正文内容
$eles = QueryList::html($html)->find('#content');
// 选择正文内容中要移除的元素,并移除
$eles->find('.tt,span:last,p:last')->remove();
//获取纯净的正文内容
$content = $eles->html();
print_r($content);
以上结果执行如下:
这是正文内容段落1.....
<span>这是正文内容段落2</span>
<p>这是正文内容段落3......</p>
列表DOM解析场景
$rules = [
'规则名1' => ['选择器1','元素属性','内容过滤选择器'],
'规则名2' => ['选择器2','元素属性','内容过滤选择器'],
// ...
];
实例如下:
use QL\QueryList;
$html =<<<STR
<div id="content">
<span class="tt">作者:xxx</span>
这是正文内容段落1.....
<span>这是正文内容段落2</span>
<p>这是正文内容段落3......</p>
<span>这是广告</span>
<p>这是版权声明!</p>
</div>
STR;
// DOM解析规则
$rules = [ //设置了内容过滤选择器 'content' => ['#content','html','-.tt -span:last -p:last']
];
$rt = QueryList::rules($rules)->html($html)->query()->getData();
print_r($rt->all());
以上代码执行如下:
Array
(
[0] => Array
(
[content] => 这是正文内容段落1.....
<span>这是正文内容段落2</span>
<p>这是正文内容段落3......</p>
)
)