简化日常工作系列之二 ----- 定时采集小说

2.去跑一遍采集小说的脚本任务

为了减少依赖,之前采集小说的实现是两部分:
第一部分:nodejs去目录页抓取章节的url,写入txt文件存储。
第二部分:php利用封装的curl类和分析解析类去分别获取标题内容,写入HTML文件。

这样不仅要让进行定时任务的物理机或docker上要有php环境也要有nodejs环境。由于我擅长php,所以改为两部分全部由php完成。采集的完整代码可以见前面写过的采集类等博客。

curl封装类beta版的博客记录: http://www.cnblogs.com/freephp/p/4962591.html.
优化curl封装类的博客记录: http://www.cnblogs.com/freephp/p/5112135.html.

如果不熟悉的朋友,可以先看这部分博客后再阅读本文。

代码关键部分:

$menuUrl = ‘http://www.zhuaji.org/read/2531/‘;
$menuContents = MyCurl::send($menuUrl, ‘get‘);

$analyzer = new Analyzer();
$urls = $analyzer->getLinks($menuContents);

后面再循环去curl每个章节页面,抓取和解析内容并写入文件即可。
代码简洁和可读性已经比较好了。现在我们考虑效率和性能问题。这个代码都是一次性下载完所有文件,唯一做去重判断都是在每次get到章节内容之后对比文件名是否存在。但已经做了一些无用费时的网络请求。目前该小说有578章,加上目录被爬一次,一共要发起578+1次get请求,以后小说还会不断增加章节,那么执行时间会更长。

这个脚本最大的瓶颈就在网络消耗上。

此脚本效率不高,每次都是把所有章节的页面都去爬一次,网络消耗很大。如果是第一次下载还好,毕竟要下载全部。如果是每天都执行,那么其实我是想增量地去下载前一天新增的章节。

又有几个思路可以考虑:
1.我们要考虑每次执行之后最后一个被存下来的页面的id要记录下来。然后下一次就从这个id开始继续下载。
2.中间断掉也可以反复重新跑。(遵从第一条最后一句)

这样就能从新增的页面去爬,减少了网络请求量,执行效率大幅提高。

其实这个问题就变成想办法记录执行成功的最后一个章节id的问题了。
我们可以把这个id写入数据库,也可以写入文件。为了简单和少依赖,我决定还是写文件。

单独封装一个获取最大id的函数,然后过滤掉已经下载的文件。完整代码如下:

function getMaxId() {
    $idLogFiles = ‘./biggestId.txt‘;

    $biggestId = 0;
    if (file_exists($idLogFiles)) {
        $fp = fopen($idLogFiles, ‘r‘);
        $biggestId = trim(fread($fp, 1024));
        fclose($fp);
    }
    return $biggestId;
}
/**
 * ?client to run
 */
set_time_limit(0);
require ‘Analyzer.php‘;
$start = microtime(true);
$menuUrl = ‘http://www.zhuaji.org/read/2531/‘;
$menuContents = MyCurl::send($menuUrl, ‘get‘);
$biggestId = getMaxId() + 0;
$analyzer =new Analyzer();
$urls = $analyzer->getLinks($menuContents);
$ids = array();
foreach ($urls as $url) {
    $parts = explode(‘.‘, $url);
    array_push($ids, $parts[0]);
}
sort($ids, SORT_NUMERIC);
$newIds = array();
foreach ($ids as &$id) {
    if ((int)$id > $biggestId) array_push($newIds, $id);
}
if (empty($newIds)) exit(‘nothing to download!‘);

