如何用 Python 制作 GitHub 消息助手


Posted in Python onFebruary 20, 2021

在互联网2.0时代,工程师解决业务问题主要依赖的是自己掌握的各种工具和软件伴随着席卷全球的开源浪潮,开源工具和软件也迅猛增长。工程师需要关注的技术和软件也随之越来越多,学习负担越来越大,大脑也越来越不够用。但工程师们也很无奈,因为谁掌握的技术和软件越多,谁就能更高效的解决问题。于是工程师们开始借助互联网外脑工具:尤其是搜索引擎、书签、github、scihub等 而工程师们解决问题的能力就体现在了对外脑工具的利用上。
但是,随着工程师们要解决的问题增长以及自身知识的积累,外脑工具也逐渐变得臃肿:书签越来越多,github的订阅越来越多,多到最后就约等于没有书签、没有订阅了。为了解决这些问题,我们需要更智能灵活的外脑工具,能让我们从信息的海洋中解放出来,让我们能更加专注自身业务。

GitHub 消息的问题

如何用 Python 制作 GitHub 消息助手

有没有发现你的 Github 消息 Inbox 过几天不处理,就会堆积成山呢?相信有的同学 Inbox 里的数字比这个还要夸张,甚至有的同学已经绝望的放弃了 Inbox 这个功能。
为什么会这样?
因为每个Coder内心大多都会喜欢收藏喜爱的作品,而github的项目主页右上角最醒目的位置总是摆着这三个按钮:

如何用 Python 制作 GitHub 消息助手

相信工程师们看到喜爱的项目,就会毫不犹豫的一键三连:watch、start、fork。
悲剧也就从这里开始了。
1、工程师喜欢的项目越来越多;
2、项目会有自己的生命周期,有的变得活跃,有的逐渐消亡;
3、工程师越来越忙,无暇顾及Inbox。
然后,Inbox就变这样了:

如何用 Python 制作 GitHub 消息助手

看着满是堆积的消息,是不是有种崩溃的感觉。那github的功能到底出了什么问题?
我认为是 watch、star、fork 需要工程师投入的关注程度搞错了。当然现在github也在积极改进,相比以前,我们可以发现有了更多的 watch 选项:

如何用 Python 制作 GitHub 消息助手

但是仅仅这些就够了吗?看着 Inbox 动辄上万条的消息,难道要将自己关注的项目一个个的修改为 Ignore?
工程师的内心依然是崩溃的!
有没有办法拯救工程师的Inbox?
有!来吧,自己动手拯救我的收件箱。

解决方案

用 python 做一个 GitHub 消息助手,自动帮工程师关闭和删除不必要的消息。这不也就是真正意义上的Watch吗?你看它的时候,会接收它的信息,你不看了它就消失了。那么仔细想想,到底哪些消息真正对工程师有用呢?
1、已经很久没更新的项目,是不是就可以不关注了?
2、已经不是工作范围和兴趣点的项目,是不是也可以不关注了?
3、已经很久都没人反馈问题的项目,是不是也可以不关注了?
而python有一个优势就是可以很方便的实现用户操作的自动化 嗯,看起来这些僵尸项目都可以用python自动化的方式清除掉 说干就干,让我们开始吧!

代码实现

我们知道Python有一款很棒的Web自动化测试框架:Selenium,但 Selenium 主要还是用于测试,调用还是略显复杂。所以笔者在github上搜刮了一番,终于找到一款合适的Python包:PyChrome 项目地址:
https://github.com/siversalih/pyChrome-Web-Automation
下面我们就用这款非主流的自动化工具包,完成我们的小助手 看主页,这个作者很懒,几年前就没有更新了,但幸好说明帮助还是挺全的:
https://pychrome.wordpress.com/usage/
所以我们就可以 happy 的按照说明书来组装机器人了。

0.环境准备

首先需要准备Python 3.8环境,然后按照网上说明安装 Selenium,接下来将PyChrome项目 clone到本地。ok,环境准备完成。

1、模拟登录github

使用PyChrome访问github有个小麻烦,每次都会启动一个全新的Chrome浏览器实例。这就导致无法重复利用保存在本地的cookie信息,所以每次要模拟登陆下。github有一个特点,如果ip变更,需要输入验证码,如果ip不变则不需要,所以第一次我们只能先手工输入一次。

如何用 Python 制作 GitHub 消息助手

不过github的登录页面相对简单,只需要找到Username和password对应的表单组件就可以了。所以登录的代码可以非常简洁,如下所示:

