用Goutte爬虫整合进php项目(ProcessWire)的思路
记录一下用Goutte整合到ProcessWire项目的过程:
建立一个Page存放已经抓取过的URL
每次对URL产生Request前先看看这个页面是不是已经爬过了,然后再做相应更新或者跳过的处理,虽然Goutte不能像binux大神的pyspider以服务形态工作,但是也可以通过人工重复运行爬虫项目更新,或者使用crontab去执行定时任务,这里不做过多说明。
建立一个Page存放并运行Goutte爬虫项目
该Page下存储各个Spider项目,结构应该是这样子的:
Spiders:
----a.com
--------entry1
--------entryN
----B.com
--------entry1
--------entryN
通用爬虫规则
应付简单的内容抓取,为爬虫添加规则配置字段,前面已经说过如何用json存储配置信息,配置内容:
"bikes":{ //项目中的列表页/频道,可能同一个站点爬去不同的列表 "url":"http://www.***.com/cn/zh_CN/%E8%87%AA%E8%A1%8C%E8%BD%A6/c/B100/", //URL "pagination":"Next", //下一页 "content":{ //内容提取页配置 "link":".product-tile__button", //列表页中对内容页的链接提取 "title": ".buying-zone__title", //内容字段,标题 "images": { //图片提取,提取内容中独立的图片项目/相册等 "item" => ".pdp-thumbnails_item data-zoom-src", //图片的CSSSelector "src" => "src" //有些情况下原始图片特别是使用了放大镜插件的时候,并不是src而是zoom-src等 }, "content": "main" //正文的提取 }, }, "components", { "url":"http://www.***.com/cn/zh_CN/%E8%A3%85%E5%A4%87/%E8%87%AA%E8%A1%8C%E8%BD%A6%E9%83%A8%E4%BB%B6/c/E200/", "pagination":"Next", "content":{ "link":".product-tile__button", "title": ".buying-zone__title", "images": { "item" => ".pdp-thumbnails_item data-zoom-src", "src" => "src" }, "content": "main" }, }
有了通用的规则之后每次只需要添加spider的页面并修改相应规则就能应付绝大大部分情况了。
特殊情况的处理
规则已经不管用的时候独立编写规则,spider项目读取配置前先看看独立的spider项目文件在不在,如果在就直接运行该项目,这么一来你就可以抓取任何你想要抓的数据了。
一些常用的代码片段
链接的提取
$crawler->filter($spiderItem->content->link)->each(function($node){ $url = $node->extract(array('href')); }
内容的提取
if($crawler1->filter($contentItem->title)->count()) { $form['title'] = $crawler1->filter($contentItem->title)->text(); }
分页的处理
if($spiderItem->pagination) { $paginationCount = $crawler->selectLink($spiderItem->pagination)->count(); if($paginationCount) { do{ $linkcount = $crawler->selectLink($spiderItem->pagination)->count(); if($linkcount == 0) break; $pagelink = $crawler->selectLink($spiderItem->pagination)->link(); $pageurl = $crawler->selectLink($spiderItem->pagination)->extract(array('href')); if(empty($pageurl[0])) break; $crawler = $goutteClient->click($pagelink); try{ $crawler->filter($spiderItem->content->link)->each(function($node){ //处理内容 } }catch(GuzzleHttp\Exception\ConnectException $e) { continue; } }while(!empty($pagelink)); } }