Giter Site home page Giter Site logo

grank's People

Contributors

bestony avatar c4pt0r avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar luuming avatar wxy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grank's Issues

安装之后输入 grank 出错

输入 grank login 之后报错
Traceback (most recent call last):
File "/home/mj/grank_work/bin/grank", line 7, in
from grank.core import main
File "/home/mj/grank_work/lib/python3.6/site-packages/grank/core.py", line 12, in
from .libs import helpers
File "/home/mj/grank_work/lib/python3.6/site-packages/grank/libs/helpers.py", line 12, in
import matplotlib.pyplot as plt
File "/home/mj/grank_work/lib/python3.6/site-packages/matplotlib/pyplot.py", line 2374, in
switch_backend(rcParams["backend"])
File "/home/mj/grank_work/lib/python3.6/site-packages/matplotlib/pyplot.py", line 207, in switch_backend
backend_mod = importlib.import_module(backend_name)
File "/home/mj/grank_work/lib/python3.6/importlib/init.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "/home/mj/grank_work/lib/python3.6/site-packages/matplotlib/backends/backend_tkagg.py", line 1, in
from . import _backend_tk
File "/home/mj/grank_work/lib/python3.6/site-packages/matplotlib/backends/_backend_tk.py", line 5, in
import tkinter as Tk
ModuleNotFoundError: No module named 'tkinter'

复现

  1. pip install grank
  2. grank login
    报错
    image

之后再安装 tkinter 报错找不到,是我的操作有误?

系统

  • OS: [Ubuntu 18]

建议增加指定统计的分支的功能

