一个简单的开源PHP爬虫框架『Phpfetcher』
这篇文章首发在吹水小镇:http://blog.reetsee.com/archives/366
要在手机或者电脑看到更好的图片或代码欢迎到博文原地址。也欢迎到博文原地址批评指正。
转载请注明: 吹水小镇
| reetsee.com
原文链接地址: http://blog.reetsee.com/archives/366
——————————————————————————————
好久不见了!
我最终又写一篇日志了,本来有非常多流水帐想发可是感觉没营养,就作罢了。今天我主要分享一个简单的PHP爬虫框架。名字叫:Phpfetcher项目的地址是:https://github.com/fanfank/phpfetcher这个框架的作者是:reetsee.xu。即吹水。
把整个项目下载下来后,在Linux下的终端直接运行demo目录下的single_page.php就可以看到效果。
只是在运行demo文件前,先设置一下你的终端编码为UTF-8以免显示乱码:
export LANG=en_US.UTF-8
————————————————————————————————
0 背景
背景是这种眼下吹水新闻(http://news.reetsee.com)下的内容所有由Python的爬虫抓取。使用的框架是Python的Scrapy。而吹水新闻眼下是执行在BAE(百度应用引擎)下的,每一个月还须要交钱。眼下我的想法是把吹水新闻全然迁移到眼下这台阿里云主机上。并且原本的新闻我每天都手动执行一次脚本来抓取再更新到站点,等迁移到这里后就能直接使用Crontab定时脚本自己主动更新新闻了!
近期工作都在用PHP,开发站点的新页面要PHP,直接读写数据库也能用PHP,那么就直接用PHP重构新闻站点好了。
准备开干的时候却发现没找到一个好的PHP爬虫框架(可能是我没细致找)。于是就打算自己写一个,因此就有了这个Phpfetcher。名字起得略好……可是代码写得略搓……无论怎么样。眼下基本能够用,并且应该能满足不少简单的需求,以下就是使用演示样例。
1 基本概念
在Phpfetcher中有四个基本的对象。依次是:Dom,Page。Crawler,Manager。
- Dom对象用来解析html,可以訪问html里的dom;
- Page对象相应到一个详细的html页面,可以取得整个网页的内容,Page对象中有一个Dom对象的成员;
- Crawler对象可以理解为就是爬虫对象,用来设置要爬取页面的规则。
- Manager对象原本是用来管理Crawler对象的。以后也许能用来在多进程环境下使用,但眼下没有实现,所以临时没实用;
大致概念就是这样了,实际使用主要是操作Crawler对象。在Phpfetcher中。你能够实现自己的Dom,Page和Crawler,仅仅要符合基类的要求就可以。
要说明的是Phpfetcher的默认Page对象中的Dom对象使用的是simple_html_dom,没有使用PHP提供的DOMDocument类,由于我发现DOMDocument对HTML格式的内容兼容性比較差。有时网页中混入其他内容时可能解析不出dom。以下这张是图是Phpfetcher的文件夹结构:你能够依据自己的须要定制想要的Crawler,Page,Dom类。默认情况下我提供了Crawler的默认类是Phpfetcher_Crawler_Default。Page的默认类是Phpfetcher_Page_Default。Dom的默认类是Phpfetcher_Dom_SimpleHtmlDom。类名和它们所在的路径有相应关系。要注意的是,在使用默认的Page对象时须要PHP的curl库,使用默认的Crawler对象时须要使用PHP的mb_string库,没有的须要装一下。为了便于理解。我画了几张图,第一张是Phpfetcher的三个主要对象之间的关系:
图里表示的是Crawler里面有Page的对象,Page里面有Dom的对象。
在使用Phpfetcher时,最重要的是完毕下图中两个绿色矩形框要求的事情:即你要写一个类继承Phpfetcher提供的Crawler类,然后在你自己的类中实现一个名为handlePage($page)的函数。
当中$page參数是一个Phpfetcher的Page类对象。最后这里给出一个主要的流程图: 上面说的东西有点虚,那还是直接看实例吧!
2 简单样例
****** 实例1:single_page.php ******比如我们要抓取这个站点的内容:http://news.qq.com/a/20140927/026557.htm里面有非常多超链接。有标题,有新闻具体内容。或者其他我们关心的内容。
先看一下以下的样例:
<? php
require_once('phpfetcher.php');
class mycrawler extends Phpfetcher_Crawler_Default {
public function handlePage($page) {
//打印处当前页面的title
$res = $page->sel('//title');
for ($i = 0; $i < count($res); ++$i) {
echo $res[$i]->plaintext;
echo "\n";
}
}
} $crawler = new mycrawler();
$arrJobs = array(
//任务的名字随便起,这里把名字叫qqnews
//the key is the name of a job, here names it qqnews
'qqnews' => array(
'start_page' => 'http://news.qq.com/a/20140927/026557.htm', //起始网页
'link_rules' => array(
/*
* 全部在这里列出的正则规则,仅仅要能匹配到超链接,那么那条爬虫就会爬到那条超链接
* Regex rules are listed here, the crawler will follow any hyperlinks once the regex matches
*/
),
//爬虫从開始页面算起。最多爬取的深度,设置为1表示仅仅爬取起始页面
//Crawler's max following depth, 1 stands for only crawl the start page
'max_depth' => 1, ) ,
); //$crawler->setFetchJobs($arrJobs)->run(); 这一行的效果和以下两行的效果一样
$crawler->setFetchJobs($arrJobs);
$crawler->run();
将这个脚本和“phpfetcher.php”以及“Phpfetcher”文件夹放在同一个文件夹下(或者将“phpfetcher.php”和“Phpfetcher”放到你的PHP环境默认include的查找路径),运行这个脚本,得到的输出例如以下:
[root@reetsee demo]# php single_page.php
王思聪回应遭警方调查:带弓箭不犯法 我是绿箭侠_新闻_腾讯网
查看一下我们抓取的网页源码。能够发现是以下这几行中的title标签内容提取出来了:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"></meta>
<meta charset="gb2312"></meta>
<title>
王思聪回应遭警方调查:带弓箭不犯法 我是绿箭侠_新闻_腾讯网
</title>
上面就是一个最简单的样例。 ****** 实例2:multi_page.php ******接下来就是另外一个简单的样例,比如说腾讯新闻的主页,上面有各种新闻,我们这次的目标是把腾讯新闻主页(http://news.qq.com)显示的部分新闻标题抓下来。直接先上例程:
<? php
//以下两行使得这个项目被下载下来后本文件能直接执行
$demo_include_path = dirname(__FILE__) . '/../';
set_include_path(get_include_path() . PATH_SEPARATOR . $demo_include_path); require_once('phpfetcher.php');
class mycrawler extends Phpfetcher_Crawler_Default {
public function handlePage($page) {
//打印处当前页面的第1个h1标题内荣(下标从0開始)
$strFirstH1 = trim($page->sel('//h1', 0)->plaintext);
if (!empty($strFirstH1)) {
echo $page->sel('//h1', 0)->plaintext;
echo "\n";
}
}
} $crawler = new mycrawler();
$arrJobs = array(
//任务的名字随便起。这里把名字叫qqnews
//the key is the name of a job, here names it qqnews
'qqnews' => array(
'start_page' => 'http://news.qq.com', //起始网页
'link_rules' => array(
/*
* 全部在这里列出的正则规则,仅仅要能匹配到超链接,那么那条爬虫就会爬到那条超链接
* Regex rules are listed here, the crawler will follow any hyperlinks once the regex matches
*/
'#news\.qq\.com/a/\d+/\d+\.htm$#',
),
//爬虫从開始页面算起,最多爬取的深度,设置为2表示爬取深度为1
//Crawler's max following depth, 1 stands for only crawl the start page
'max_depth' => 2, ) ,
); $crawler->setFetchJobs($arrJobs)->run(); //这一行的效果和以下两行的效果一样
//$crawler->setFetchJobs($arrJobs);
//$crawler->run();
相比于第1个样例,变化的地方有几个:首先这次我们添加了一条爬虫跟踪的规则“#news\.qq\.com/a/\d+/\d+\.htm$#”(注:PHP使用pcre正則表達式,能够到PHP关于正則表達式的页面看一下)。这是一个正則表達式。比如这样的超链接“news.qq.com/a/12345678/00234.htm”那么爬虫就会跟踪。然后是我们把爬虫的最大跟踪深度设置为2,这样爬虫会跟踪1次起始页面上符合要求的超级链接;最后是我把原本的Dom选择从“//title”改为了“//h1”。意思就是抓取h1标签的内容而不是像之前那样抓取title标签,想知道这样的Dom选择器的选择规则,须要了解一下xpath。执行这个文件,能够看到大致效果例如以下: 这样第二个样例就结束了。
临时我就介绍这两个样例吧,Phpfetcher的源码在这里:https://github.com/fanfank/phpfetcher把代码下载下来后。demo内的东西就能够直接执行了(当然你须要一个有curl和mb_string扩展的php,能够使用“php
-m”命令来看一下你的PHP有没有装这两个扩展)。
3 后话
实际上这个phpfetcher眼下还有非常多问题,性能应该是比較差的,只是毕竟也是我写的第一个框架。另外是关于phpfetcher我有非常多东西还没有提到,比如Page对象的一些设置,Crawler对象的设置等,主要是眼下太过懒不想写文档,也不知道有没有必要写。我感觉这个框架还是蛮简单的,里面基本的函数我都做了具体的凝视,欢迎阅读批评指正给建议!最后就是,假设你想写个爬虫,又想用PHP来写,最好还是试一下phpfetcher。祝大家国庆节快乐~!
一个简单的开源PHP爬虫框架『Phpfetcher』的更多相关文章
- 开源通用爬虫框架YayCrawler-开篇
各位好!从今天起,我将用几个篇幅的文字向大家介绍一下我的一个开源作品--YayCrawler,其在GitHub上的网址是:https://github.com/liushuishang/YayCraw ...
- 一个简单的多线程Python爬虫(一)
一个简单的多线程Python爬虫 最近想要抓取拉勾网的数据,最开始是使用Scrapy的,但是遇到了下面两个问题: 前端页面是用JS模板引擎生成的 接口主要是用POST提交参数的 目前不会处理使用JS模 ...
- 如何创建一个简单的C++同步锁框架(译)
翻译自codeproject上面的一篇文章,题目是:如何创建一个简单的c++同步锁框架 目录 介绍 背景 临界区 & 互斥 & 信号 临界区 互斥 信号 更多信息 建立锁框架的目的 B ...
- 一个简单好用的日志框架NLog
之前我介绍过如何使用log4net来记录日志,但最近喜欢上了另一个简单好用的日志框架NLog. 关于NLog和log4net的比较这里就不多讨论了,感兴趣的朋友可以参看.NET日志工具介绍和log4n ...
- 一个自定义python分布式专用爬虫框架。支持断点爬取和确保消息100%不丢失,哪怕是在爬取进行中随意关停和随意对电脑断电。
0.此框架只能用于爬虫,由框架来调度url请求,必须按照此方式开发,没有做到类似celery的通用分布式功能,也不方便测试.可以使用另外一个,基于函数式编程的,调度一切函数的分布式框架,做到了兼容任何 ...
- 一个简单的python线程池框架
初学python,实现了一个简单的线程池框架,线程池中除Wokers(工作线程)外,还单独创建了一个日志线程,用于日志的输出.线程间采用Queue方式进行通信. 代码如下:(不足之处,还请高手指正) ...
- 实现一个简单的邮箱地址爬虫(python)
我经常收到关于email爬虫的问题.有迹象表明那些想从网页上抓取联系方式的人对这个问题很感兴趣.在这篇文章里,我想演示一下如何使用python实现一个简单的邮箱爬虫.这个爬虫很简单,但从这个例子中你可 ...
- 开源通用爬虫框架YayCrawler-框架的运行机制
这一节我将向大家介绍一下YayCrawler的运行机制,首先允许我上一张图: 首先各个组件的启动顺序建议是Master.Worker.Admin,其实不按这个顺序也没关系,我们为了讲解方便假定是这个启 ...
- 开源通用爬虫框架YayCrawler-页面的抽取规则定义
本节我将向大家介绍一下YayCrawler的核心-页面的抽取规则定义,这也是YayCrawler能够做到通用的主要原因之一.如果我要爬去不同的网站的数据,尽管他们的网站采用的开发技术不同.页面的结构不 ...
随机推荐
- 20165235 祁瑛 2018-4 《Java程序设计》第七周学习总结
20165235 祁瑛 2018-4 <Java程序设计>第七周学习总结 教材学习内容总结 MySQL数据管理系统 MySQL数据管理系统,简称MySQL,是世界上流行的数据管理系统. M ...
- Idea问题:“marketplace plugins are not loaded”解决方案
博主本人遇见该问题时是想要通过Idea的plugins工具下载阿里巴巴的代码规约工具 但是在我点开settings,然后打开plugins工具时竟然给我提示“marketplace plugins a ...
- Python 爬虫利器 Selenium 介绍
Python 爬虫利器 Selenium 介绍 转 https://mp.weixin.qq.com/s/YJGjZkUejEos_yJ1ukp5kw 前面几节,我们学习了用 requests 构造页 ...
- Java中位运算符的使用
先预知识: 数据在计算机中是以二进制的形式进行存储的,而二进制在内存中是以补码的形式进行存储的.在介绍位运算之前,首先来看一下原码.反码和补码的概念.由于正数的原码.反码和补码的形式都是一样的,所以以 ...
- 大数据小白系列——HDFS(2)
这里是大数据小白系列,这是本系列的第二篇,介绍一下HDFS中SecondaryNameNode.单点失败(SPOF).以及高可用(HA)等概念. 上一篇我们说到了大数据.分布式存储,以及HDFS中的一 ...
- Left join on where 区别
on 后面 直接加条件的话,不会对左边的表产生影响,on条件是在左关联时候的条件,不管如何都会返回左边表中的记录 where 加条件 才会对左边的表 生效.where条件是关联查询之后的条件
- 一个小demo 实用selenium 抓取淘宝搜索页面内的产品内容
废话少说,上代码 #conding:utf-8 import re from selenium import webdriver from selenium.webdriver.common.by i ...
- NOIP2017 题解(给自己看的) --有坑要填
目录 D1T1精妙证明: D1T3 D2T2 几道水题就不写了.... D1T1精妙证明: 把ax+by = z 的z按照模a剩余系分类 由于\((a,b)=1\)所以对于每个\(k\in[0, a) ...
- idea中Hibernate反向生成工具
HIbernate反向生成工具 1.使用idea数据库集成工具连接所需数据库 第一步 View-->Tool windows---->Database 第二步 找到所需连接的数据库 第三步 ...
- BZOJ4912 : [Sdoi2017]天才黑客
建立新图,原图中每条边在新图中是点,点权为$w_i$,边权为两个字符串的LCP. 对字典树进行DFS,将每个点周围一圈边对应的字符串按DFS序从小到大排序. 根据后缀数组利用height数组求LCP的 ...