GitHub使用历程、丁香园爬虫、数据提取API及数据仓库搭建小结
由于今年的新型冠状病毒影响,学校延期开学,原本要在一月底结束的假期硬生生延长到了二月中旬,甚至还有可能继续延期。在家宅着闲来无事,第一次认真地维护了一个开源项目。
GitHub使用历程
从接触计算机到现在一年有余,一直很频繁地在使用GitHub,共有55个项目,其中开源项目18个,未开源项目37个。未开源的项目大部分都是成品,但大部分商业用途,所以无法让大家来对代码做审核和检验。
开源项目扣除fork来做pull request的项目和作业,恐怕只有BlankerL/Market-Report-Generator一个项目可以说是我自己完成的开源作品了。但这一个项目是我接触计算机和Python的第一个开源项目,在实习的过程中随便做的一个软件,实习结束之后也并没有继续维护了。现在来看,这些代码完全没法入眼,冗杂并且可视化效果也并不是很理想。近期也有重写这个项目,把它做成前端的打算。
直到这个假期,在GitHub上发布的BlankerL/DXY-COVID-19-Crawler和BlankerL/DXY-COVID-19-Data正好搭上了疫情的顺风车,受到了很多人的关注。截止2020年2月12日晚10:40,两个项目分别有 850/561 Star, 169/137 Fork,远远超出了我的想象。
项目初衷和历程
我自己本身是跨学科转计算机的,所以对数据的要求远高于对编程的要求,也才有了这一个爬虫和数据收集、共享的项目。
由于自己并不是医学背景,没有办法对疫情控制做一些什么力所能及的贡献。1月22日凌晨,某一个交流群里的群友们希望做一个疫情数据可视化,由于当时丁香园的可视化是静态图像,而他们希望能够通ECharts来实现动态的可视化界面,我就自告奋勇地决定来实现爬虫和后端的功能。这本身也是一个十分基础的小项目,一共只花了3个小时就完成了爬虫和后端的第一次开发。
随后,这个项目中的大部分人或许因为春运等种种原因退出,也只有几个人的小项目存活了下来。可能很多人都有数据的需求吧,所以最后我的这个从来没有宣传过的项目逐渐被越来越多人知道。先是群内的几个人小范围使用,我也把后端架设在Azure香港的免费云服务器上,每个月15GB的流量瞬间就见底开始扣费😓后来V2EX上有人发帖提到了我的后端,也有越来越多人开始关注这个项目,我又先后迁移了2次数据库和2次服务器,直到目前用了1000GB流量+10Mbps带宽的阿里云服务器,才比较好地维持项目持续运转。
正好,丁香园目前忙于数据的收集和动态的更新,暂时没有数据定制和公开的打算,所以我也希望通过对实时数据的收集和分享,来帮助其他人更好地研究疫情,也借此机会学一点新的东西。这个项目也就这样,一路维护到了现在。
丁香园爬虫
丁香园的这个爬虫本身十分简单,第一个版本大约用了2个小时就完成了。包括一个爬虫脚本和一个数据库脚本,爬虫将获取到的数据做初步的处理,并储存到数据库中,逻辑十分简单。
说是叫爬虫,其实一共只完成了一次请求,丁香园应该是有意为之,至今没有任何反爬虫措施,爬虫到现在都运转良好。虽然我对爬虫和所有反爬虫的绕开方式都挺有信心,但如果有反爬机制,可能开发的耗时会严重延长,而且一旦有反爬虫,我也不太敢做数据共享了。
对于大部分的数据我都选择直接保留而并没有做数据清理,一方面是实时数据流无法回溯,一次错过就再也无法取得,另一方面是数据更新频率比较低,就算全盘保存也并不会占用太多的硬盘。
我并没有深入接触过其他数据库,一开始莫名其妙地用上了MongoDB之后,不论什么数据都是往MongoDB里硬塞。通过PyMongo可以很方便地实现MongoDB和Python的交互。不用建表的数据库用起来十分简单,开一个Database之后,甚至不用开Collection就可以直接往里面存放数据。
爬虫和数据库做好之后,就可以开始正常获取数据并存放到数据库中了。
数据提取API
为了能够让用户直接通过API获取数据,必然还需要开发一套简单的API来联通数据库和用户。
Flask版本
由于我只接触过Django和Flask,而Django完全没有完整的开发经验,所以只能通过Flask来做后端的开发。正巧,我有一个荒废已久的Flask后端,决定直接基于这个后端加一个Blueprint直接实现了API接口。
Flask的优势在于开发十分简单,除去说明文档的撰写,整个开发过程在1小时左右。当时丁香园的数据并不像现在这样格式清晰、规范,它们经常改变变量的命名,所以后端的文档和返回数据的格式也经常发生改变。
FastAPI版本
受限于服务器性能问题,同时只有4个并行的Flask进程。然而,Flask的异步性能十分有限,当数据返回体积较大,而数据传输速度较慢的情况下,很容易导致进程占有而无法响应连接,当时每隔一段时间就需要重启Flask进程保证项目稳定。
受限于上述两个原因,最后我将后端切换为FastAPI。个人来看,FastAPI或许是目前基于Python能够使用的同时兼顾轻量、高性能且开发友好的API框架。
抛开广为讨论的优越异步性不谈,它还有以下几个特点:
- 自动生成的Swagger UI和ReDoc文档。直接在接口中写清变量含义,就能够自动生成文档。
- 接口返回数据通过BaseModel可以很清晰地直接展示。
- Swagger UI下可以直接对接口进行测试。
未来如果我要使用Python作为后端来实现类似的API,应该还会继续使用FastAPI。
数据仓库
项目架设之后,几乎每天都会有十数封邮件与我联系,大部分是科研人员,希望能够获取数据,但是苦于对API和数据处理并不在行,希望我能够提供更易于操作的数据。
一开始,我直接按csv格式导出数据库并且发送给他们,但丁香园后期添加的Area数据将字典存放在列表当中,导出csv后数据仍然需要一定的编程基础才能清理。因此,我又开了一个数据仓库,写了一个脚本来完成基础的数据提取和定时的数据推送工作,让大家可以直接下载csv数据,相当于一站式科研服务了😓
其他
随着GitHub上大家要求的增加,我也添加了一些新的功能:
- 请求变量来定制返回数据的格式,添加一些请求变量,并且在后端通过PyMongo的aggregate方法,通过pipeline来实现数据的筛选和排序;
- 使用Certbot自动部署Let’s Encrypt证书证书并且实现HTTPS协议,方便跨域请求。
总结
总结起来,其实这些小工具的开发都并没有什么困难的。整个流程很明确,大部分的新增功能也都是用户直接提出的,实现起来也并不困难。
恐怕,最困难的是新建这个项目、写下第一行代码,以及未来坚持项目的维护吧。
开发过程中留下了很多宝贵的经验,包括第一次把Flask用于生产环境、第一次对uWSGI的设置和部署,以及在后端的开发中对一些算法和功能的实现方法有了更深入的了解,都是可以另开一篇来详细记录的。
等我摸清楚了这些内容,并且没有其他人写过这些内容的话,我会找机会再聊聊的。
不知不觉就快到了13号了,也提前几分钟祝自己生日快乐吧😊