如题, 以 [https://github.com/NetBSD/src](https://github.com/NetBSD/src) 为例, 社区活跃度较高,但是用的不是master管理,所以 grank analy分析出的活跃度才0.03~~~

数据采集范围前端

需要编写一个前端程序(不指 web 界面),用于从特定的数据源抽取要进行数据分析的 github 项目。

目前考虑的数据源有:

该程序需要从此自动获取 organ ,并采用 organ 命令进行抓取。
考虑到项目分类各异和数据参差,应该需要前置工作 #6 的项目分类,并对筛选 star 数超过 100 项目。

重复项目数据的覆盖

当重复分析同一个项目(组织/仓库)时,后来的数据应该覆盖前一个数据。

此外,判断重复的主键是: 组织/仓库 ,或者 组织。

JSON 配置文件读取模式的支持

应该建立一个数据配置数据库(文本或 json):

  • 以组织(用户)或仓库名为主键,
    • 指定仓库时,包括其组织(用户),格式为“组织/仓库名”
    • 其下级数据指定对该数据的配置:
      • 非社区化匹配规则:以正则表达式方式来匹配贡献者的邮件域,配置则为企业人员
      • 对于组织/用户,会遍历其名下的所有仓库,可指定筛选条件,可支持:
        • star:最小 star 数要求
        • last_commit:最后提交的时间
        • first_commit:首次提交的时间(即仓库创建时间)
        • 等等
      • 强制分类:默认仓库会根据其首选语言分为文档类、前端类和代码类项目,但是可以在此强制指定。
      • 数据采集范围:如没有指定,采用系统配置数据
        • start: 采集开始时间
        • end: 采集结束时间(如系统也未指定,则为当前时间)
      • 忽略:用于在指定组织(用户)是,列出需要忽略的仓库

调试参数的添加

为命令添加 --debug 参数,从而在后续的输出中,输出各种调试信息。

公共域邮箱添加

在次提交需要加入公共域过滤的邮件域地址

比如

  1. @yahoo.co.uk
  2. @googlemail.com
  3. @hotmail.com
  4. @yandex.ru

关于如何判断一个用户是社区开发者还是企业开发者

由于项目中包含了社区化分析,需要分析出不同项目的社区开发者和企业开发者的比重。

当前的方案是读取每一个 commit 的贡献者邮箱,并通过正则表达式拆分出邮件域

通过判断邮件域内是否包含特定关键词来判断是否是企业开发者。同时一个项目只能设置一个关键词,这样如果有百度的员工贡献了腾讯的项目,这个员工的贡献依然标记为社区开发者贡献。

不知是否有更好的方案,欢迎一同讨论。

go 版本的实现

相比于 Python ,golang 可以更加方便的实现跨平台二进制的分发。相比之下会更适合做成 cli 。不过要评估 Go 是否有对应的依赖

  1. pandas 类似的数据分析库
  2. matplotlib 类似的方便的绘图库。如果无法方便的绘图,实现一个 go 版本的不划算。

社区化分析参数的预处理

需求:对于特定的项目,不清楚邮件域是什么,可能需要提供一个列表进行辅助。

详细描述:

在进行社区化分析前,进行数据的预处理,提取出所有的邮件域,根据出现频次进行排序,展示列表给用户,由用户输入标记为企业的邮件域。

加入预处理前的顺序

  1. 抓取数据
  2. 活跃度分析
  3. 社区化分析

加入预处理后的顺序

  1. 抓取数据
  2. 活跃度分析
  3. 数据预处理
  4. 社区化分析

此处预处理也可以提前到2 ,不过建议放在3 。后续可能可以设置分析类目。

补充信息

  1. 展示 Top 10 的邮件域
  2. 默认排除掉公共邮件域,比如 gmail.com qq.com 163.com 等公共邮件域(此参数应当内置,同时允许用户指定,第一批可以考虑不实现,后续迭代实现。)
  3. 在交互中,输出 Top 10 的列表,然后展示 1~10 ,用英文逗号或空格隔开。
  4. 用户输入的获取可以参考:http://click.palletsprojects.com/en/7.x/prompts/

query 疑似有误

  1. 在 crawler.py 的 fetch_user_data 函数中
    next_query = query.organ_all_query_with_pager % ( organization, helpers.get_page_cursor(result, "user_repository"))
    疑似应为
    next_query = query.user_all_query_with_pager % ( user, helpers.get_page_cursor(result, 'user_repository'))

  2. 在 helpers.py 的 get_page_cursor 函数中
    if mode == "user_repository": return result["data"]["organization"]["repositories"]["pageInfo"]["endCursor"]
    疑似应为
    return result["data"]["user"]["repositories"]["pageInfo"]["endCursor"]

  3. 此外,当用户 repository 过多时(例如 cloudwu),抓取到的数据呈现
    {'data': {'organization': None}, 'errors': [{'message': "Could not resolve to an Organization with the login of 'cloudwu'.", 'type': 'NOT_FOUND', 'path': ['organization'], 'locations': [{'line': 3, 'column': 3}]}]}
    因此访问 'user' key 会出错。

根据项目主体代码进行分类

根据项目主体代码,将所分析的项目分成几类:

  • 文档类项目,以 markdown、html 为主体的项目
  • 前端类项目,以 javascript、css(及预处理器) 为主体的项目
  • 开发类项目,以其它源代码为主体的项目

以上三类项目的开发和活跃度模式相差比较大,应该分别进行排行。

python 标准模块的实现

目前的实现是基于 cli 的,因此需要一个可引用模块的实现。

import grank 
result = grank.repo(owner=xxx,repo=xxxx)

此部分完成后可以后续实现 #10 ;
此部分的实现可以参考 #20

第一版本建议 result 返回一个分数。后续可以评估一下返回数组的成本。如果实现简单且不容易出问题,可以考虑将 具体的数据返回前端,从而实现前端的绘图。

命令行模式的支持

「命令行模式的支持」

即所有参数均由命令行来提供,如

grank --token=xxx repo lctt grank --start=2018-08-01 --stop=2018-09-01

实现方法

  1. 参考 http://click.palletsprojects.com/en/7.x/options/ 的文档,加入 option ,加入位置大致在

    Grank/grank/core.py

    Lines 16 to 19 in 7259124

    @click.group()
    def main():
    """Grank Command"""
    pass
    (未测试)

  2. 检测到 Option 后,手动生成一个 config 实例,不再通过文件读取。可能涉及到 context 的传递,参考 http://click.palletsprojects.com/en/7.x/commands/#nested-handling-and-contexts

拆分 Script 目录下的脚本

目前 script 目录下仅有 activity.py 一个文件

应当拆分数据抓取、分析、以及入口,降低维护难度。在完成本 issue 前,需要完成 #4

  1. crawler.py 负责抓取数据,并放入 output 中特定目录
  2. activity.py 负责分析活跃度,并生成活跃度图片和报表
  3. social.py 负责分析社区化,并生成社区化图片和报表
  4. endpoint.py 负责整合上述三个命令,对外提供服务(也可以由 core.py 负责整合减少封装带来的维护成本)

grank 项目的可能出现误差的点

可能导致误差的点

1. 丢弃项目中未设定时间的 commit / pr

在使用 GraphQL 抓取数据时,发现了部分 commit / pr 是未标注时间的,未确保这些 dirty data 不影响项目的分析,丢弃了这部分数据。但是同样可能导致数据分析的结果不够精确。

相关代码位置:

commit_frame = commit_frame[commit_frame.date != "未标注时间"]

2. 邮箱不精确

在使用 GraphQL 抓取数据时,发现部分 commit/pr 的email 为 github 域下的,考虑到无法对 Github 域下的项目分析其所属的企业和个人,将此部分数据丢弃。以确保社区化分析的准确性。

Grank/grank/libs/helpers.py

Lines 229 to 234 in 7b00abb

def is_corp(email,config):
"""判断是否是企业用户"""
if config["corp"]["keyword"] in email:
return True
else:
return False

GraphQL 无法根据时间抓取特定时间点的项目

目前项目使用 GraphQL 来进行数据抓取,但 GraphQL 的数据分页参数 after 接受的是一个特定的指针,而非特定的时间,因此无法直接对特定时间的数据进行抓取,从而只抓取特定时间端内的 commit 数据。

目前的数据抓取是通过抓取一个项目所有的数据并在后续的分析时进行时间隔离的。

可能导致的问题

  1. 对于 commit /pr 特别多的项目,可能无法在一次请求中抓取到所有的数据。目前脚本暂无断点续抓的代码

GitLab Support

提供对 Gitlab 的支持。

可以考虑设置一个全局的 options --gitlab

此外,需要支持 gitlab-ce 和 gitlab-ee 以及 gitlab.com

社区化关键字的设置

这个关键字目前是设置在 ini 中,应该是根据命令行参数指定的组织或项目名来指定。

grank analy owner 命令出现的错误

1.在使用 grank analy owner 时,出现FileNotFoundError: [Errno 2] No such file or directory: 'output/activity/owner,找不到文件夹。
测试:
grank analy bestony

Traceback (most recent call last):
  File "/home/luming/miniconda3/envs/grank/bin/grank", line 11, in <module>
    load_entry_point('Grank==0.1.4', 'console_scripts', 'grank')()
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/Grank-0.1.4-py3.7.egg/grank/core.py", line 88, in analy
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/Grank-0.1.4-py3.7.egg/grank/libs/helpers.py", line 263, in comsum_owner
FileNotFoundError: [Errno 2] No such file or directory: 'output/activity/bestony'
  1. 在抓取某些用户时,会报KeyError: 'score'
    测试:
    grank analy luuming
Traceback (most recent call last):
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 3078, in get_loc
    return self._engine.get_loc(key)
  File "pandas/_libs/index.pyx", line 140, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/index.pyx", line 162, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/hashtable_class_helper.pxi", line 1492, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas/_libs/hashtable_class_helper.pxi", line 1500, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 'score'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/internals.py", line 4243, in set
    loc = self.items.get_loc(item)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 3080, in get_loc
    return self._engine.get_loc(self._maybe_cast_indexer(key))
  File "pandas/_libs/index.pyx", line 140, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/index.pyx", line 162, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/hashtable_class_helper.pxi", line 1492, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas/_libs/hashtable_class_helper.pxi", line 1500, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 'score'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/luming/miniconda3/envs/grank/bin/grank", line 11, in <module>
    load_entry_point('Grank==0.1.4', 'console_scripts', 'grank')()
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/Grank-0.1.4-py3.7.egg/grank/core.py", line 88, in analy
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/Grank-0.1.4-py3.7.egg/grank/libs/helpers.py", line 269, in comsum_owner
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/frame.py", line 3119, in __setitem__
    self._set_item(key, value)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/frame.py", line 3195, in _set_item
    NDFrame._set_item(self, key, value)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/generic.py", line 2600, in _set_item
    self._data.set(key, value)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/internals.py", line 4246, in set
    self.insert(len(self.items), item, value)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/internals.py", line 4347, in insert
    placement=slice(loc, loc + 1))
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/internals.py", line 3205, in make_block
    return klass(values, ndim=ndim, placement=placement)
  File "/home/luming/miniconda3/envs/grank/lib/python3.7/site-packages/pandas/core/internals.py", line 125, in __init__
    '{mgr}'.format(val=len(self.values), mgr=len(self.mgr_locs)))