browser.open("https://github.com/login")
# name="login"
name_locator = "//*[@name='login']"
el_name = browser.findElementByXPath(name_locator) 
browser.sendTextToElement(username, el_name) 
# name="password"
pass_locator = "//*[@name='password']"
el_pass = browser.findElementByXPath(pass_locator) 
browser.sendTextToElement(password,el_pass) 
login_locator = "//*[@name='commit']"
el_login = browser.findElementByXPath(login_locator) 
browser.clickElement(el_login)

2.模拟进入Inbox

登录完成后,我们需要进入收件箱,查看到底有哪些未读消息。收件箱有点小复杂,不过也还能很方便的区分。

如何用 Python 制作 GitHub 消息助手

找到了正确的xpath,相信定位也不是难事。这里我又取了个巧,我们被困扰的其实是有消息的项目,如果一个项目不发消息,我们其实也不会被骚扰到。所以直接选取左下角的 Repositories 区域似乎效率更高一些。
代码如下:

browser.open("https://github.com/notifications")
# 获取有消息的Repositories列表
locator = "js-notification-sidebar-repositories"
el_repos = browser.findElementByClass(locator) 
repos_list = browser.findElementsByTag("li", el_repos)

3.检查僵尸项目

我选用第三条策略,已经很久没人反馈问题的项目作为判断僵尸项目的标准(纯粹只是因为方便实现),首先访问issue,然后判断issue里的更新日期,恰好有一个详细的日期字段。下面代码目的很简单,就是获取最后一条issue更新了多久。

    browser.newTab("https://github.com/" + repos_name + "/pulls?q=")
    # 判断最近的 pull request
    locator = "//div[@aria-label='Issues']"
    el_pulls = browser.findElementByXPath(locator) 
    pull_list = browser.findElementsByTag("relative-time", el_pulls)
    timedelta = 0
    if type(pull_list)==list and len(pull_list)>0:
        # 2020-11-10T00:55:39Z
        # last_pull_time_str = pull_list[0].getAttribute("datetime")
        last_pull_time_str = pull_list[0].get_attribute("datetime")
        last_time = datetime.strptime(last_pull_time_str, "%Y-%m-%dT%H:%M:%SZ")
        timedelta = (datetime.now() - last_time).days 
    logger.debug(repos_name + " timedelta: " + str(timedelta) + " days")

4.取消关注僵尸项目

如果issue已经超过了1年,自然就应该取消关注了,毕竟目前信息更新的速度太快了。

# 取消不活跃项目的订阅(1年以上没有pull request)
if unsubscribe and timedelta > 366:
    el_notify_button =browser.findElementsByTag("notifications-list-subscription-form")
    browser.clickElement(el_notify_button) 
    time.sleep(1)
    # data-target="notifications-list-subscription-form.menu"
    locator = "//*[@data-target='notifications-list-subscription-form.menu']"
    el_notify_menus = browser.findElementByXPath(locator) 
    # value="ignore"
    sub_locator = "//*[@value='ignore']"
    el_ignore_button =browser.findElementByXPath(sub_locator, el_notify_menus) 
    browser.clickElement(el_ignore_button) 
    logger.debug(repos_name + " cancel subscribed")

5.删除僵尸项目消息

最后,该是解除困扰的时候了,这种不再更新的项目,工程师自然也不要再被它的消息骚扰。

    el_repos_link = browser.findElementByTag("a", repos)
    browser.clickElement(el_repos_link) 
    # mr-1 js-notifications-mark-all-prompt
    time.sleep(1)
    el_sel_all =browser.findElementByClass("js-notifications-mark-all-prompt")
    browser.clickElement(el_sel_all) 
    time.sleep(1)
    # title="Done"
    done_locator = "//*[@title='Done']"
    el_done = browser.findElementByXPath(done_locator) 
    browser.clickElement(el_done) 
    logger.debug(repos_name + " remove notifiy")

以上代码就是模拟 Done 按钮的操作:

如何用 Python 制作 GitHub 消息助手

到这里就完成了GitHub消息助手的全部逻辑,整个Inbox终于清静了,是不是可以喝杯咖啡惬意一下了。

如何用 Python 制作 GitHub 消息助手

后记

