import yt_dlp, json, os
VIDEO_ID = 'dQw4w9WgXcQ'
VIDEO_URL = f'https://www.youtube.com/watch?v={VIDEO_ID}'
def download_chat(video_url):
ydl_opts = {
'skip_download': True,
'writeinfojson': True,
'writethumbnail': True,
'writesubtitles': True,
'subtitlesformat': 'json',
'outtmpl': f'{VIDEO_ID}.json',
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([video_url])
return f"{VIDEO_ID}.json.live_chat.json"
def parse_chat_json(chat_filename):
if not os.path.exists(chat_filename):
return []
messages = []
with open(chat_filename, 'r', encoding='utf-8') as f:
for line in f:
data = json.loads(line)
try:
print(data['replayChatItemAction']['actions'][0]['addChatItemAction']['item']['liveChatTextMessageRenderer'])
author_name = data['replayChatItemAction']['actions'][0]['addChatItemAction']['item']['liveChatTextMessageRenderer']['authorName']['simpleText']
message_parts = data['replayChatItemAction']['actions'][0]['addChatItemAction']['item']['liveChatTextMessageRenderer']['message']['runs']
message = ''.join(part.get('text', '') for part in message_parts)
timestamp = data['replayChatItemAction']['actions'][0]['addChatItemAction']['item']['liveChatTextMessageRenderer']['timestampText']['simpleText']
messages.append(f"{author_name}: {message} ({timestamp})")
except KeyError:
continue
return messages
def save_chat_to_txt(chat_filename, video_id):
chat_messages = parse_chat_json(chat_filename)
output_filename = f'output_{video_id}.txt'
with open(output_filename, 'w', encoding='utf-8') as out_file:
for message in chat_messages:
out_file.write(message + '\n')
def clean_up_files(video_id):
for ext in ['json.webp', 'json.live_chat.json', 'json.info.json']:
filename = f"{video_id}.{ext}"
if os.path.exists(filename):
os.remove(filename)
if __name__ == '__main__':
chat_file = download_chat(VIDEO_URL)
if chat_file:
save_chat_to_txt(chat_file, VIDEO_ID)
clean_up_files(VIDEO_ID)
class Semaphore {
constructor(max = 1) {
if (max < 1) { max = 1; }
this.max = max;
this.count = 0;
this.queue = [];
}
acquire() {
let promise;
if (this.count < this.max) {
promise = Promise.resolve();
} else {
promise = new Promise(resolve => {
this.queue.push(resolve);
});
}
this.count++;
return promise;
}
release() {
if (this.queue.length > 0) {
const resolve = this.queue.shift();
resolve();
}
this.count--;
}
}
const semaphore = new Semaphore(10);
for (const url of urls) {
await semaphore.acquire();
void downloadUrlSynchronized(url, semaphore);
}
async function downloadUrlSynchronized(url, semaphore) {
const resp = await fetch(url);
const blob = await resp.blob();
semaphore.release();
// const name = new URL(url).pathname.slice(1);
// downloadBlob(blob, name, url);
}
fetch
) будет не больше 10 в один момент, что собственно и требовалось.3
:Что будет если я сделаю бота в VK который будет смотреть айпи адреса и выводить ФИО владельцев и номера телефонов?
Это по закону УК РФ запрещено?
# Сохранить адрес шаблона в переменную template
git remote add template https://github.com/OWNER/TEMPLATE.git
# Скачать все обновления
git fetch template
# Попробовать сделать слияние ветки BRANCH-NAME шаблона с нашей текущей веткой
git merge --allow-unrelated-histories template/BRANCH-NAME
Опция --allow-unrelated-histories нужна, так как истории веток никак не связаны. :screenshot --fullpage
firefox --screenshot [url]
/interface bridge settings set use-ip-firewall=yes
, что позволит фильтровать DHCP-пакеты непосредственно в IP Firewall.osInfo()
, .cpu()
, .currentLoad()
и .mem()
— это промисы.si.osInfo()
в коде будет объект Promise.platform
, distro
и kernel
, которые вы пытаетесь получить.undefined
.si.cpu()
, si.currentLoad()
и т.д.undefined
будут давать NaN
.