ValueError: Wrong number of items passed 0, placement implies 1

其中,抓取到的 DataFrame 为

Empty DataFrame
Columns: []
Index: [2017-01-01 00:00:00, 2017-01-08 00:00:00, 2017-01-15 00:00:00, 2017-01-22 00:00:00, 2017-01-29 00:00:00, 2017-02-05 00:00:00, 2017-02-12 00:00:00, 2017-02-19 00:00:00, 2017-02-26 00:00:00, 2017-03-05 00:00:00, 2017-03-12 00:00:00, 2017-03-19 00:00:00, 2017-03-26 00:00:00, 2017-04-02 00:00:00, 2017-04-09 00:00:00, 2017-04-16 00:00:00, 2017-04-23 00:00:00, 2017-04-30 00:00:00, 2017-05-07 00:00:00, 2017-05-14 00:00:00, 2017-05-21 00:00:00, 2017-05-28 00:00:00, 2017-06-04 00:00:00, 2017-06-11 00:00:00, 2017-06-18 00:00:00, 2017-06-25 00:00:00, 2017-07-02 00:00:00, 2017-07-09 00:00:00, 2017-07-16 00:00:00, 2017-07-23 00:00:00, 2017-07-30 00:00:00, 2017-08-06 00:00:00, 2017-08-13 00:00:00, 2017-08-20 00:00:00, 2017-08-27 00:00:00, 2017-09-03 00:00:00, 2017-09-10 00:00:00, 2017-09-17 00:00:00, 2017-09-24 00:00:00, 2017-10-01 00:00:00, 2017-10-08 00:00:00, 2017-10-15 00:00:00, 2017-10-22 00:00:00, 2017-10-29 00:00:00, 2017-11-05 00:00:00, 2017-11-12 00:00:00, 2017-11-19 00:00:00, 2017-11-26 00:00:00, 2017-12-03 00:00:00, 2017-12-10 00:00:00, 2017-12-17 00:00:00, 2017-12-24 00:00:00, 2017-12-31 00:00:00, 2018-01-07 00:00:00, 2018-01-14 00:00:00, 2018-01-21 00:00:00, 2018-01-28 00:00:00, 2018-02-04 00:00:00, 2018-02-11 00:00:00, 2018-02-18 00:00:00, 2018-02-25 00:00:00, 2018-03-04 00:00:00, 2018-03-11 00:00:00, 2018-03-18 00:00:00, 2018-03-25 00:00:00, 2018-04-01 00:00:00, 2018-04-08 00:00:00, 2018-04-15 00:00:00, 2018-04-22 00:00:00, 2018-04-29 00:00:00, 2018-05-06 00:00:00, 2018-05-13 00:00:00, 2018-05-20 00:00:00, 2018-05-27 00:00:00, 2018-06-03 00:00:00, 2018-06-10 00:00:00, 2018-06-17 00:00:00, 2018-06-24 00:00:00, 2018-07-01 00:00:00, 2018-07-08 00:00:00, 2018-07-15 00:00:00, 2018-07-22 00:00:00, 2018-07-29 00:00:00, 2018-08-05 00:00:00, 2018-08-12 00:00:00, 2018-08-19 00:00:00, 2018-08-26 00:00:00, 2018-09-02 00:00:00, 2018-09-09 00:00:00, 2018-09-16 00:00:00, 2018-09-23 00:00:00, 2018-09-30 00:00:00, 2018-10-07 00:00:00]

