Browse Source

完成(たぶん)

feature/query
みてるぞ 1 month ago
parent
commit
e4b541ecdc
1 changed files with 137 additions and 21 deletions
  1. +137
    -21
      update_db.py

+ 137
- 21
update_db.py View File

@@ -1,3 +1,7 @@
"""
日次で実行し,ぼざクリ DB を最新に更新する.
"""

from __future__ import annotations from __future__ import annotations


import json import json
@@ -7,7 +11,7 @@ import string
import time import time
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import TypedDict, cast
from typing import Any, TypedDict, cast


import mysql.connector import mysql.connector
import requests import requests
@@ -16,15 +20,6 @@ DbNull = (None,)
DbNullType = tuple[None] DbNullType = tuple[None]




class VideoResult (TypedDict):
contentId: str
title: str
tags: list[str]
description: str
viewCounter: int
startTime: str


class VideoSearchParam (TypedDict): class VideoSearchParam (TypedDict):
q: str q: str
targets: str targets: str
@@ -34,8 +29,29 @@ class VideoSearchParam (TypedDict):
jsonFilter: str jsonFilter: str




class VideoResult (TypedDict):
contentId: str
title: str
tags: list[str]
description: str
viewCounter: int
startTime: str


class CommentResult (TypedDict): class CommentResult (TypedDict):
pass
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




def main ( def main (
@@ -50,10 +66,13 @@ def main (
tag_dao = TagDao (conn) tag_dao = TagDao (conn)
video_tag_dao = VideoTagDao (conn) video_tag_dao = VideoTagDao (conn)
video_history_dao = VideoHistoryDao (conn) video_history_dao = VideoHistoryDao (conn)
comment_dao = CommentDao (conn)
user_dao = UserDao (conn)


api_data = search_nico_by_tags (['伊地知ニジカ', 'ぼざろクリーチャーシリーズ']) api_data = search_nico_by_tags (['伊地知ニジカ', 'ぼざろクリーチャーシリーズ'])


update_tables (video_dao, tag_dao, video_tag_dao, video_history_dao, api_data, now)
update_tables (video_dao, tag_dao, video_tag_dao, video_history_dao, comment_dao, user_dao,
api_data, now)


# TODO: 書くこと # TODO: 書くこと


@@ -63,9 +82,12 @@ def update_tables (
tag_dao: TagDao, tag_dao: TagDao,
video_tag_dao: VideoTagDao, video_tag_dao: VideoTagDao,
video_history_dao: VideoHistoryDao, video_history_dao: VideoHistoryDao,
comment_dao: CommentDao,
user_dao: UserDao,
api_data: list[VideoResult], api_data: list[VideoResult],
now: datetime, now: datetime,
) -> None: ) -> None:
video_ids: list[int] = []
for datum in api_data: for datum in api_data:
video = VideoDto (code = datum['contentId'], video = VideoDto (code = datum['contentId'],
title = datum['title'], title = datum['title'],
@@ -73,6 +95,7 @@ def update_tables (
uploaded_at = datetime.fromisoformat (datum['startTime'])) uploaded_at = datetime.fromisoformat (datum['startTime']))
video_dao.upsert (video, False) video_dao.upsert (video, False)
if video.id_ is not None: if video.id_ is not None:
video_ids.append (video.id_)
video_history = VideoHistoryDto (video_id = video.id_, video_history = VideoHistoryDto (video_id = video.id_,
fetched_at = now, fetched_at = now,
views_count = datum['viewCounter']) views_count = datum['viewCounter'])
@@ -99,17 +122,37 @@ def update_tables (
tag_id = tag.id_, tag_id = tag.id_,
tagged_at = now) tagged_at = now)
video_tag_dao.insert (video_tag, False) video_tag_dao.insert (video_tag, False)
# TODO: コメント取得すること

# TODO: 削除処理,存在しなぃ動画リストを取得した上で行ふこと
# video_dao.delete (video_ids, now)

# TODO: 書くこと
for com in fetch_comments (video.code):
user = user_dao.fetch_by_code (com['userId'])
if user is None:
user = UserDto (code = com['userId'])
user_dao.insert (user)
if video.id_ is not None and user.id_ is not None:
comment = CommentDto (video_id = video.id_,
comment_no = com['no'],
user_id = user.id_,
content = com['body'],
posted_at = datetime.fromisoformat (com['postedAt']),
nico_count = com['nicoruCount'],
vpos_ms = com['vposMs'])
comment_dao.upsert (comment, False)

alive_video_ids = [d['contentId'] for d in api_data]

lost_video_ids: list[int] = []
videos = video_dao.fetch_alive ()
for video in videos:
if video.id_ is not None and video.id_ not in alive_video_ids:
lost_video_ids.append (video.id_)

video_dao.delete (lost_video_ids, now)




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

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


@@ -119,7 +162,7 @@ def fetch_comments (
+ '_' + '_'
+ str (random.randrange (10 ** 12, 10 ** 13))) + str (random.randrange (10 ** 12, 10 ** 13)))


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


res = requests.post (url, headers = headers, timeout = 60).json () res = requests.post (url, headers = headers, timeout = 60).json ()
@@ -253,6 +296,27 @@ class VideoDao:
videos.append (self._create_dto_from_row (row, with_relation_tables)) videos.append (self._create_dto_from_row (row, with_relation_tables))
return videos return videos


def fetch_alive (
self,
) -> list[VideoDto]:
with self.conn.cursor () as c:
c.execute ("""
SELECT
id,
code,
title,
description,
uploaded_at,
deleted_at
FROM
videos
WHERE
deleted_at IS NULL""")
videos: list[VideoDto] = []
for row in c.fetchall ():
videos.append (self._create_dto_from_row (row, False))
return videos

def upsert ( def upsert (
self, self,
video: VideoDto, video: VideoDto,
@@ -836,6 +900,58 @@ class CommentDto:
nico_count: int = 0 nico_count: int = 0
vpos_ms: int | DbNullType = DbNull vpos_ms: int | DbNullType = DbNull
video: VideoDto | None = None video: VideoDto | None = None
user: UserDto | None = None


class UserDao:
def __init__ (
self,
conn,
):
self.conn = conn

def fetch_by_code (
self,
user_code: str
) -> UserDto | None:
with self.conn.cursor () as c:
c.execute ("""
SELECT
id,
code
FROM
users
WHERE
code = %s""", user_code)
row = c.fetchone ()
if row is None:
return None
return self._create_dto_from_row (row)

def insert (
self,
user: UserDto,
) -> None:
with self.conn.cursor () as c:
c.execute ("""
INSERT INTO
users(code)
VALUES
(%s)""", user.code)
user.id_ = c.lastrowid

def _create_dto_from_row (
self,
row,
) -> UserDto:
return UserDto (id_ = row['id'],
code = row['code'])


@dataclass (slots = True)
class UserDto:
code: str
id_: int | None = None




if __name__ == '__main__': if __name__ == '__main__':


Loading…
Cancel
Save