foreach ($newIds as $id) {
    $url = $id . ‘.html‘;
    $res = MyCurl::send(‘http://www.zhuaji.org/read/2531/‘ . $url, ‘get‘);
    $title = $analyzer->getTitle($res)[1];

    $content = $analyzer->getContent(‘div‘, ‘content‘, $res)[0];

    $allContents = $title . "<br/>". $content;
    $filePath = ‘D:/www/tempscript/juewangjiaoshi/‘ . $title . ‘.html‘;
    if(!file_exists($filePath)) {
        $analyzer->storeToFile($filePath, $allContents);
        $idfp = fopen(‘biggestId.txt‘, ‘w‘);
        fwrite($idfp, $id);
        fclose($idfp);
    } else {
        continue;
    }
    echo ‘down the url:‘ , $url , "\r\n";
}

$end = microtime(true);
$cost = $end - $start;
echo "total cost time:" . round($cost, 3) . " seconds\r\n";

加在windows定时任务或linux下的cron即可每天享受小说的乐趣,而不用每次手动去浏览网页浪费流量,解析后的html文件存文字版更舒服。不过这段代码在低版本的php下会报错,数组简化写法[44,3323,443]是在php5.4之后才出现的。

之前下载完所有小说需要大概2分多钟。改进最终结果为:

效果显著,我在/etc/crontab里面设置如下:

0 3 * * * root /usr/bin/php /data/scripts/tempscript/MyCurl.php >> /tmp/downNovel.log

这个作者的小说真心不错,虽然后期写得很后宫和文字匮乏,常到12点还在更新,所以把每天定时任务放在凌晨3点采集之。

时间: 2024-08-12 07:46:21

简化日常工作系列之二 ----- 定时采集小说的相关文章

SCCM 2012 R2实战系列之二:前提工作准备

在上一篇中,我们完成了SQL Server 2012的安装和配置.现在跟大家分享SCCM安装前的准备工作. 2.1 SCCM 2012 R2 准备工作 2.1.1 创建并分配System Management容器权限 打开ADSI编辑器,连接到"默认命名上下文"---右击"system"新建对象---选择"container"-下一步---填写值"system management"---下一步---完成 分配System M

系统运维日常工作有哪些,应该具备哪些技能

一.日常工作内容: 1.看监控.网站流量,CDN流量,看邮件有没有普通业务监控报警,看邮件中有没其他需要做的工作 2.处理报警,查看报警的原因,和开发一起解决,并且尽量找出避免再次发生的方法,例如添加一些 定时清理脚本 3.处理发布,基本都是自动化,但是总有发布不成功或者需要回滚的时候,这时候就需要手工介入, 找到原因,并跟开发一起讨论最后是否撤销还是重上 4.日常一起能够自动化的工作尽量找到自动化的方法 5.配合开发搭建测试环境,线上环境,上线代码,以及日常开个权限 6.定期机房巡检 7.灾备

MySQL数据库性能优化及自动化运维实践教程!DBA日常工作

MySQL数据库性能优化及自动化运维实践教程!本文作者将站在更加全面的角度分享他在这一年多 DBA 工作中的经验,希望可以给大家带来启发和帮助. DBA 的日常工作 我觉得 DBA 真的很忙,我们来看看 DBA 的具体工作:备份和恢复.监控状态.集群搭建与扩容.数据迁移和高可用. 上面这些是我们 DBA 的功能,了解这些功能以后要对体系结构有更加深入的了解,你不知道怎么处理这些故障和投诉的事情. 所以我们要去了解缓存/线程.SQL 优化.存储引擎.SQL 审计以及锁与实务:体系结构更深一点,就去

算法系列之二十三:离散傅立叶变换之音频播放与频谱显示

算法系列之二十三:离散傅立叶变换之音频播放与频谱显示 算法系列之二十三离散傅立叶变换之音频播放与频谱显示 导语 什么是频谱 1 频谱的原理 2 频谱的选择 3 频谱的计算 显示动态频谱 1 实现方法 2 杂项说明 结果展示 导语 频谱和均衡器,几乎是媒体播放程序的必备物件,没有这两个功能的媒体播放程序会被认为不够专业,现在主流的播放器都具备这两个功能,foobar 2000的十八段均衡器就曾经让很多人着迷.在上一篇对离散傅立叶变换介绍的基础上,本篇就进一步介绍一下频谱是怎么回事儿,下一篇继续介绍

[Axis2与Eclipse整合开发Web Service系列之二] Top-Down方式,通过WSDL逆向生成服务端(续)

前言 本篇是承接上一篇: [Axis2与Eclipse整合开发Web Service系列之二] Top-Down方式,通过WSDL逆向生成服务端 在上一篇粗略地介绍了如何使用Top-Down的方式创建一个web service .  但是对于如何部署及调用,以及一些细节的部分基本上没有介绍. 应某些博友的要求, 也适逢自己有空, 接下来就详细介绍一下整个部分如何进行. 环境准备 JDK 肯定要安装了, 这个就不多讲了. 1. eclipse  3.5.2 对eclipse 版本的要求其实不是很严

Tokyo Tyrant(TTServer)系列(二)-启动参数和配置

启动参数介绍 ttserver命令可以启动一个数据库实例.因为数据库已经实现了Tokyo Cabinet的抽象API,所以可以在启动的时候指定数据库的配置类型. 支持的数据库类型有: 内存hash数据库 内存tree数据库 hash数据库 B+ tree数据库, 命令通过下面的格式来使用,'dbname'制定数据库名,如果省略,则被视作内存hash数据库. ttserver [-host name] [-port num] [-thnum num] [-tout num] [-dmn] [-pi

企业内部IT一体化系列之二:系统角色

继续上一章的内容,这章主要将整个系统中每个角色详细讲解一下: SharePoint结构: 由于我在做这个项目的时候,所有的系统要求都是高可用,且公司人员基数也大,所有服务器都是高可用的结构,总过7台服务器,三层结构.两台WEB前端服务器,提供IIS服务,两台APP服务器,重要跑SharePoint的各种应用和服务,比如搜索服务,用户配置同步服务等.两台数据库服务器提供一个数据库群集,一台单独数据库服务器提供报表服务,因为report服务不支持群集.如下图: Operation Manager即S

C#微信公众号开发系列教程二(新手接入指南)

http://www.cnblogs.com/zskbll/p/4093954.html 此系列前面已经更新了两篇博文了,都是微信开发的前期准备工作,现在切入正题,本篇讲解新手接入的步骤与方法,大神可直接跳过,也欢迎大神吐槽. 目录 C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) 微信公众平台消息接口的工作原理大概可以这样理解:从用户端到公众号端一个流程是这样的,用户发送消息到微信服务器,微

Sql Server来龙去脉系列之二 框架和配置

数据库对象 数据库维持了一系列表存储所有对象.数据类型/约束/配置项/资源等,在2008种我们叫他们为system base tables,并且这些表我们默认是看不到的.我们可以通过管理员登陆数据库,然后执行脚本: USE master; SELECT name FROM sys.objects WHERE type_desc = 'SYSTEM_TABLE'; 能查看到几十条数据.一般我们是不能查看到这些表里边的任何数据,只有通过DAC方式连接数据库才能查看到数据.这些数据主要被数据库引擎使用