ニジカのスカトロ,ニジカトロ. https://bsky.app/profile/deerjika-bot.bsky.social
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.

129 lines
3.3 KiB

  1. """
  2. ニコニコのニジカ動画取得モヂュール
  3. """
  4. from typing import TypedDict
  5. import requests
  6. from bs4 import BeautifulSoup
  7. from requests.exceptions import Timeout
  8. class VideoInfo (TypedDict):
  9. contentId: str
  10. title: str
  11. tags: list[str]
  12. description: str
  13. def get_nico_deerjika (
  14. ) -> list:
  15. URL = ('https://snapshot.search.nicovideo.jp/api/v2/snapshot/video'
  16. '/contents/search')
  17. now = datetime.now ()
  18. base = now - timedelta (hours = 24)
  19. params = { 'q': '伊地知ニジカ OR ぼざろクリーチャーシリーズ',
  20. 'targets': 'tags',
  21. '_sort': '-startTime',
  22. 'fields': 'contentId,title,description,tags,startTime',
  23. '_limit': 20,
  24. 'jsonFilter': json.dumps ({ 'type': 'or',
  25. 'filters': [{
  26. 'type': 'range',
  27. 'field': 'startTime',
  28. 'from': ('%04d-%02d-%02dT05:00:00+09:00'
  29. % (base.year, base.month, base.day,
  30. base.hour, base.minute)),
  31. 'to': ('%04d-%02d-%02dT05:00:00+09:00'
  32. % (now.year, now.month, now.day)),
  33. 'include_lower': True }] }) }
  34. try:
  35. res = requests.get (URL, params = params, timeout = 60).json ()
  36. except Timeout:
  37. return []
  38. data = []
  39. for datum in res['data']:
  40. datum['tags'] = datum['tags'].split ()
  41. data.append (datum)
  42. return data
  43. pass
  44. def get_latest_deerjika (
  45. ) -> VideoInfo | None:
  46. tag = '伊地知ニジカ'
  47. url = f"https://www.nicovideo.jp/tag/{ tag }"
  48. params = { 'sort': 'f',
  49. 'order': 'd' }
  50. video_info = { }
  51. bs = get_bs_from_url (url, params)
  52. if bs is None:
  53. return None
  54. try:
  55. video = (bs.find_all ('ul', class_ = 'videoListInner')[1]
  56. .find ('li', class_ = 'item'))
  57. video_info['contentId'] = video['data-video-id']
  58. except Exception:
  59. return None
  60. bs = get_bs_from_url ('https://www.nicovideo.jp/watch/'
  61. + video_info['contentId'])
  62. if bs is None:
  63. return None
  64. try:
  65. video_info['title'] = '-'.join (bs.find ('title').text.split ('-')[:(-1)])[:(-1)]
  66. tags = bs.find ('meta', attrs = { 'name': 'keywords' }).get ('content')
  67. video_info['tags'] = tags.split (',')
  68. video_info['description'] = bs.find ('meta', attrs = { 'name': 'description' }).get ('content')
  69. except Exception:
  70. return None
  71. return video_info
  72. def get_bs_from_url (
  73. url: str,
  74. params: dict = { },
  75. ) -> BeautifulSoup | None:
  76. """
  77. URL から BeautifulSoup インスタンス生成
  78. Parameters
  79. ----------
  80. url: str
  81. 捜査する URL
  82. params: dict
  83. パラメータ
  84. Return
  85. ------
  86. BeautifulSoup | None
  87. BeautifulSoup オブゼクト(失敗したら None)
  88. """
  89. try:
  90. req = requests.get (url, params = params, timeout = 60)
  91. except Timeout:
  92. return None
  93. if req.status_code != 200:
  94. return None
  95. req.encoding = req.apparent_encoding
  96. return BeautifulSoup (req.text, 'html.parser')