11月15日更新
最新版本的动态友联已经支持输出到自定义文件,因此读者继续参考本文时请注意文章的时效性。
由于本文对于仓库源码有一定的改动,请先确认你是否确实有这个需求,而后再理性地选择是否魔改。
废话我就不多说了,我们直接开始。
fork动态友链抓取仓库
首先,你需要fork动态友链抓取仓库,链接如下:
https://github.com/xaoxuu/issues-json-generatorhttps://github.com/xaoxuu/issues-json-generator
根据README内容完成配置。这里我就不多赘述了,需要保证你的workflow能够正确运行并且output
分支能看到输出的data.json
文件。
代码修改
在这个魔改中需要修改两部分内容(均处于main
分支下):config.yml
和generator/main.py
。这里先给出两者的文件:
提示
在复制源码前,我建议你看看我都改了什么。这有助于你对代码有宏观的把握,也对程序中可能出现的问题有解决想法。
config.yml
1
2
3
4
5
6
7
8
9
10
11
12
13# 网络请求设置
request:
timeout: 10 # 超时设置
ssl: false # ssl设置
# 要抓取的 issues 配置
issues:
repo: felixchen0707/friendLink_api # 仓库持有者/仓库名
label: active # 筛选具有 active 标签的 issue ,取消此项则会提取所有 open 状态的 issue
+ className:
+ - 'ordinary'
+ - 'top'
sort: updated-desc # 排序,按最近更新,取消此项则按创建时间排序
1
2
3
4
5
6
7
8
9
10
11
12
13# 网络请求设置
request:
timeout: 10 # 超时设置
ssl: false # ssl设置
# 要抓取的 issues 配置
issues:
repo: felixchen0707/friendLink_api # 仓库持有者/仓库名
label: active # 筛选具有 active 标签的 issue ,取消此项则会提取所有 open 状态的 issue
className:
- 'ordinary'
- 'top'
sort: updated-desc # 排序,按最近更新,取消此项则按创建时间排序
generator/main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87# -*- coding: utf-8 -*-
# author: https://github.com/Zfour
from bs4 import BeautifulSoup
import os
import request
import json
import config
version = 'v2'
outputdir = version # 输出文件结构变化时,更新输出路径版本
- filename = 'data.json'
data_pool = []
+ cfg = config.load()
+ filter = cfg['issues']
def mkdir(path):
folder = os.path.exists(path)
if not folder:
os.makedirs(path)
print("create dir:", path)
else:
print("dir exists:", path)
- def github_issuse(data_pool):
+ def github_issuse(data_pool, className):
print('\n')
print('------- github issues start ----------')
+ print('is catching label:' + className)
baselink = 'https://github.com/'
- cfg = config.load()
- filter = cfg['issues']
try:
for number in range(1, 100):
print('page:', number)
url = 'https://github.com/' + filter['repo'] + '/issues?page=' + str(number) + '&q=is%3Aopen'
if filter['label']:
- url = url + '+label%3A' + filter['label']
+ url = url + '+label%3A' + filter['label'] + '+label%3A' + className
if filter['sort']:
url = url + '+sort%3A' + filter['sort']
print('parse:', url)
github = request.get_data(url)
soup = BeautifulSoup(github, 'html.parser')
main_content = soup.find_all('div', {'aria-label': 'Issues'})
linklist = main_content[0].find_all('a', {'class': 'Link--primary'})
if len(linklist) == 0:
print('> end')
break
for item in linklist:
issueslink = baselink + item['href']
issues_page = request.get_data(issueslink)
issues_soup = BeautifulSoup(issues_page, 'html.parser')
try:
issues_linklist = issues_soup.find_all('pre')
source = issues_linklist[0].text
if "{" in source:
source = json.loads(source)
print(source)
data_pool.append(source)
except:
continue
except Exception as e:
- print('> end')
+ print('> end catching label:' + className)
print('------- github issues end ----------')
print('\n')
# 友链规则
+ for className in filter['className']:
+ data_pool.clear()
- github_issuse(data_pool=data_pool)
+ github_issuse(data_pool=data_pool, className=className)
mkdir(outputdir)
- full_path = outputdir + '/' + filename
+ full_path = outputdir + '/' + className + '.json'
with open(full_path, 'w', encoding='utf-8') as file_obj:
data = {
'version': version,
'content': data_pool
}
json.dump(data, file_obj, ensure_ascii=False, indent=2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79# -*- coding: utf-8 -*-
# author: https://github.com/Zfour
from bs4 import BeautifulSoup
import os
import request
import json
import config
version = 'v2'
outputdir = version # 输出文件结构变化时,更新输出路径版本
data_pool = []
cfg = config.load()
filter = cfg['issues']
def mkdir(path):
folder = os.path.exists(path)
if not folder:
os.makedirs(path)
print("create dir:", path)
else:
print("dir exists:", path)
def github_issuse(data_pool, className):
print('\n')
print('------- github issues start ----------')
print('is catching label:' + className)
baselink = 'https://github.com/'
try:
for number in range(1, 100):
print('page:', number)
url = 'https://github.com/' + filter['repo'] + '/issues?page=' + str(number) + '&q=is%3Aopen'
if filter['label']:
url = url + '+label%3A' + filter['label'] + '+label%3A' + className
if filter['sort']:
url = url + '+sort%3A' + filter['sort']
print('parse:', url)
github = request.get_data(url)
soup = BeautifulSoup(github, 'html.parser')
main_content = soup.find_all('div', {'aria-label': 'Issues'})
linklist = main_content[0].find_all('a', {'class': 'Link--primary'})
if len(linklist) == 0:
print('> end')
break
for item in linklist:
issueslink = baselink + item['href']
issues_page = request.get_data(issueslink)
issues_soup = BeautifulSoup(issues_page, 'html.parser')
try:
issues_linklist = issues_soup.find_all('pre')
source = issues_linklist[0].text
if "{" in source:
source = json.loads(source)
print(source)
data_pool.append(source)
except:
continue
except Exception as e:
print('> end catching label:' + className)
print('------- github issues end ----------')
print('\n')
# 友链规则
for className in filter['className']:
data_pool.clear()
github_issuse(data_pool=data_pool, className=className)
mkdir(outputdir)
full_path = outputdir + '/' + className + '.json'
with open(full_path, 'w', encoding='utf-8') as file_obj:
data = {
'version': version,
'content': data_pool
}
json.dump(data, file_obj, ensure_ascii=False, indent=2)
如何配置className
在我的构想中,一个网站应该由两部分构成:网站状态和网站分类。前者通过active
、404
、suspend
这类的label进行标记;后者则是你自定义的分类。
对于你自定义的分类名称,你需要写在config.yml
中的className
项中,例如我这里用ordinary
和top
来区分一般友链和置顶友链。经过配置后的className
包含的元素会在执行action的时候依次被作为label单独抓取合适的友链,例如下图是我的友链仓库:
我的友链仓库
其中,标记为active
的issue表示允许被抓取,而标记为top
和ordinary
的issue会在抓取top
和ordinary
的两批抓取中分别被抓取,来达到对友链分类的效果。
期望的运行结果
被标记为classA
的友链将会输出至output
分支下v2/classA.json
文件中,其他情况类似。由于label的名字与输出文件的名字强相关,这也要求你不要用奇怪的符号作为label的内容。
一些些补充
每个issue对应两个label
由于我使用站点状态和站点分类来分别表示一个网站,因此每一个issue至少都有两个label标记。例如,你的config.yml
中配置了:
1 | issues: |
若你仅仅为一个issue打上了ordinary
标记而没有加上active
标记或者反之,则该issue都不会被读取到。
加快访问速度
由于直接访问github的速度极慢,你可以使用Vercel构建该仓库来达到加速访问的效果。在你的Vercel的面板界面(dashboard)新建项目,导入你的友链数据仓库并点击deploy。由于你的输出内容一般不在main
分支但是Vercel却会默认构建main
分支,你需要进行以下操作:
点开项目,进入Settings->Git
界面,找到Production Branch
配置项,将分支名称从main/master
改成output
。下次向output
分支推送时,Vercel就会重新改为部署该分支了。
致谢
本文链接:https://my.lmcjl.com/post/16044.html
4 评论