fix bangumi, close

This commit is contained in:
Your Name 2023-10-31 04:29:28 -04:00 committed by Henri Dickson
parent c380220ab2
commit f862c78de5
4 changed files with 204 additions and 2 deletions

View file

@ -80,6 +80,18 @@ class IMDBMovieTestCase(TestCase):
self.assertEqual(site.resource.item.imdb, "tt1375666")
class BangumiMovieTestCase(TestCase):
@use_local_response
def test_scrape(self):
url = "https://bgm.tv/subject/237"
site = SiteManager.get_site_by_url(url)
self.assertEqual(site.id_value, "237")
site.get_resource_ready()
self.assertEqual(site.resource.metadata["title"], "攻壳机动队")
self.assertEqual(site.resource.item.primary_lookup_id_type, IdType.IMDB)
self.assertEqual(site.resource.item.imdb, "tt0113568")
class MultiMovieSitesTestCase(TestCase):
@use_local_response
def test_movies(self):

View file

@ -1,5 +1,6 @@
import logging
from catalog.book.utils import detect_isbn_asin
from catalog.common import *
from catalog.models import *
@ -12,6 +13,7 @@ class Bangumi(AbstractSite):
ID_TYPE = IdType.Bangumi
URL_PATTERNS = [
r"https://bgm\.tv/subject/(\d+)",
r"https://bangumi\.tv/subject/(\d+)",
]
WIKI_PROPERTY_ID = ""
DEFAULT_MODEL = None
@ -21,5 +23,116 @@ class Bangumi(AbstractSite):
return f"https://bgm.tv/subject/{id_value}"
def scrape(self):
# TODO rewrite with bangumi api https://bangumi.github.io/api/
pass
api_url = f"https://api.bgm.tv/v0/subjects/{self.id_value}"
o = BasicDownloader(api_url).download().json()
showtime = None
pub_year = None
pub_month = None
year = None
dt = o.get("date")
episodes = o.get("total_episodes", 0)
match o["type"]:
case 1:
model = "Edition"
if dt:
d = dt.split("-")
pub_year = d[0]
pub_month = d[1]
case 2 | 6:
is_series = episodes > 1
model = "TVSeason" if is_series else "Movie"
if dt:
year = dt.split("-")[0]
showtime = [{"time": dt, "region": "首播日期" if is_series else "发布日期"}]
case 3:
model = "Album"
case 4:
model = "Game"
case _:
raise ValueError(
f"Unknown type {o['type']} for bangumi subject {self.id_value}"
)
title = o.get("name_cn") or o.get("name")
orig_title = o.get("name") if o.get("name") != title else None
brief = o.get("summary")
genre = None
platform = None
other_title = []
imdb_code = None
isbn_type = None
isbn = None
language = None
pub_house = None
authors = None
site = None
director = None
for i in o.get("infobox", []):
k = i["key"]
v = i["value"]
match k:
case "别名":
other_title = [d["v"] for d in v] if type(v) == list else v
case "imdb_id":
imdb_code = v
case "isbn":
isbn_type, isbn = detect_isbn_asin(v)
case "语言":
language = v
case "出版社":
pub_house = v
case "导演":
director = v
case "作者":
authors = [d["v"] for d in v] if type(v) == list else v
case "平台":
platform = [d["v"] for d in v] if type(v) == list else v
case "游戏类型":
genre = v
case "官方网站" | "website":
site = v[0] if type(v) == list else v
img_url = o["images"].get("large") or o["images"].get("common")
raw_img = None
ext = None
if img_url:
raw_img, ext = BasicImageDownloader.download_image(
img_url, None, headers={}
)
data = {
"preferred_model": model,
"title": title,
"orig_title": orig_title,
"other_title": other_title or None,
"author": authors,
"genre": genre,
"translator": None,
"director": director,
"language": language,
"platform": platform,
"year": year,
"showtime": showtime,
"imdb_code": imdb_code,
"pub_house": pub_house,
"pub_year": pub_year,
"pub_month": pub_month,
"binding": None,
"episode_count": episodes or None,
"official_site": site,
"site": site,
"isbn": isbn,
"brief": brief,
"cover_image_url": img_url,
"release_date": dt,
}
lookup_ids = {}
if isbn:
lookup_ids[isbn_type] = isbn
if imdb_code:
lookup_ids[IdType.IMDB] = imdb_code
return ResourceContent(
metadata={k: v for k, v in data.items() if v is not None},
cover_image=raw_img,
cover_image_extention=ext,
lookup_ids=lookup_ids,
)

