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.

191 lines
4.3 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 = { 'new_search': 'false',
  96. 'sort': 'f',
  97. 'order': 'd' }
  98. video_info = { }
  99. bs = _create_bs_from_url (url, params)
  100. if bs is None:
  101. return None
  102. try:
  103. video = (bs.find_all ('ul', class_ = 'videoListInner')[1]
  104. .find ('li', class_ = 'item'))
  105. video_info['contentId'] = video['data-video-id']
  106. except (AttributeError, IndexError, KeyError, TypeError) as ex:
  107. print (ex)
  108. return None
  109. return fetch_video_info (video_info['contentId'])
  110. def _create_bs_from_url (
  111. url: str,
  112. params: dict | None = None,
  113. ) -> BeautifulSoup | None:
  114. """
  115. URL から BeautifulSoup オブゼクトを作成する.
  116. Parameters
  117. ----------
  118. url: str
  119. URL
  120. params: dict | None
  121. パラメータ
  122. Return
  123. ------
  124. BeautifulSoup | None
  125. BeautifulSoup オブゼクト
  126. """
  127. if params is None:
  128. params = { }
  129. try:
  130. req = requests.get (url, params = params, timeout = 60)
  131. except Timeout as ex:
  132. print (ex)
  133. return None
  134. if req.status_code != 200:
  135. return None
  136. req.encoding = req.apparent_encoding
  137. return BeautifulSoup (req.text, 'html.parser')
  138. class VideoInfo (TypedDict):
  139. """
  140. 動画情報
  141. """
  142. contentId: str
  143. title: str
  144. tags: list[str]
  145. description: str