Browse Source

#1

pull/5/head
みてるぞ 4 months ago
parent
commit
b7a88cc774
3 changed files with 140 additions and 6 deletions
  1. +1
    -1
      __init__.py
  2. +139
    -5
      module.py
  3. +0
    -0
      py.typed

+ 1
- 1
__init__.py View File

@@ -1 +1 @@
from .module.py import fetch_comments
from .module import VideoInfo, fetch_comments, fetch_embed_info, fetch_video_info

+ 139
- 5
module.py View File

@@ -1,3 +1,16 @@
from __future__ import annotations

import json
import random
import string
import time
from typing import Any, TypedDict

import requests
from bs4 import BeautifulSoup
from requests.exceptions import Timeout


def fetch_video_info (
video_code: str,
) -> VideoInfo | None:
@@ -6,20 +19,141 @@ def fetch_video_info (
return None

try:
title = bs.find ('title')
if title is None:
title_tag = bs.find ('title')
if title_tag is None:
return None
title = '-'.join (title.text.split ('-')[:(-1)])[:(-1)]
title = '-'.join (title_tag.text.split ('-')[:(-1)]).strip ()

tags_str: str = bs.find ('meta', attrs = { 'name': 'keywords' }).get ('content') # type: ignore
tags = tags_str.split (',')

description = bs.find ('meta', attrs = { 'name': 'description' }).get ('content') # type: ignore
except Exception:
except (AttributeError, TypeError):
return None

return { 'contentId': video_code,
'title': title,
'tags': tags,
'description': description }
'description': str (description) }


def fetch_comments (
video_code: str,
) -> list[Comment]:
time.sleep (1.2)

headers = { 'X-Frontend-Id': '6',
'X-Frontend-Version': '0' }

action_track_id = (
''.join (random.choice (string.ascii_letters + string.digits)
for _ in range (10))
+ '_'
+ str (random.randrange (10 ** 12, 10 ** 13)))

url = (f"https://www.nicovideo.jp/api/watch/v3_guest/{ video_code }"
+ f"?actionTrackId={ action_track_id }")

res = requests.post (url, headers = headers, timeout = 60).json ()

try:
nv_comment = res['data']['comment']['nvComment']
except KeyError:
return []
if nv_comment is None:
return []

headers = { 'X-Frontend-Id': '6',
'X-Frontend-Version': '0',
'Content-Type': 'application/json' }

params = { 'params': nv_comment['params'],
'additionals': { },
'threadKey': nv_comment['threadKey'] }

url = nv_comment['server'] + '/v1/threads'

res = (requests.post (url, json.dumps (params),
headers = headers,
timeout = 60)
.json ())

try:
return res['data']['threads'][1]['comments']
except (IndexError, KeyError):
return []


def fetch_embed_info (
url: str,
) -> tuple[str, str, str]:
title: str = ''
description: str = ''
thumbnail: str = ''

bs = _create_bs_from_url (url)
if bs is None:
return ('', '', '')

tmp = bs.find ('title')
if tmp is not None:
title = tmp.text

tmp = bs.find ('meta', attrs = { 'name': 'description' })
if tmp is not None and hasattr (tmp, 'get'):
try:
description = str (tmp.get ('content'))
except Exception:
pass

tmp = bs.find ('meta', attrs = { 'name': 'thumbnail' })
if tmp is not None and hasattr (tmp, 'get'):
try:
thumbnail = str (tmp.get ('content'))
except Exception:
pass

return (title, description, thumbnail)


def _create_bs_from_url (
url: str,
params: dict | None = None,
) -> BeautifulSoup | None:
if params is None:
params = { }

try:
req = requests.get (url, params = params, timeout = 60)
except Timeout:
return None

if req.status_code != 200:
return None

req.encoding = req.apparent_encoding

return BeautifulSoup (req.text, 'html.parser')


class VideoInfo (TypedDict):
contentId: str
title: str
tags: list[str]
description: str


class Comment (TypedDict):
id: str
no: int
vposMs: int
body: str
commands: list[str]
userId: str
isPremium: bool
score: int
postedAt: str
nicoruCount: int
nicoruId: Any
source: str
isMyPost: bool

+ 0
- 0
py.typed View File


Loading…
Cancel
Save