View file

@ -0,0 +1,76 @@
{% load admin_url %}
{% load duration %}
{% load static %}
{% load i18n %}
<section class="filter">
<script>
function filter() {
location = '{{ user.identity.url }}' + $('#shelf')[0].value + '/' + $('#category')[0].value + '/' + ( $('#year')[0].value ? $('#year')[0].value + '/' : '' );
}
</script>
<form role="search" method="get" action="">
<select name="year" id="year" onchange="filter()">
<option value="">全部</option>
{% for y in years %}
<option value="{{ y }}" {% if y == year %}selected{% endif %}>{{ y }}</option>
{% endfor %}
</select>
<select name="shelf" id="shelf" onchange="filter()">
<option {% if '/wishlist/' in request.path %}selected{% endif %}
value="wishlist">想看</option>
<option {% if '/progress/' in request.path %}selected{% endif %}
value="progress">在看</option>
<option {% if '/complete/' in request.path %}selected{% endif %}
value="complete">看过</option>
<option {% if '/reviews/' in request.path %}selected{% endif %}
value="reviews">评论</option>
</select>
<select name="category" id="category" onchange="filter()">
{% visible_categories as cats %}
{% if 'book' in cats %}
<option {% if '/book/' in request.path %}selected{% endif %} value="book">书籍</option>
{% endif %}
{% if 'movie' in cats %}
<option {% if '/movie/' in request.path %}selected{% endif %} value="movie">电影</option>
{% endif %}
{% if 'tv' in cats %}
<option {% if '/tv/' in request.path %}selected{% endif %} value="tv">剧集</option>
{% endif %}
{% if 'podcast' in cats %}
<option {% if '/podcast/' in request.path %}selected{% endif %}
value="podcast">播客</option>
{% endif %}
{% if 'music' in cats %}
<option {% if '/music/' in request.path %}selected{% endif %} value="music">音乐</option>
{% endif %}
{% if 'game' in cats %}
<option {% if '/game/' in request.path %}selected{% endif %} value="game">游戏</option>
{% endif %}
{% if 'performance' in cats %}
<option {% if '/performance/' in request.path %}selected{% endif %}
value="performance">演出</option>
{% endif %}
</select>
</form>
<!--
<style type="text/css">
#rating_select input {
padding: var(--pico-form-element-spacing-vertical) calc(var(--pico-form-element-spacing-horizontal)/4) !important
}
</style>
<form role="search" method="get" action="" id="rating_select">
<input type="submit" class="secondary outline" value="1">
<input type="submit" class="secondary outline" value="2">
<input type="submit" class="secondary outline" value="3">
<input type="submit" class="secondary outline" value="4">
<input type="submit" class="secondary outline" value="5">
<input type="submit" class="secondary outline" value="6">
<input type="submit" class="secondary outline" value="7">
<input type="submit" class="secondary outline" value="8">
<input type="submit" class="secondary outline" value="9">
<input type="submit" class="secondary" value="10">
<input type="submit" class="secondary outline" value="*">
</form>
-->
</section>

View file