[93 rows x 0 columns]

企业数据聚合

根据仓库所属的上级组织(“用户”或“组织”),可以对该上级组织的各项指标进行计算,这个计算不应该是简单的平均或加权平均,而应该是根据仓库的各项指标,在同一个时间段内,统一计算而成(即不以项目为分组单位,而是统一在上级组织的层面进行增幅计算、速率计算等)。

此外,由于有多个上级组织属于同一家企业的情形,可以在数据设置上设置仓库或组织所属的企业,从而对企业进行指标计算。

上述根据上级组织和企业的聚合计算而成的指标,可用来对组织/企业进行排名。

根据项目进行所属组织的聚合

应该可以根据项目的数据收集过程中,同时生成该组织的这个数据的汇总(非活跃度累计,而是构成活跃度的基础数据的累计,并运算),以生成该组织的该时间点的活跃度指标。

项目活跃度指标的三维动画显示

每个项目在一个时间点的活跃度是以一个三维坐标(提交数增量、拉取请求数增量、贡献者数增量)确定的,因此可以用 SVG 结合 D3.JS 来绘制一个根据时间变化的动画图。

也应该可以支持多个项目的该指标的同时展示。

于此,我希望最终是一个Web 界面,可以勾选或输入(一个或多个)项目名称,选择时间范围,然后生成可视化的展示,并可设置时间流速。

自动识别用户还是组织

目前采用的是两个不同的命令。
后续可以使用同一个命令分析。

此外,需要为二者添加不同的判断,当 organ 子命令的参数是用户时,提示错误。

需要进行的步骤

  1. 使用 request 来读取 github.com/{name},根据页面内容判断是用户还是组织 (此部分建议放在 helper 中实现)
  2. 返回 true or false
  3. 各子命令调用,提醒用户输入错误, 然后切换到另外的命令上去请求。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.