basic support for douban drama

This commit is contained in:
Your Name 2023-02-15 23:45:12 -05:00 committed by Henri Dickson
parent f570083565
commit 69ef9ab627
11 changed files with 3606 additions and 23 deletions

View file

@ -6,35 +6,100 @@ from django.db import models
class Performance(Item):
category = ItemCategory.Performance
url_path = "performance"
demonstrative = _("这个演出")
douban_drama = LookupIdDescriptor(IdType.DoubanDrama)
versions = jsondata.ArrayField(
other_title = jsondata.ArrayField(
verbose_name=_("其它标题"),
base_field=models.CharField(),
null=False,
blank=False,
default=list,
)
genre = jsondata.ArrayField(
verbose_name=_("类型"),
base_field=models.CharField(blank=True, default="", max_length=200),
null=True,
blank=True,
default=list,
)
version = jsondata.ArrayField(
verbose_name=_("版本"),
base_field=models.CharField(),
null=False,
blank=False,
default=list,
)
directors = jsondata.ArrayField(
director = jsondata.ArrayField(
verbose_name=_("导演"),
base_field=models.CharField(),
null=False,
blank=False,
default=list,
)
playwrights = jsondata.ArrayField(
playwright = jsondata.ArrayField(
verbose_name=_("编剧"),
base_field=models.CharField(),
null=False,
blank=False,
default=list,
)
actors = jsondata.ArrayField(
actor = jsondata.ArrayField(
verbose_name=_("主演"),
base_field=models.CharField(),
null=False,
blank=False,
default=list,
)
composer = jsondata.ArrayField(
verbose_name=_("作曲"),
base_field=models.CharField(),
null=False,
blank=False,
default=list,
)
choreographer = jsondata.ArrayField(
verbose_name=_("编舞"),
base_field=models.CharField(),
null=False,
blank=False,
default=list,
)
troupe = jsondata.ArrayField(
verbose_name=_("剧团"),
base_field=models.CharField(),
null=False,
blank=False,
default=list,
)
theatre = jsondata.ArrayField(
verbose_name=_("剧场"),
base_field=models.CharField(),
null=False,
blank=False,
default=list,
)
opening_date = jsondata.CharField(
verbose_name=_("演出日期"), max_length=100, null=True, blank=True
)
official_site = jsondata.CharField(
verbose_name=_("官方网站"), max_length=1000, null=True, blank=True
)
METADATA_COPY_LIST = [
"title",
"brief",
"other_title",
"genre",
"version",
"director",
"playwright",
"actor",
"composer",
"choreographer",
"troupe",
"theatre",
"opening_date",
"official_site",
]
class Meta:
proxy = True

View file

@ -19,6 +19,32 @@ class DoubanDramaTestCase(TestCase):
@use_local_response
def test_scrape(self):
t_url = "https://www.douban.com/location/drama/25883969/"
site = SiteManager.get_site_by_url(t_url)
resource = site.get_resource_ready()
item = site.get_item()
self.assertEqual(item.title, "不眠之人·拿破仑")
self.assertEqual(item.other_title, ["眠らない男・ナポレオン ―愛と栄光の涯(はて)に―"])
self.assertEqual(item.genre, ["音乐剧"])
self.assertEqual(item.troupe, ["宝塚歌剧团"])
self.assertEqual(item.composer, ["ジェラール・プレスギュルヴィック"])
t_url = "https://www.douban.com/location/drama/20270776/"
site = SiteManager.get_site_by_url(t_url)
resource = site.get_resource_ready()
item = site.get_item()
self.assertEqual(item.title, "相声说垮鬼子们")
self.assertEqual(item.opening_date, "1997-05")
self.assertEqual(item.theatre, ["臺北新舞臺"])
t_url = "https://www.douban.com/location/drama/24311571/"
site = SiteManager.get_site_by_url(t_url)
resource = site.get_resource_ready()
item = site.get_item()
self.assertEqual(item.other_title, ["死而复生的伊菲格尼", "Iphigenie auf Tauris"])
self.assertEqual(item.opening_date, "1974-04-21")
self.assertEqual(item.choreographer, ["Pina Bausch"])
t_url = "https://www.douban.com/location/drama/24849279/"
site = SiteManager.get_site_by_url(t_url)
self.assertEqual(site.ready, False)
@ -27,11 +53,12 @@ class DoubanDramaTestCase(TestCase):
self.assertEqual(resource.metadata["title"], "红花侠")
item = site.get_item()
self.assertEqual(item.title, "红花侠")
# self.assertEqual(i.other_titles, ['スカーレットピンパーネル', 'THE SCARLET PIMPERNEL'])
# self.assertEqual(len(i.brief), 545)
# self.assertEqual(i.genres, ['音乐剧'])
# self.assertEqual(i.versions, ['08星组公演版', '10年月組公演版', '17年星組公演版', 'ュージカル2017年版'])
# self.assertEqual(i.directors, ['小池修一郎', '小池 修一郎', '石丸さち子'])
# self.assertEqual(i.playwrights, ['小池修一郎', 'Baroness Orczy原作', '小池 修一郎'])
# self.assertEqual(i.actors, ['安蘭けい', '柚希礼音', '遠野あすか', '霧矢大夢', '龍真咲'])
self.assertEqual(item.other_title, ["THE SCARLET PIMPERNEL", "スカーレットピンパーネル"])
self.assertEqual(len(item.brief), 545)
self.assertEqual(item.genre, ["音乐剧"])
self.assertEqual(
item.version, ["08星组公演版", "10年月組公演版", "17年星組公演版", "ュージカル2017年"]
)
self.assertEqual(item.director, ["小池修一郎", "小池 修一郎", "石丸さち子"])
self.assertEqual(item.playwright, ["小池修一郎", "Baroness Orczy原作", "小池 修一郎"])
self.assertEqual(item.actor, ["安蘭けい", "柚希礼音", "遠野あすか", "霧矢大夢", "龍真咲"])

View file

@ -16,7 +16,7 @@ class DoubanDrama(AbstractSite):
DEFAULT_MODEL = Performance
@classmethod
def id_to_url(self, id_value):
def id_to_url(cls, id_value):
return "https://www.douban.com/location/drama/" + id_value + "/"
def scrape(self):
@ -29,49 +29,77 @@ class DoubanDrama(AbstractSite):
else:
raise ParseError(self, "title")
data["other_titles"] = [s.strip() for s in title_elem[1:]]
data["other_title"] = [s.strip() for s in title_elem[1:]]
other_title_elem = h.xpath(
"//dl//dt[text()='又名:']/following::dd[@itemprop='name']/text()"
)
if len(other_title_elem) > 0:
data["other_titles"].append(other_title_elem[0].strip())
data["other_title"] += other_title_elem
data["other_title"] = list(set(data["other_title"]))
plot_elem = h.xpath("//div[@id='link-report']/text()")
if len(plot_elem) == 0:
plot_elem = h.xpath("//div[@class='abstract']/text()")
data["brief"] = "\n".join(plot_elem) if len(plot_elem) > 0 else ""
data["genres"] = [
data["genre"] = [
s.strip()
for s in h.xpath(
"//dl//dt[text()='类型:']/following-sibling::dd[@itemprop='genre']/text()"
)
]
data["versions"] = [
data["version"] = [
s.strip()
for s in h.xpath(
"//dl//dt[text()='版本:']/following-sibling::dd[@class='titles']/a//text()"
)
]
data["directors"] = [
data["director"] = [
s.strip()
for s in h.xpath(
"//div[@class='meta']/dl//dt[text()='导演:']/following-sibling::dd/a[@itemprop='director']//text()"
)
]
data["playwrights"] = [
data["composer"] = [
s.strip()
for s in h.xpath(
"//div[@class='meta']/dl//dt[text()='作曲:']/following-sibling::dd/a[@itemprop='musicBy']//text()"
)
]
data["choreographer"] = [
s.strip()
for s in h.xpath(
"//div[@class='meta']/dl//dt[text()='编舞:']/following-sibling::dd/a[@itemprop='choreographer']//text()"
)
]
data["troupe"] = [
s.strip()
for s in h.xpath(
"//div[@class='meta']/dl//dt[text()='演出团体:']/following-sibling::dd/a[@itemprop='performer']//text()"
)
]
data["playwright"] = [
s.strip()
for s in h.xpath(
"//div[@class='meta']/dl//dt[text()='编剧:']/following-sibling::dd/a[@itemprop='author']//text()"
)
]
data["actors"] = [
data["actor"] = [
s.strip()
for s in h.xpath(
"//div[@class='meta']/dl//dt[text()='主演:']/following-sibling::dd/a[@itemprop='actor']//text()"
)
]
date_elem = h.xpath("//dl//dt[text()='演出日期:']/following::dd/text()")
data["opening_date"] = date_elem[0] if date_elem else None
data["theatre"] = [
s.strip()
for s in h.xpath(
"//div[@class='meta']/dl//dt[text()='演出剧院:']/following-sibling::dd/a[@itemprop='location']//text()"
)
]
img_url_elem = h.xpath("//img[@itemprop='image']/@src")
data["cover_image_url"] = img_url_elem[0].strip() if img_url_elem else None

View file

@ -15,7 +15,7 @@
<div class="entity-detail__fields">
<div class="entity-detail__rating">
{% if item.rating and item.rating_count >= 5 %}
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:"0" }}"></span>
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:0 }}"></span>
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
<small>({{ item.rating_count }}人评分)</small>
{% else %}

View file

@ -255,7 +255,9 @@
<div class="action-panel__label">{% trans '标记' %}{% trans item.demonstrative %}</div>
<div class="action-panel__button-group">
{% for k, v in shelf_types %}
{% if v %}
<button class="action-panel__button" data-status="{{ k }}" hx-get="{% url 'journal:mark' item.uuid %}?shelf_type={{ k }}" class="edit" hx-target="body" hx-swap="beforeend">{% trans v %}</button>
{% endif %}
{% endfor %}
</div>
</div>

View file

@ -1 +1,146 @@
Unsupported Data Type
{% extends "item_base.html" %}
{% load static %}
{% load i18n %}
{% load l10n %}
{% load humanize %}
{% load admin_url %}
{% load mastodon %}
{% load oauth_token %}
{% load truncate %}
{% load strip_scheme %}
{% load thumb %}
<!-- class specific details -->
{% block details %}
<div class="entity-detail__fields">
<div class="entity-detail__rating">
{% if item.rating and item.rating_count >= 5 %}
<span class="entity-detail__rating-star rating-star" data-rating-score="{{ item.rating | floatformat:0 }}"></span>
<span class="entity-detail__rating-score"> {{ item.rating | floatformat:1 }} </span>
<small>({{ item.rating_count }}人评分)</small>
{% else %}
<span> {% trans '评分:评分人数不足' %}</span>
{% endif %}
</div>
<div>{% if item.other_title %}{% trans '别名:' %}
{% for other_title in item.other_title %}
<span {% if forloop.counter > 5 %}style="display: none;" {% endif %}>
<span class="other_title">{{ other_title }}</span>
{% if not forloop.last %} / {% endif %}
</span>
{% endfor %}
{% if item.other_title|length > 5 %}
<a href="javascript:void(0);" id="otherTitleMore">{% trans '更多' %}</a>
<script>
$("#otherTitleMore").on('click', function (e) {
$("span.other_title:not(:visible)").each(function (e) {
$(this).parent().removeAttr('style');
});
$(this).remove();
})
</script>
{% endif %}
{% endif %}
</div>
<div>
{% if item.genre %}{% trans '类型:' %}
{% for genre in item.genre %}
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
{% endfor %}
{% endif %}
</div>
<div>
{% if item.director %}{% trans '导演:' %}
{% for director in item.director %}
<span>{{ director }}</span>{% if not forloop.last %} / {% endif %}
{% endfor %}
{% endif %}
</div>
<div>
{% if item.playwright %}{% trans '编剧:' %}
{% for playwright in item.playwright %}
<span>{{ playwright }}</span>{% if not forloop.last %} / {% endif %}
{% endfor %}
{% endif %}
</div>
<div>
{% if item.actor %}{% trans '主演:' %}
{% for actor in item.actor %}
<span>{{ actor }}</span>{% if not forloop.last %} / {% endif %}
{% endfor %}
{% endif %}
</div>
<div>
{% if item.choreographer %}{% trans '编舞:' %}
{% for choreographer in item.choreographer %}
<span>{{ choreographer }}</span>{% if not forloop.last %} / {% endif %}
{% endfor %}
{% endif %}
</div>
<div>
{% if item.composer %}{% trans '作曲:' %}
{% for composer in item.composer %}
<span>{{ composer }}</span>{% if not forloop.last %} / {% endif %}
{% endfor %}
{% endif %}
</div>
</div>
<div class="entity-detail__fields">
<div>
{% if item.troupe %}{% trans '剧团:' %}
{% for troupe in item.troupe %}
<span>{{ troupe }}</span>{% if not forloop.last %} / {% endif %}
{% endfor %}
{% endif %}
</div>
<div>
{% if item.theatre %}{% trans '剧场:' %}
{% for theatre in item.theatre %}
<span>{{ theatre }}</span>{% if not forloop.last %} / {% endif %}
{% endfor %}
{% endif %}
</div>
<div>
{% if item.opening_date %}{% trans '演出日期:' %}
<span>{{ item.opening_date }}</span>
{% endif %}
</div>
<div>
{% if item.version %}{% trans '版本:' %}
{% for version in item.version %}
<span>{{ version }}</span>{% if not forloop.last %} / {% endif %}
{% endfor %}
{% endif %}
</div>
<div>{% if item.official_site %}
{% trans '官方网站:' %}{{ item.official_site|urlizetrunc:42 }}
{% endif %}
</div>
{% if item.last_editor and item.last_editor.preference.show_last_edit %}
<div>{% trans '最近编辑者:' %}<a href="{% url 'journal:user_profile' item.last_editor.mastodon_username %}">{{ item.last_editor | default:"" }}</a></div>
{% endif %}
<div>
{% if user.is_authenticated %}
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
{% endif %}
</div>
</div>
{% endblock %}
<!-- class specific sidebar -->
{% block sidebar %}
{% endblock %}

View file

@ -525,6 +525,9 @@ ShelfTypeNames = [
[ItemCategory.Podcast, ShelfType.WISHLIST, _("想听")],
[ItemCategory.Podcast, ShelfType.PROGRESS, _("在听")],
[ItemCategory.Podcast, ShelfType.COMPLETE, _("听过")],
[ItemCategory.Performance, ShelfType.WISHLIST, _("想看")],
[ItemCategory.Performance, ShelfType.PROGRESS, _("")],
[ItemCategory.Performance, ShelfType.COMPLETE, _("看过")],
]

View file

@ -25,7 +25,9 @@
<div id="statusSelection" class="mark-modal__status-radio float-right">
<ul id="id_status">
{% for k, v in shelf_types %}
{% if v %}
<li><label for="id_status_{{ k }}"><input type="radio" name="status" value="{{ k }}" required="" id="id_status_{{ k }}" {% if shelf_type == k %}checked=""{% endif %}> {{ v }}</label></li>
{% endif %}
{% endfor %}
</ul>
</div>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff