用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));
}
}