采集单元素

学习采集单个网页元素的属性值或内容。



获取单个元素的单个属性

如果你有使用过jQuery的经验,就会发现下面的写法与jQuery的写法是一致的。

设置待采集的HTML片段

  1. use QL\QueryList;
  2. $html = <<<STR
  3. <div id="one">
  4. <div class="two">
  5. <a href="http://querylist.cc">QueryList官网</a>
  6. <img src="http://querylist.com/1.jpg" alt="这是图片" abc="这是一个自定义属性">
  7. <img class="second_pic" src="http://querylist.com/2.jpg" alt="这是图片2">
  8. <a href="http://doc.querylist.cc">QueryList文档</a>
  9. </div>
  10. <span>其它的<b>一些</b>文本</span>
  11. </div>
  12. STR;
  13. $ql = QueryList::html($html);

获取第一张图片的属性

采集代码:

  1. $rt = [];
  2. //获取第一张图片的链接地址
  3. //下面四种写法完全等价
  4. $rt[] = $ql->find('img')->attr('src');
  5. $rt[] = $ql->find('img')->src;
  6. $rt[] = $ql->find('img:eq(0)')->src;
  7. $rt[] = $ql->find('img')->eq(0)->src;
  8. //获取第一张图片的alt属性
  9. $rt[] = $ql->find('img')->alt;
  10. //获取第一张图片的abc属性,注意这里获取定义属性的写法与普通属性的写法是一样的
  11. $rt[] = $ql->find('img')->abc;
  12. print_r($rt);

采集结果:

  1. Array
  2. (
  3. [0] => http://querylist.com/1.jpg
  4. [1] => http://querylist.com/1.jpg
  5. [2] => http://querylist.com/1.jpg
  6. [3] => http://querylist.com/1.jpg
  7. [4] => 这是图片
  8. [5] => 这是一个自定义属性
  9. )

获取第二张图片的属性

采集代码:

  1. $rt = [];
  2. //获取第二张图片的alt属性
  3. $rt[] = $ql->find('img')->eq(1)->alt;
  4. //等价下面这句话
  5. $rt[] = $ql->find('img:eq(1)')->alt;
  6. //也等价下面这句话,通过class选择图片
  7. $rt[] = $ql->find('.second_pic')->alt;
  8. print_r($rt);

采集结果:

  1. Array
  2. (
  3. [0] => 这是图片2
  4. [1] => 这是图片2
  5. [2] => 这是图片2
  6. )

获取元素的所有属性

属性匹配支持通配符*,表示匹配当前元素的所有属性。

采集代码:

  1. $rt = [];
  2. $rt[] = $ql->find('img:eq(0)')->attr('*');
  3. $rt[] = $ql->find('a:eq(1)')->attr('*');
  4. print_r($rt);

采集结果:

  1. Array
  2. (
  3. [0] => Array
  4. (
  5. [src] => http://querylist.com/1.jpg
  6. [alt] => 这是图片
  7. [abc] => 这是一个自定义属性
  8. )
  9. [1] => Array
  10. (
  11. [href] => http://doc.querylist.cc
  12. )
  13. )

获取元素内的html内容或text内容

text内容与html内容的区别是,text内容中去掉了所有html标签,只剩下纯文本。

采集代码:

  1. $rt = [];
  2. // 获取元素下的HTML内容
  3. $rt[] = $ql->find('#one>.two')->html();
  4. // 获取元素下的text内容
  5. $rt[] = $ql->find('.two')->text();
  6. print_r($rt);

采集结果:

  1. Array
  2. (
  3. [0] => <a href="http://querylist.cc">QueryList官网</a>
  4. <img src="http://querylist.com/1.jpg" alt="这是图片" abc="这是一个自定义属性">
  5. <img src="http://querylist.com/2.jpg" alt="这是图片2">
  6. <a href="http://doc.querylist.cc">QueryList文档</a>
  7. [1] => QueryList官网
  8. QueryList文档
  9. )



获取多个元素的单个属性

map()方法用于遍历多个元素的集合,find()方法返回的其实是多个元素的集合,这一点与jQuery也是一致的。

{info} QueryList中凡是涉及到集合的地方返回的都是Collection集合对象,这个对象有个all()方法,用于把当前对象转成数组,所以你会发现下面很多写法都是$data->all() 。

获取class为two的元素下的所有图片的alt属性

采集代码:

  1. $data1 = $ql->find('.two img')->map(function($item){
  2. return $item->alt;
  3. });
  4. // 等价下面这句话
  5. $data2 = $ql->find('.two img')->attrs('alt');
  6. print_r($data1->all());
  7. print_r($data2->all());

采集结果:

  1. Array
  2. (
  3. [0] => 这是图片
  4. [1] => 这是图片2
  5. )
  6. Array
  7. (
  8. [0] => 这是图片
  9. [1] => 这是图片2
  10. )

获取选中元素的所有html内容和text内容

采集代码:

  1. $texts = $ql->find('.two>a')->texts();
  2. $htmls = $ql->find('#one span')->htmls();
  3. print_r($texts->all());
  4. print_r($htmls->all());

采集结果:

  1. Array
  2. (
  3. [0] => QueryList官网
  4. [1] => QueryList文档
  5. )
  6. Array
  7. (
  8. [0] => 其它的<b>一些</b>文本
  9. )



实战 - 采集IT之家文章页

img

如图采集IT之家文章页的:文章标题、作者和正文内容。

采集代码:

  1. use QL\QueryList;
  2. $ql = QueryList::get('https://www.ithome.com/html/discovery/358585.htm');
  3. $rt = [];
  4. // 采集文章标题
  5. $rt['title'] = $ql->find('h1')->text();
  6. // 采集文章作者
  7. $rt['author'] = $ql->find('#author_baidu>strong')->text();
  8. // 采集文章内容
  9. $rt['content'] = $ql->find('.post_content')->html();
  10. print_r($rt);

采集结果:

  1. Array
  2. (
  3. [title] => 巴基斯坦一城镇温度达50.2度:创下全球4月历史温度新高
  4. [author] => 白猫
  5. [content] => <p><a class="s_tag" href="https://www.ithome.com/" target="_blank">IT之家</a>5月6日消息 4月份就遇到超过50度的极端天气显然是不可想象的,不过这的的确确发生在我们的周围,目前在巴基斯坦的一个城镇,有气象观测站显示该地的温度最高达到50.2度,打破了全球有记录以来的四月最高温。</p>
  6. <p><img src="//img.ithome.com/images/v2/t.png" w="600" h="400" class="lazy" title="巴基斯坦一城镇温度达50.2度:创下全球4月历史温度新高" data-original="https://img.ithome.com/newsuploadfiles/2018/3/20180323_103720_572.png" width="600" height="400"></p>
  7. <p>根据天空新闻的报道,在位于巴基斯坦南部的纳瓦布沙在周一(430日)的时候出现了高达50.2度的气温,气象学家表示这或许是人类有史以来遇到的四月份最高的温度。</p>
  8. <p>法国气象局的气象学家卡比奇安在推特上表示,巴基斯坦的这个小城镇不但是有史以来亚洲遇到的最高的四月气温,更有可能是全球四月的最高温,而也有网友表示由于过于炎热的天气,当地已经有不少人因为中暑而丧命。</p>
  9. <p>全球极端天气专家克里斯托弗伯特也表示,四月份就达到50摄氏度极其罕见,纳瓦布沙的温度或将是人类有史以来遇到的温度最高的四月。农业学家表示巴基斯坦过高的温度会严重影响未来粮食的收割。</p>
  10. )