以下内容节选自我的github码农周刊整理repo,欢迎大家star。

写在最前面的话

作为最初的一批码农周刊的订阅者,不能说经历了其成长,但是确实见证了他的壮大。码农周刊确实从开始第一期的基本上都是精选的满满的干货,至少从我收到的每一期的一周精选看真是如此。但是随着时间的累计,一周精选的总量变得很大,到我写这些话的时候是280期。我就想,可不可以做个分类,让这些有心人分类的有用的资源更加有效率的被运用。

我要做什么

对于这个repo,我想做的主要其实就是以下两点:

  • 获取码农周刊第一期到当前最新一期的所有内容,做一个分类展示
  • 可以处理以后的每一期的更新,人工干预的越少越好

大饼已经画好了,考虑到我是一个程序员,秉承着能让机器帮我干事就就不应该自己费力气的原则,对于这么一个算不上特别有难度的事情,我开始了折腾之路。

我是怎么想的

我是这样想的,好歹也写了不少代码,不谈一谈我的心路历程,难以铺平我的技术人生。所以,这一部分是写我从一开始要做这个repo到写成所有代码的心路历程,和运行代码没有半点关系,但是我觉得对于代码注释还是有很大的帮助的。

万事开头难

其实这个东西,如果考虑的是从0开始,其思路还是很直观的,我相信在啥也不想,靠意识流的情况下基本就是思路一的节奏。但是随着思考的深入,动手的介入,脑子的进入,明显思路二才是最优的选择。

思路一 思路二
利用爬虫获取每一期码农周刊的内容,一条一条的标题和链接 利用爬虫获取每一期码农周刊的内容,一次性将所有的标题和链接存入文本文件
筛选每一条链接,主要去除无效链接 读取上述文本文件,根据配置文件中的分类关键词分类
对于每条链接,从配置文件中按照规则寻找关键字分类 一次性分类好,形成所有分好类的md文件
按照分类写入相应的md文件 处理所有的md文件,去除失效的链接,形成最终的md文件

为什么要采用思路二,主要有以下几点:

  • 思路二中每个步骤都是相对独立的文件,每个部分完成一个简单的小功能,keep it simple,stupid
  • 在这个过程中,最费时的就是探查链接是否有效,如果按照思路一的方式,基本要全部运行完才能获得最终可以git push的文件,而思路二,完全可以实现一边执行,一边获取部分完整可以git push上去的文件

然后后面更加难

我一直秉承着实用主义的原则,软件只是实现思想的工具,关键不是炫技而是要满足需求。那么,我已经可以从0开始获取到所有的markdown文件,那么下一个问题是怎样更新?首先,得明确在每次将要更新的时候自己有什么。

  • 已经分类好的若干md文件
  • 一个readme.md文件用来进行说明这玩意儿干什么

我的主要任务是当新一期出来之后更新若干md文件,这个更新当然是需要有效的,格式化好的md文本,并且用最少的力气。所以,我的思路是这样的:

  • 获取最新一期的内容
  • 重复上一节的过程。
  • 和按照文件名和现有的md文件合并。

说一说所谓分类关键词文件吧

这个repo有一个核心文件,这个在下一大节会具体说明,但是一开始我面临过的问题是,怎么分类,找哪些关键词?于是我想到了分词,但是这玩意儿其实没想象的那么好用,也不能说不好用,仅仅做一个参考吧。于是我就利用了分类后的结果,最主要的是得加上我这真“人工智能”,human intelligence,大体搞出了几类的关键词。而且这个东西基本只需要执行一次,因为分分类标准并不会剧烈变化,除非我们的语言变了。所以tools里面并没有这个相关的代码,但是放心,分类配置的json文件是有的。

另外,在分类分分的过程中,我发现我分出了感情。于是,我就开始自我展(chui)望(niu)一下,我也在开始用用人工智能,这次是AI,从这将近2w个样本中高出一个合理而又高效的计算机分类。不为别的,每当我在网上买计算机书籍的时候,我发现分类并不那么的合理,也许有一天,我能做出一套“行业”标准呢?

我是怎么做的