Python自动化工具的确是给工程师们带来了便捷,使得工程师能应对各种日常不同的挑战。为方便各位工程师小伙伴们早日解脱、得偿所愿,以上代码已开源,完整的代码地址:
https://gitee.com/knifecms/puppetry/blob/master/github-agent/resp_notify.py
另外,该项目下,还有几个其他有意思的自动化助手和工具哟,大家感兴趣的话也可以研究研究。
希望得到你的更多好点子!

以上就是如何用 Python 制作 GitHub 消息助手的详细内容,更多关于Python 制作 GitHub 消息助手的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python时间整形转标准格式的示例分享
Feb 14 Python
使用wxpython实现的一个简单图片浏览器实例
Jul 10 Python
python实现的重启关机程序实例
Aug 21 Python
Python中unittest用法实例
Sep 25 Python
使用Python保存网页上的图片或者保存页面为截图
Mar 05 Python
python正则中最短匹配实现代码
Jan 16 Python
Python生成器generator用法示例
Aug 10 Python
python如何以表格形式打印输出的方法示例
Jun 21 Python
Python 获取项目根路径的代码
Sep 27 Python
python多继承(钻石继承)问题和解决方法简单示例
Oct 21 Python
Python抓包程序mitmproxy安装和使用过程图解
Mar 02 Python
python实现程序重启和系统重启方式
Apr 16 Python
详解tf.device()指定tensorflow运行的GPU或CPU设备实现
Feb 20 #Python
Python 的 f-string 可以连接字符串与数字的原因解析
Feb 20 #Python
安装不同版本的tensorflow与models方法实现
Feb 20 #Python
python爬虫scrapy基本使用超详细教程
Feb 20 #Python
解决pip安装tensorflow中出现的no module named tensorflow.python 问题方法
Feb 20 #Python
conda安装tensorflow和conda常用命令小结
Feb 20 #Python
TensorFlow低版本代码自动升级为1.0版本
Feb 20 #Python
You might like
php mysql Errcode: 28 终极解决方法
2009/07/01 PHP
php实现按文件名搜索文件的远程文件查找器
2014/05/10 PHP
几行代码轻松实现PHP文件打包下载zip
2017/03/01 PHP
laravel5.6中的外键约束示例
2019/10/23 PHP
JQuery中的ready函数冲突的解决方法
2010/05/17 Javascript
javascript hashtable 修正版 下载
2010/12/30 Javascript
有趣的JavaScript数组长度问题代码说明
2011/01/20 Javascript
基于jQuery中对数组进行操作的方法
2013/04/16 Javascript
Jquery多选框互相内容交换的实例代码
2013/07/04 Javascript
jquery 跳到顶部和底部动画2句代码简单实现
2013/07/18 Javascript
JavaScript字符串对象fromCharCode方法入门实例(用于把Unicode值转换为字符串)
2014/10/17 Javascript
在父页面得到zTree已选中的节点的方法
2015/02/12 Javascript
javascript插件开发的一些感想和心得
2016/02/28 Javascript
JS HTML5拖拽上传图片预览
2016/07/18 Javascript
Angular和百度地图的结合实例代码
2016/10/19 Javascript
jquery插件bootstrapValidator表单验证详解
2016/12/15 Javascript
javascript 中的try catch应用总结
2017/04/01 Javascript
angular1.x ui-route传参的三种写法小结
2018/08/31 Javascript
写一个Vue Popup组件
2019/02/25 Javascript
node.js实现上传文件功能
2019/07/15 Javascript
layui表格分页 记录勾选的实例
2019/09/02 Javascript
JS typeof fn === 'function' && fn()详解
2020/08/22 Javascript
微信小程序canvas动态时钟
2020/10/22 Javascript
[55:25]2018DOTA2亚洲邀请赛3月29日 小组赛A组 VG VS OG
2018/03/30 DOTA
Python中的pprint折腾记
2015/01/21 Python
详解python的webrtc库实现语音端点检测
2017/05/31 Python
Python基于高斯消元法计算线性方程组示例
2018/01/17 Python
python使用opencv实现马赛克效果示例
2019/09/28 Python
python编写一个会算账的脚本的示例代码
2020/06/02 Python
Python3 pyecharts生成Html文件柱状图及折线图代码实例
2020/09/29 Python
mac系统下安装pycharm、永久激活、中文汉化详细教程
2020/11/24 Python
Spartoo瑞典:鞋子、包包和衣服
2018/09/15 全球购物
质量保证书
2015/01/17 职场文书
综合测评个人总结
2015/03/03 职场文书
python not运算符的实例用法
2021/06/30 Python
Mysql数据库group by原理详解
2022/07/07 MySQL