E 绅士、即 e-hentai,以其丰富的内容受到了各国阿宅们的赞美与欢迎,是广大人民喜闻乐见的优秀漫画网站。

同时,E 绅士因其囊括作品的数量、多样性、多语言版本、齐全而丰富的 tag 标注,成为了用于机器学习等领域的天然优秀数据集。

关于 e-hentai 数据集更多的论述请参考这篇博文:HHHentaiCollection☆!!! —— 一个ML数据集的设想。

同时,一个 E 绅士爬虫项目 E-HentaiCrawler 发布了其截至今年一月爬取到的所有数据,并发布了简单的统计报告:从 E 绅士(Ehentai)47 万条本子数据看各国死宅的兴趣爱好。

其中包括了约 47 万本作品不含图像的全部数据。但是其发布形式为 mysqldump 导出文件,使用起来不是很方便。于是我将数据整理去掉无用信息后,将其导入 Python ,每本作品信息分别保存在 dict 中,以 list 形式组织,并使用 pickle 模块保存为文件。

可以使用以下方法导入数据集:

1
2
3
import pickle
with open("ehdataset",'rb') as file:
dataset = pickle.load(file)

每个 dict 的结构如下:

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
{
"gid": 618395,
"token": "0439fa3666",
"title": "(Kouroumu 8) [Handful☆Happiness! (Fuyuki Nanahara)] TOUHOU GUNMANIA A2 (Touhou Project)",
"title_jpn": "(紅楼夢8) [Handful☆Happiness! (七原冬雪)] TOUHOU GUNMANIA A2 (東方Project)",
"category": "Non-H",//10 Categories of e-hentai
"thumb":"https://ehgt.org/14/63/1463dfbc16847c9ebef92c46a90e21ca881b2a12-1729712-4271-6032-jpg_l.jpg"//Url of thumbnails
"uploader": "avexotsukaai",
"posted": "1376143500",//Unix timestamp of upload
"filecount": "20",//pages number
"filesize": 51210504,//File size
"expunged": false,
"rating": "4.43",
"torrentcount": "0",
'Favorited': 103,//Favorite Number
"tags": [
"parody:touhou project",
"group:handful happiness",
"artist:nanahara fuyuki",
"full color",
"artbook",
"male:xxxxx",
"female:xxxxx"
]
}

为了演示数据集用法,也是从实际需求出发,使用向量余弦法判断两部作品 tag 的相似度,实现了一个基于简单相似度排序的推荐算法:

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
import pickle
import math
def calc(book1, book2):#将每个tag看作一个独立的维度,存在置1,否则为0;计算两部作品 tag 向量的余弦值。
cos = 0
book1 = set(book1["tags"])
book2 = set(book2["tags"])
if (math.sqrt(len(book1)) * math.sqrt(len(book2))) != 0:
cos = len(book1 & book2)/(math.sqrt(len(book1)) * math.sqrt(len(book2)))
else:
cos = 0
return cos
print("Loading...")
with open("ehdataset",'rb') as file:#加载数据集
dataset = pickle.load(file)
while True:
print('Please enter gid:')
gid = input()
sample = [item for item in dataset if str(item["gid"]) == gid]
if len(sample) == 0:
print("Invaild gid! The dataset maximum gid is {0}".format(dataset[-1:][0]["gid"]))
continue
for i in dataset:
i["cos"] = calc(sample[0], i)
dataset.sort(key=lambda x:x["cos"], reverse=True)
for i in dataset[0:20]:
if i["title_jpn"]:
print("{0} gid:{1} like:{2} rate:{3}".format(i["title_jpn"],i["gid"],i["Favorited"],i["rating"]))
else:
print("{0} gid:{1} like:{2} rate:{3}".format(i["title"],i["gid"],i["Favorited"],i["rating"]))

代码中 gid 为 e-hentai 的作品 ID,是唯一的。两部作品在空间中 tag 向量的夹角越小,相似度越高,其夹角余弦值则越大。这段代码实现了在数据集中通过 gid 任选一部作品,通过判断 tag 向量夹角余弦值,推荐相似度最高的 20 部作品。

还可以考虑自己手动键入多个 tag,计算相似度并作推荐,代码我就懒得写了,有兴趣请自行发挥。另外计算向量余弦的时候没有使用 numpy,主要是因为 tag 的总量很大,约 10 万种(绝大部分 tag 出现次数极少)。若生成为 10 万维向量再求值,会浪费大量内存空间,故采取了模拟手算的方法,仅需考虑有效维。

进一步思考,为了提升推荐算法的效果,还可以考虑修改不同 tag 的权重,起到增强偏好、过滤多语言版本等效果。

数据集和以上代码可以在 Github 上 clone:ZRStea/ehdataset

下一步考虑使用该数据集进行一些机器学习算法的实践尝试。