具体到实现上,按照我的初步想法,我写了这么几个文件:

  • GetAllTitles.py -> 这个是用来爬取码农周刊内容的,正式一点的话就叫爬虫部分吧
  • ExtractMD.py -> 这个是把爬虫保存下来的内容格式化好,并且根据分类配置文件,组织形成markdown文件,也就是呈现的主要内容
  • Erase404.py -> 名字起的不是特别恰当,其实我就留下了相应码是200的文件,顾名思义,剔除掉那些也许是年久失修,也许是已经被挪走的内容
  • MergeFile.py -> 这个是专门为更新写的,功能简单,就是把最新一期形成的markdown文件汇总到已经分类好的大的markdown文件之中
  • OmitDup.py -> 这个文件是后来添加的,目的是剔除markdown中重复的项目
  • category.json -> 这个是传说中的汇聚了自动分词加上human intelligence结果的分类配置文件

所有文件都完成独立的,简单的,弱智的的功能,互相有依赖但是功能上完全不会影响。对于我个人,我是很喜欢这种设计哲学的,以不要把事情搞复杂了为原则。 因为代码中没有注释,所以,接下来,我来稍微具体扯一扯这些文件是怎么用的。

GetAllTitles.py

由于命令行神器click的加入,所以无论编写还是使用都变得更加简单。使用python3 GetAllTitles.py --help可以看到该脚本有三个子命令:

  • new -> 获取从第一期到最新一期的所有码农周刊的内容
  • update -> 指定起始期数和结束期数,获取指定期数的内容,如果起始期数未指定,则从第一期开始,如果结束期数未指定,则一直获取到最新的一期
  • latest -> 获取最新一期的内容

在爬虫部分,我试过比较多的方法,为什么选用selenium这个偏向测试而不是爬虫的库?原因是我用了requests,但是码农周刊这个域名的签名有问题,使用requests的话会报错。我试了几个方法,都在解决和不能解决这问题之前徘徊,所以,索性我换了另一种框架。

其实后面解释的内容使用子命令的--help都能看到,比如python3 GetAllTitles.py new --help会显示如下结果:

Usage: GetAllTitles.py new [OPTIONS]
Options:
   --fname TEXT  The output file name for all content, default file name is allLists.txt.
   --help        Show this message and exit.

简单点,如果你执行python3 GetAllTitles.py new会怎样呢?理论上如果你无人值守的话,过一会你会发现在你的代码目录下有个一直在更新的allLists.txt文件,里面的内容都是这样的格式的:

期数:标题$url

为什么用$作为分隔符,一,这是一个对于美好事物的向往,二,更重要的是,最开始我是选用最常见的逗号,但是在实践的过程中发现,很多标题里面本身就带有逗号。导致后面的步骤分类格式化成为markdown文件出问题,所以,改成了一个很不常用的$富豪,哦不,符号。

其他两个子命令主要功能都一样,就不再赘述了。

ExtractMD.py

这个文件流程相当清晰:

  • 从爬取保存下来的文件中读取内容,找到标题
  • 从category.json中读取filter和rejecter,为什么有这两个玩意儿,下一节就可以说明
  • 按照类别格式化好字符串,存储成为markdown文件
  • 记录下未被分到任何一类的内容,自动保存在一个名叫uncategorized1.md的文件中,人工筛选其中的文章,并且根据筛选的结果,更新category.json文件,以求在一次次的洗礼中获得更加准确,合理的分类配置文件

使用python3 ./ExtractMD.py --help可以看到如下帮助信息:

Usage: ExtractMD.py [OPTIONS]
Options:
  --fname TEXT    The raw file name for crawling file,default is allList.txt.
  --filters TEXT  Input the filers that you need, seperate by ',', if no keywords, means use all filters by default.
  --help          Show this message and exit.

其中的filters是你想分类的文件的关键词,比如说“c++,java,大数据”等等,这些类名可以在下一节提到的category.json中查询。如果不传这个参数,标示按照category.json文件里面的类别尽量分类。

category.json

这个应该算这个repo的核心部件了,程序根据这个json文件里的标示来进行分类,特意节选一部分方便说明:

{
    "root":[
        {
            "keywords":"C++",
            "filters":["c++","c 语言"],
            "rejecters":[],
            "fileName":"CppLinks.md"
        },
        {
            "keywords":"Java",
            "filters":["java","jar","jvm","jdk"],
            "rejecters":["招聘","bjarne","javascript"],
            "fileName":"JavaLinks.md"
        }
    ]
}

主要的元素有四个,作用分别如下:

  • keywords:这一个类别的名字,暂时在代码中没有直接使用,主要是给人做一个标示
  • filters:只有包含这些个关键词的标题才能归为这一类
  • rejecters:如果标题中包含了这类关键词,一定不归属于这一类
  • fileName:最终形成的markdown文件的名字

