一个简单的开源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的查找路径),执行这个脚本,得到的输出如下:

[[email protected] 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。祝大家国庆节快乐~!

时间: 2024-08-06 09:57:39

一个简单的开源PHP爬虫框架『Phpfetcher』的相关文章

开源通用爬虫框架YayCrawler-开篇

各位好!从今天起,我将用几个篇幅的文字向大家介绍一下我的一个开源作品——YayCrawler,其在GitHub上的网址是:https://github.com/liushuishang/YayCrawler,欢迎大家关注和反馈. YayCrawler是一个基于WebMagic开发的分布式通用爬虫框架,开发语言是Java.我们知道目前爬虫框架很多,有简单的,也有复杂的,有轻量型的,也有重量型的.您也许会问:你这个爬虫框架的优势在哪里呢?额,这个是一个很重要的问题!在这个开篇中,我先简单的介绍一下我

一个简单好用的日志框架NLog

之前我介绍过如何使用log4net来记录日志,但最近喜欢上了另一个简单好用的日志框架NLog. 关于NLog和log4net的比较这里就不多讨论了,感兴趣的朋友可以参看.NET日志工具介绍和log4net vs. Nlog这两篇文章.本文主要介绍一下如何在项目中使用NLog. 在Nuget中安装NLog NLog可以直接使用Nuget安装: PM > Install-Package Nlog 使用NLog NLog的使用方式基本上和其它的Log库差不多,分为Trace.Debug.Info.Er

实现一个简单的邮箱地址爬虫(python)

我经常收到关于email爬虫的问题.有迹象表明那些想从网页上抓取联系方式的人对这个问题很感兴趣.在这篇文章里,我想演示一下如何使用python实现一个简单的邮箱爬虫.这个爬虫很简单,但从这个例子中你可以学到许多东西(尤其是当你想做一个新虫的时候). 我特意简化了代码,尽可能的把主要思路表达清楚.这样你就可以在需要的时候加上自己的功能.虽然很简单,但完整的实现从网上抓取email地址的功能.注意,本文的代码是使用python3写的. 好.让我们逐步深入吧.我一点一点的实现,并加上注释.最后再把完整

一个方便易用的爬虫框架

本文转载至  http://www.tuicool.com/articles/VZBj2e 原文  http://itindex.net/detail/52388-框架 webmagic的是一个无须配置.便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫. 官方网站  http://webmagic.io/ webmagic是一个开源的Java垂直爬虫框架,目标是简化爬虫的开发流程,让开发者专注于逻辑功能的开发.webmagic的核心非常简单,但是覆盖爬虫的整个流程,也

一个简单的多线程Python爬虫

最近想要抓取拉勾网的数据,最开始是使用Scrapy的,但是遇到了下面两个问题: 前端页面是用JS模板引擎生成的 接口主要是用POST提交参数的 目前不会处理使用JS模板引擎生成的HTML页面,用POST的提交参数的话,接口统一,也没有必要使用Scrapy,所以就萌生了自己写一个简单的Python爬虫的想法. 一个爬虫的简单框架 一个简单的爬虫框架,主要就是处理网络请求,Scrapy使用的是Twisted(一个事件驱动网络框架,以非阻塞的方式对网络I/O进行异步处理),这里不使用异步处理,等以后再

一个简单的python线程池框架

初学python,实现了一个简单的线程池框架,线程池中除Wokers(工作线程)外,还单独创建了一个日志线程,用于日志的输出.线程间采用Queue方式进行通信. 代码如下: 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 __author__ = "pandaychen" 5 6 import Queue 7 import sys 8 import os 9 import threading 10 import time 11

一个简单的文件系统过滤驱动框架

很多人认为文件系统过滤驱动很复杂,其实也有一定道理,因为需要有很多细节需要考虑到,这是一个简单的文件系统过滤驱动,抛去了大部分细节,留下了一个简单的框架,其实这样文件系统过滤驱动就变得蛮简单的,很多接口可以不用实现,只要知道大致流程,其它都将会很清晰. #define DBG 1 #include <ntifs.h> #include "fsfilter.h" PDEVICE_OBJECT g_Cdo; PDRIVER_OBJECT g_MyDriver; NTSTATUS

开源通用爬虫框架YayCrawler-页面的抽取规则定义

本节我将向大家介绍一下YayCrawler的核心-页面的抽取规则定义,这也是YayCrawler能够做到通用的主要原因之一.如果我要爬去不同的网站的数据,尽管他们的网站采用的开发技术不同.页面的结构不同,但是我只要针对不同的网站定义不同的抽取规则即可,不用再对每个网站专门开发一个爬虫. 首先让我来解释几个概念: 一.页面(Page) 这里说的页面不是指在浏览器上能直接看到的页面,而是指一个http请求发送后服务端返回的response中的内容.它大多数情况是一个html文档,也可能是一个Json

开源通用爬虫框架YayCrawler-运行与调试

本节我将向大家介绍如何运行与调试YayCrawler.该框架是采用SpringBoot开发的,所以可以通过java –jar  xxxx.jar的方式运行,也可以部署在tomcat等容器中运行. 首先让我们介绍一下运行环境: 1.jdk8 2.安装mysql数据库,用作存储解析规则等数据 3.安装redis,用作任务队列 4.安装mongoDB用于存放结果数据 5.安装ftp服务器软件ftpserver(可选,用于存放下载图片) 一.运行发布包 首先从https://github.com/liu