You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
4.2 KiB

  1. """
  2. ニコニコ動画から動画情報を取得するためのヘルパ集
  3. """
  4. from __future__ import annotations
  5. from typing import TypedDict
  6. import requests
  7. from bs4 import BeautifulSoup
  8. from requests.exceptions import Timeout
  9. def fetch_video_info (
  10. video_code: str,
  11. ) -> VideoInfo | None:
  12. """
  13. 動画コードからタイトル、タグ、説明を取得して返す.
  14. Parameters
  15. ----------
  16. video_code: str
  17. 動画コード
  18. Return
  19. ------
  20. VideoInfo | None
  21. 動画情報
  22. """
  23. bs = _create_bs_from_url (f"https://www.nicovideo.jp/watch/{ video_code }")
  24. if bs is None:
  25. return None
  26. try:
  27. title_tag = bs.find ('title')
  28. if title_tag is None:
  29. return None
  30. title = '-'.join (title_tag.text.split ('-')[:(-1)]).strip ()
  31. tags_str: str = (bs.find ('meta', attrs = { 'name': 'keywords' })
  32. .get ('content')) # type: ignore
  33. tags = tags_str.split (',')
  34. description = (bs.find ('meta', attrs = { 'name': 'description' })
  35. .get ('content')) # type: ignore
  36. except (AttributeError, TypeError) as ex:
  37. print (ex)
  38. return None
  39. return { 'contentId': video_code,
  40. 'title': title,
  41. 'tags': tags,
  42. 'description': str (description) }
  43. def fetch_embed_info (
  44. url: str,
  45. ) -> tuple[str, str, str]:
  46. """
  47. ニコニコ動画の URL からタイトル、詳細、サムネールを取得して返す.
  48. Parameters
  49. ----------
  50. url: str
  51. 動画 URL
  52. Return
  53. ------
  54. tuple[str, str, str]
  55. タイトル、詳細、サムネールからなるタプル
  56. """
  57. title = ''
  58. description = ''
  59. thumbnail = ''
  60. bs = _create_bs_from_url (url)
  61. if bs is None:
  62. return ('', '', '')
  63. tmp = bs.find ('title')
  64. if tmp is not None:
  65. title = tmp.text
  66. tmp = bs.find ('meta', attrs = { 'name': 'description' })
  67. if tmp is not None and hasattr (tmp, 'get'):
  68. try:
  69. description = str (tmp.get ('content'))
  70. except (AttributeError, TypeError) as ex:
  71. print (ex)
  72. tmp = bs.find ('meta', attrs = { 'name': 'thumbnail' })
  73. if tmp is not None and hasattr (tmp, 'get'):
  74. try:
  75. thumbnail = str (tmp.get ('content'))
  76. except (AttributeError, TypeError) as ex:
  77. print (ex)
  78. return (title, description, thumbnail)
  79. def fetch_latest_video (
  80. tags: list[str],
  81. ) -> VideoInfo | None:
  82. """
  83. ニコニコから指定したタグが含まれる動画を検索し,最新のものを返す.
  84. Parameters
  85. ----------
  86. tags: list[str]
  87. タグ・リスト
  88. Return
  89. ------
  90. VideoInfo | None
  91. 動画情報
  92. """
  93. tag = ' OR '.join (tags)
  94. url = f"https://www.nicovideo.jp/tag/{ tag }"
  95. params = { 'sort': 'f',
  96. 'order': 'd' }
  97. video_info = { }
  98. bs = _create_bs_from_url (url, params)
  99. if bs is None:
  100. return None
  101. try:
  102. video = (bs.find_all ('ul', class_ = 'videoListInner')[1]
  103. .find ('li', class_ = 'item'))
  104. video_info['contentId'] = video['data-video-id']
  105. except (AttributeError, IndexError, KeyError, TypeError) as ex:
  106. print (ex)
  107. return None
  108. return fetch_video_info (video_info['contentId'])
  109. def _create_bs_from_url (
  110. url: str,
  111. params: dict | None = None,
  112. ) -> BeautifulSoup | None:
  113. """
  114. URL から BeautifulSoup オブゼクトを作成する.
  115. Parameters
  116. ----------
  117. url: str
  118. URL
  119. params: dict | None
  120. パラメータ
  121. Return
  122. ------
  123. BeautifulSoup | None
  124. BeautifulSoup オブゼクト
  125. """
  126. if params is None:
  127. params = { }
  128. try:
  129. req = requests.get (url, params = params, timeout = 60)
  130. except Timeout as ex:
  131. print (ex)
  132. return None
  133. if req.status_code != 200:
  134. return None
  135. req.encoding = req.apparent_encoding
  136. return BeautifulSoup (req.text, 'html.parser')
  137. class VideoInfo (TypedDict):
  138. """
  139. 動画情報
  140. """
  141. contentId: str
  142. title: str
  143. tags: list[str]
  144. description: str