这里面有值得解释的就是rejecters,有这个东西也是没有办法。以java举例,jar关键词是属于Java这一类的,但是偏偏大名鼎鼎的c++之父名字里面也有jar这个关键词,我又觉得精确匹配的话没那个必要,所以就使用了rejecter这么个玩意儿。

这里着重的提一句,这里的分类带有浓烈的个人喜好和自我经验的限制,非常欢迎各位对于这个分类提出补充。

对于这个json文件,我还有一些扩展的想法,统一在最后一节扯扯。

Erase404.py

这个就是去除不可达的url的内容,因为码农周刊从第一期开始算的话,已经有6年了,那是一个二维码支付都还刚刚开始普及的年代,很多估计是年久失修了或者作者心血来潮清除了自己的黑历史。

方法很简单,就是利用requests的库去获得每一条url的response code。但是正如我在该部分第一小节说过的一样,码农周刊的域名和requests库会发生证书报错的问题。怎么办?我选取了最简单的办法,如果url里面含有码农周刊的域名,也就是toutiao.io,我就默认这个是一个可以访问的网站。使用python3 ./Erase404.py --help可以看到如下内容:

Usage: Erase404.py [OPTIONS]
Options:
   --folder TEXT  The folder that contains markdown files to be processed, default is current folder.
   --help         Show this message and exit.

只需要一个参数,就是含有需要处理的markdown文件的folder名称,默认就是当前文件。处理好的文件会放在当前文件夹下的新建的一个叫做filtered的文件夹下。因为这个算IO密集型的操作,所以使用多线程大大提高了其速度。

MergeFiles.py

这个文件就及其简单了,合并两个文件夹下文件名相同的文件。目的是为了方便在更新的时候自动合并最新一期产生出来的新的markdown文件和已经分类好的现存markdown文件。使用python3 ./MergeFiles.py --help可以看到如下内容:

Usage: MergeFiles.py [OPTIONS]
Options:
  --src TEXT  Sorce folder that contains markdown files to be merged.
  --dst TEXT  Destination folder that contains existing,categorized markdown files.
  --help      Show this message and exit.

OmitDup.py

这个文件是后面加入的,原因是发现在前面形成的markdown文件中有时候会出现重复项,原因我猜应该是小编们在整理文章时很难记得在之前其实已经被选入过了。比如有一个文章在第16期被选中了,而后在36期又被选中了,其中差了20期。按照码农周刊的更新频率,这至少得5个月了,让一个人记得这么久的内容显然不现实。这个去重其实可以在最先做,但这是开挂的视角看待这个问题,因为我发现这个已经是有大量整理好的文件了。本着我自己前面说的要keep it simple,stupid的原则,我选择了再搞一个功能单一的文件。

用法很简单,使用python3 ./OmitDup.py --help可以看到如下内容:

Usage: OmitDup.py [OPTIONS]
Options:
  --folder TEXT  the folder name to omit duplications of markdowns.
  --help         Show this message and exit.

该程序会搜索folder路径下面所有md结尾的文件,然后对他们进行去重操作,当然,是多线程的。

如何把他们链接起来

这里我又要做一次树莓派的强力推广人员,上面的4个文件明显是可以自动化,只有最后的git push需要更多一点的关照。而这种默默采集数据加一些处理的工作利用树莓派再合适不过了,只需要利用脚本在上linux的cron程序,可以实现这些程序定时的跑起来,省时又省电。

