静画ランキングの作り方
2021年10月からクッキー☆タグ内で人気が高い絵をランキング形式で紹介しています。
これはもちろん自分で一枚一枚閲覧数を確認してランキングにしているわけではなく、前回の記事でも紹介したpythonのwebスクレイピングを利用しています。
さて、一言で「人気がある絵」といっても簡単にランク付けできるわけではありません。僕の投稿しているランキングでは
(閲覧数)+(コメント数×40)+(クリップ数×200)=ポイント
としてポイントの高い順にランキングにしています。(https://seiga.nicovideo.jp/seiga/im6609014 の計算式を参考にしました。)
個人的には毎月ちゃんと人気のある絵を抽出できていると思っています。しかし絵の人気さを比較するにあたり、閲覧、コメント、クリップの何を重視するかは人によって違うでしょうし、そもそも簡単に工作できるクリップ数やコメント数に高い補正をかけている点で公正なランキングとは言えないかもしれません。
そこで、僕がランキングを作るのに使っているpythonのソースコードを公開します。ランキングに不満がある人はこれコピペして自分好みの補正かけて、どうぞ。
入力が必要なのは
・ランキングを作りたいタグ
・集計の開始日と終了日
・閲覧、コメント、クリップの倍率
です。それ以外はいじる必要はありません。
※投稿数が多いタグで1年以上前のランキングや、集計範囲が1年以上のランキングを作ろうとするとクッソ時間がかかるのでお覚悟を
import requests
import bs4
import re
import urllib.parse
from requests_html import HTMLSession
session = HTMLSession()
li = [[0,0,0,0,0]]
#ランキングを作りたいタグを入力
tag = "クッキー☆"
#開始日と終了日を半角数字のみで入力(例 2022年2月5日にしたいときは「20220205」)
start_day = 20211201
end_day = 20211231
#閲覧、コメント、クリップの倍率を入力
view_mag = 1
comment_mag = 40
clip_mag = 200
#ここから下はいじる必要はありません
tag_enc = urllib.parse.quote(tag)
base_url = r"https://seiga.nicovideo.jp/tag/" + tag_enc + "?sort=image_created"
session = HTMLSession()
ses = session.get(base_url)
ses = bs4.BeautifulSoup(ses.text,"html.parser")
art_total = int(ses.select(".count")[0].text)
page_total = (art_total-1)//40 + 2
def GetDay(page):
base_url = r"https://seiga.nicovideo.jp/tag/" + tag_enc + r"?page=" + str(page)
ses = session.get(base_url)
data = bs4.BeautifulSoup(ses.text,"html.parser")
illustid = data.select('.illust_list img')[0].get("src").split("/")[5].split("u")[0]
indiv_url = "https://seiga.nicovideo.jp/seiga/im" + illustid
indiv_page = bs4.BeautifulSoup(session.get(indiv_url).text,"html.parser")
post_day = int(re.sub(r"\D", "",indiv_page.html.find(class_="lg_txt_date").text[:10]))
return(post_day)
def PointCalc(data,illustid,ID):
count = data.select(".illust_count")[illustid.index(ID)].text
user = data.select(".user")[illustid.index(ID)].text
count = re.findall(r"\d+",count)
point = int(count[0])*view_mag + int(count[1])*comment_mag + int(count[2])*clip_mag
print(ID_number)
new_li = [point,(count[0]),count[1],count[2],ID_number,user]
return(new_li)
if len(str(start_day)) != 8 and len(str(end_day)) != 8:
print("日付は8桁の半角数字で入力してください")
elif start_day > end_day:
print("終了日時は開始日時以降の日付を設定してください")
elif art_total == 0:
print("指定したタグのついた作品はありません")
else:
for i in range(1,page_total):
post_day = GetDay(i)
print(post_day)
if post_day <= end_day:
end_page = i
print(i)
break
for j in range(i,page_total):
post_day = GetDay(j)
print(post_day)
if post_day < start_day:
start_page = j
print(j)
break
base_url = r"https://seiga.nicovideo.jp/tag/" + tag_enc + r"?page=" + str(j-1)
ses = session.get(base_url)
data = bs4.BeautifulSoup(ses.text,"html.parser")
illustid = data.select('.illust_list img')
for ID in reversed(illustid):
ID_number = ID.get("src")
ID_number = ID_number.split("/")[5].split("u")[0]
indiv_url = "https://seiga.nicovideo.jp/seiga/im" + ID_number
indiv_page = bs4.BeautifulSoup(session.get(indiv_url).text,"html.parser")
post_day = int(re.sub(r"\D", "",indiv_page.html.find(class_="lg_txt_date").text[:10]))
if post_day >= start_day:
new_li = PointCalc(data,illustid,ID)
print(ID_number)
for exist in li:
if exist[0] < new_li[0]:
large = li[:li.index(exist)]
small = li[li.index(exist):]
li = large + [new_li] + small
break
for n in range(j-2,i-1,-1):
base_url = r"https://seiga.nicovideo.jp/tag/" + tag_enc + r"?page=" + str(n)
ses = session.get(base_url)
data = bs4.BeautifulSoup(ses.text,"html.parser")
illustid = data.select('.illust_list img')
for ID in reversed(illustid):
ID_number = ID.get("src")
ID_number = ID_number.split("/")[5].split("u")[0]
new_li = PointCalc(data,illustid,ID)
for exist in li:
if exist[0] < new_li[0]:
large = li[:li.index(exist)]
small = li[li.index(exist):]
li = large + [new_li] + small
break
if i > 1:
base_url = r"https://seiga.nicovideo.jp/tag/" + tag_enc + r"?page=" + str(i-1)
ses = session.get(base_url)
data = bs4.BeautifulSoup(ses.text,"html.parser")
illustid = data.select('.illust_list img')
for ID in reversed(illustid):
ID_number = ID.get("src")
ID_number = ID_number.split("/")[5].split("u")[0]
indiv_url = "https://seiga.nicovideo.jp/seiga/im" + ID_number
indiv_page = bs4.BeautifulSoup(session.get(indiv_url).text,"html.parser")
post_day = int(re.sub(r"\D", "",indiv_page.html.find(class_="lg_txt_date").text[:10]))
print(ID_number)
if post_day > end_day:
break
new_li = PointCalc(data,illustid,ID)
for exist in li:
if exist[0] < new_li[0]:
large = li[:li.index(exist)]
small = li[li.index(exist):]
li = large + [new_li] + small
break
start_day = str(start_day)
end_day = str(end_day)
filename = "対象タグ:" + tag + "期間:" + start_day[:4] + "年" + start_day[4:6] + "月" + start_day[6:] + "日~" + end_day[:4] + "年" + end_day[4:6] + "月" + end_day[6:] + "日" + ".txt"
f = open(filename, 'a',encoding='UTF-8')
wx = "対象タグ:" + tag
wy = "期間:" + start_day[:4] + "年" + start_day[4:6] + "月" + start_day[6:] + "日" + "~" + end_day[:4] + "年" + end_day[4:6] + "月" + end_day[6:] + "日"
wz = "総投稿枚数:" + str(len(li) - 1) + "枚"
f.write(wx + " \n")
f.write(wy + " \n")
f.write(wz + " \n" + " \n")
print(wx)
print(wy)
print(wz)
for seiga in li:
if seiga[0] == 0:
break
else:
rank = str(li.index(seiga) + 1)
wa = rank + "位"
wb = "https://seiga.nicovideo.jp/seiga/im"+ seiga[4]
wc = "投稿者:" + seiga[5]
wd = "閲覧:" + seiga[1] + r"/コメント:" + seiga[2] + r"/クリップ:" + seiga[3]
we = "ポイント " + str(seiga[0])
print(wa)
print(wb)
print(wc)
print(wd)
print(we)
f.write(wa + " \n")
f.write(wb + " \n")
f.write(wc + " \n")
f.write(wd + " \n")
f.write(we + " \n" + " \n")
f.close()