前言
最近在做的統計報表項目包含人員代碼提交量。
要獲取人員代碼提交量首先要知道人員參與的項目。GitLab個人頁面中有Contributed projects頁面,如下圖:
遺憾的是GitLab api里沒有相應的API接口。
目前的做法只能通過頁面爬取。做法是使用接口登錄,然后訪問該頁面接口,然后解析數據。
獲取token
GitLab登錄頁面是有csrf_token保護的,因此要先從signin頁面抓取authenticity_token。頁面中有多個authenticity_token,不過都是一樣的。
import requests
import lxml
signin_url = 'http://gitlab服務地址/users/sign_in'
session = requests.session()
res = session.get(signin_url)
html = etree.HTML(res.text)
token, = html.xpath('//form[@id="new_ldap_user"]//input[@name="authenticity_token"]//@value') or ['']
使用session是為了保持登錄狀態,這里使用lxml解析並獲取token,首先要使用pip install lxml安裝。也可以使用正則或者bs4進行解析。
登錄
然后使用authenticity_token及用戶名密碼進行登錄。
# ldap登錄
login_url = 'http://gitlab服務地址/users/auth/ldapmain/callback'
data = {'utf8': '✓', 'authenticity_token': token, 'username': '登錄用戶名', 'password': '登錄密碼'}
session.post(login_url, data=data)
我們這里是使用ldap登錄的,使用普通方式登錄的也一樣,換下login_url即可。
獲取用戶參與項目
url = f'http://gitlab服務地址/users/{username}/contributed.json'
res = session.get(url)
html = etree.HTML(res.json()['html'])
_projects = html.xpath('//span[@class="project-full-name"]')
projects = [project.xpath('string(.)').replace('\n', '').replace(' ', '') for project in _projects]
這里面不是直接請求的用戶貢獻項目頁面,而是加了.json的AJAX請求地址。使用XPath的strings()函數獲取當前節點下的所有文本,並替換掉換行、空格。
projects便是解析出的用戶參與項目列表。
完整代碼
import requests
import lxml
GITLAB_BASE_URL = 'gitlab服務地址'
def gitlab_login(username, password):
"""登錄gitlab返回登錄后的session"""
# 從頁面獲取csrf_token
signin_url = 'GITLAB_BASE_URL/users/sign_in'
session = requests.session()
res = session.get(signin_url)
html = etree.HTML(res.text)
token, = html.xpath('//form[@id="new_ldap_user"]//input[@name="authenticity_token"]//@value') or ['']
# ldap登錄
login_url = 'GITLAB_BASE_URL/users/auth/ldapmain/callback'
data = {'utf8': '✓', 'authenticity_token': token, 'username': username, 'password': password}
session.post(login_url, data=data)
return session
def get_user_contributed(username):
"""從Gitlab獲取人員貢獻項目"""
session = gitlab_login('登錄用戶名', '登錄密碼')
url = f'GITLAB_BASE_URL/users/{username}/contributed.json'
res = session.get(url)
html = etree.HTML(res.json()['html'])
_projects = html.xpath('//span[@class="project-full-name"]')
projects = [project.xpath('string(.)').replace('\n', '').replace(' ', '') for project in _projects]
print(projects)
return projects
if __name__ == '__main__':
get_user_contributed('GitLab用戶名')