【github repo自荐】码农周刊一周精选分类的更多相关文章

  1. 《码农周刊》干货精选(Python 篇)

    <码农周刊>已经累计发送了 38 期,我们将干货内容进行了精选.此为 Python 篇. <码农周刊>往期回顾:http://weekly.manong.io/issues/ ...

  2. 《码农周刊》干货精选--Python篇(转)

    原文:http://baoz.me/446252 码农周刊,本人有修改   Python标准库,第三方库 按功能进行了分类,之前有一Pythoner说there is a library for ev ...

  3. Python码农福音,GitHub增加Python语言安全漏洞告警

    在 2017 年 GitHub 开始对托管在其网站的代码仓库和依赖库开始提供安全漏洞检查和告警,开始时候只支持 Ruby 和 JavaScript 语言的项目.根据 GitHub 官方数据显示截止目前 ...

  4. GitHub for mobile 来了,码农苦逼了!

    北京时间 2019 年 11 月 14 日 GitHub Universe 2019 大会上,GitHub 正式发布了 GitHub for mobile,即 GitHub 的移动版本,支持 iOS ...

  5. 管理与技术未必不可兼得,一个20年IT老兵的码农生涯

    作者|康德胜 我是一个喜欢写代码但几乎不太有机会写代码的CTO,也是一个看得懂财务报表.通过所有CFA(金融特许分析师)考试并获得FRM(金融风险经理)认证的拿到金融MBA的CTO,如果我有幸被称作码 ...

  6. 【整理】待毕业.Net码农就业求职储备

    声明:本文题目来源于互联网,仅供即将从学校毕业的.Net码农(当然,我本人也是菜逼一个)学习之用.当然,学习了这些题目不一定会拿到offer,但是针对就业求职做些针对性的准备也是不错的.此外,除了技术 ...

  7. [2013 eoe移动开发者大会]靳岩:从码农到极客的升级之路

    (国内知名Android开发论坛 eoe开发者社区推荐:http://www.eoeandroid.com/) 前天,2013 eoe 移动开发者大会在国家会议中心召开,eoe 开发者社区创始人靳岩在 ...

  8. android码农神器 偷懒工具 android懒人框架 LoonAndroid 3 讲解

    LoonAndroid 3.0 Loonandroid是一个注解框架,不涉及任何UI效果,目的是一个功能一个方法,以方法为最小颗粒度对功能进行拆解.把功能傻瓜化,简单化,去掉重复性的代码,隐藏复杂的实 ...

  9. Android码农如何一个星期转为iOS码农(不忽悠)

    WeTest 导读 作为一个android客户端开发,如果你不懂点ios开发,怎么好意思说自己是客户端开发呢,本文讲解如何让android开发码农在一个星期上手IOS开发 --<记录自己IOS开 ...

随机推荐

  1. linux系统查看磁盘分区使用空间

    Df命令是linux系统以磁盘分区使用空间:df -hl

  2. POJ 1785 Binary Search Heap Construction(裸笛卡尔树的构造)

    笛卡尔树: 每个节点有2个关键字key.value.从key的角度看,这是一颗二叉搜索树,每个节点的左子树的key都比它小,右子树都比它大:从value的角度看,这是一个堆. 题意:以字符串为关键字k ...

  3. js模仿jquery里的几个方法parent, parentUntil, children

    有时工作需要, 也是接着上一章的方法, 用js模仿jquery里的几个方法parent, parentUntil, children. function parent(node){ return no ...

  4. Swift - 05 - 数值型字面量

    //: Playground - noun: a place where people can play import UIKit var str = "Hello, playground& ...

  5. 更改tabBarItem图片的问题

    代码: UIImage *normal = [[UIImage imageNamed:@"tabbar_home_default"] imageWithRenderingMode: ...

  6. VC++对象布局的奥秘:虚函数、多继承、虚拟继承

    哈哈,从M$ Visual C++ Team的Andy Rich那里又偷学到一招:VC8的隐含编译项/d1reportSingleClassLayout和/d1reportAllClassLayout ...

  7. Oracle 子程序参数模式,IN,OUT,IN OUT

    IN :用于传入参数. 在调用过程的时候,实参传到该过程中. 在过程内部,形参只读且不能更改. 在过程执行完毕,返回调用环境时候,实参到的值也不会改变 --带IN参数的过程,赋值. create or ...

  8. 《Flask Web开发》学习笔记

    第一部分 Flask简介 前言:想熟练掌握一门web框架,为以后即将诞生的测试工具集做准备.为什么选择flask要做熟练掌握的一门框架,而不是其他的,最主要的原因是可以随意定制. 特别提醒:这本书的代 ...

  9. Linux 下装逼技巧

    ``` 1.下载cmatrix-1.2a.tar.gz文件 [root@localhost ~]# wget https://jaist.dl.sourceforge.net/project/cmat ...

  10. VS2017离线安装与Oracle数据库开发环境搭建

    记得之前使用VS2015打开老的MVC4项目,不能右键创建控制器和添加视图,让我非常不习惯!找遍了网络无果,最后只能回到VS2013,但我就是不喜欢用旧的VS,这是不是病... 1.将VS2017离线 ...