@ -0,0 +1 @@
{"date":"1995-11-18","platform":"剧场版","images":{"small":"https://lain.bgm.tv/r/200/pic/cover/l/53/9f/237_78UdL.jpg","grid":"https://lain.bgm.tv/r/100/pic/cover/l/53/9f/237_78UdL.jpg","large":"https://lain.bgm.tv/pic/cover/l/53/9f/237_78UdL.jpg","medium":"https://lain.bgm.tv/r/800/pic/cover/l/53/9f/237_78UdL.jpg","common":"https://lain.bgm.tv/r/400/pic/cover/l/53/9f/237_78UdL.jpg"},"summary":" 2029年公安九课在市容很像香港的日本城市“新港市”中执行各种秘密任务。九课因为不顾正当程序的自作主张、强硬行事往往与政府其他部门起冲突例如负责外交的公安六课就与九课不合。另一方面九课之中的重要人物全身是义体的机械生化人草薙素子对于自己的现状一直隐隐感到不满。有一天公安九课因为一件外国政要的刺杀未遂案而开始追查神秘的黑客“傀儡师”。傀儡师能透过网络入侵人脑植入虚拟记忆再利用记忆被窜改的对象来达成目的。虽然九课的追查没有成功藏有傀儡师的“灵魂”的机械生化人却自行来到九课。公安六课随后赶来将傀儡师绑走。草薙素子因为在事前就推测出六课的绑架行动而成功拦截傀儡师。这时发现原来傀儡师并不是人类而是公安六课设计来非法操纵人类的电脑程式“2501计划”。2501计划在意外中产生自觉意识决定逃出六课以求生存并且要求和草薙素子的灵魂“融合”以求进一步发展。草薙素子最后在同事巴特的协助与掩护下完成融合并且脱离政府掌握下落不明其意识与整个网络融合。","name":"GHOST IN THE SHELL / 攻殻機動隊","name_cn":"攻壳机动队","tags":[{"name":"押井守","count":2519},{"name":"攻壳机动队","count":1960},{"name":"剧场版","count":1558},{"name":"科幻","count":1370},{"name":"赛博朋克","count":1004},{"name":"Production.IG","count":926},{"name":"1995","count":822},{"name":"士郎正宗","count":556},{"name":"Production.I.G","count":470},{"name":"神作","count":417},{"name":"攻殻機動隊","count":239},{"name":"超现实","count":229},{"name":"ProductionI.G","count":165},{"name":"漫画改","count":136},{"name":"漫改","count":70},{"name":"川井宪次","count":57},{"name":"严肃","count":54},{"name":"经典","count":54},{"name":"脑后插管","count":49},{"name":"日本","count":31},{"name":"川井憲次","count":27},{"name":"90年代","count":25},{"name":"动画电影","count":24},{"name":"SF","count":23},{"name":"菅野洋子","count":22},{"name":"1995年","count":22},{"name":"电影","count":21},{"name":"1995年11月","count":19},{"name":"战斗","count":19},{"name":"Production_I.G","count":18}],"infobox":[{"key":"中文名","value":"攻壳机动队"},{"key":"别名","value":[{"v":"攻殻機動隊"},{"v":"GHOST IN THE SHELL"}]},{"key":"上映年度","value":"1995年11月18日"},{"key":"片长","value":"82分"},{"key":"导演","value":"押井守"},{"key":"脚本","value":"伊藤和典"},{"key":"原作","value":"士郎正宗"},{"key":"分镜","value":"押井守"},{"key":"演出","value":"西久保瑞穂"},{"key":"人物设定","value":"沖浦啓之"},{"key":"作画监督","value":"沖浦啓之、黄瀬和哉"},{"key":"机械设定","value":"河森正治、竹内敦志"},{"key":"音乐","value":"川井憲次"},{"key":"动画制作","value":"Production I.G"},{"key":"话数","value":"1"},{"key":"imdb_id","value":"tt0113568"},{"key":"製作","value":"バンダイビジュアル、講談社、MANGA ENTERTAINMENT"}],"rating":{"rank":7,"total":7633,"count":{"1":15,"2":3,"3":7,"4":4,"5":28,"6":96,"7":404,"8":1573,"9":3044,"10":2459},"score":8.9},"total_episodes":1,"collection":{"on_hold":293,"dropped":70,"wish":3613,"collect":11104,"doing":272},"id":237,"eps":1,"volumes":0,"locked":false,"nsfw":false,"type":2}