block_user_name/拉黑.py

1275 lines
65 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import os
import re
import json
import time
import pickle
import requests
from datetime import datetime
import logging
import random
import websocket
from urllib.parse import unquote
import gzip
from protobuf.douyin import *
import execjs
import hashlib
import urllib.parse
from threading import Thread
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
session = requests.session()
'''
fkgz 关注 fkfx 分享 xbwz 未知
xbman 男 xbnv 女 quanbu 全部 wx,qq,lj,dy,tp,qt = True
wx 微信 qq qq lj 链接
dy 抖音 tp 图片 qt 其他
fsllsl 粉丝数量大于 gzllsl 关注数量大于 jrcssl 进入次数大于
fsjr 粉丝进入 gzlh 关注拉黑 dammugjz 公屏关键词
nichenggjz 昵称关键词 dqlh 地区拉黑 gxqmgjz 个性签名关键词
IPgsd ip归属地 nlqj 年龄区间 zpsldysl 作品数量大于
ktlv 开通蓝v smzh 私密账号 ktcc 开通橱窗
yszh 疑似账号 IDbmd id白名单 IDhmd id黑名单
'''
# Settings_Options = r'''
# {
# "fkgz": false, "fkfx": false, "xbman": false,
# "xbnv": false, "xbwz": false, "quanbu": false,
# "wx": false, "qq": false, "lj": false,
# "dy": false, "tp": false, "qt": false,
# "fsjr": false, "gzlh": false, "fslldy": false,
# "gzlldy": false, "jrcsdy": false, "fsllsl": 0,
# "gzllsl": 0, "jrcssl": 0, "dammugjz": "",
# "nichenggjz": "", "ktlv": false, "ktcc": false,
# "smzh": false, "yszh": false, "zpsldy": false,
# "zpsldysl": 0, "IDbmd": "", "dqlh": "",
# "IDhmd": "", "IPgsd": "", "nlqj": "",
# "gxqmgjz": ""
# }
# '''
Settings_Options = '''{"fkgz": false, "fkfx": false, "xbman": false, "xbnv": false, "xbwz": false, "quanbu": false, "wx": false, "qq": false, "lj": false, "dy": false, "tp": false, "qt": false, "fsjr": false, "gzlh": false, "fslldy": false, "gzlldy": false, "jrcsdy": false, "fsllsl": 0, "gzllsl": 0, "jrcssl": 0, "dammugjz": "", "nichenggjz": "", "ktlv": false, "ktcc": false, "smzh": false, "yszh": false, "zpsldy": false, "zpsldysl": 0, "IDbmd": "", "dqlh": "", "IDhmd": "", "IPgsd": "", "nlqj": "", "gxqmgjz": ""}'''
Settings_Options = json.loads(Settings_Options)
# 写入 拉黑_用户数据
def write_user_data(user_name, display_id, usersid, reason):
'''
usre_name:用户名称
userid:用户id
usersid:用户主页id
runtime:拉黑时间
reason:拉黑原因
'''
runtime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
user_data = {
"user_name": user_name,
"display_id": display_id,
'usersid': usersid,
"runtime": runtime,
"reason": reason
}
with open('./user_data.json', 'a', encoding='utf-8') as f:
json_str = json.dump(user_data, f, ensure_ascii=False)
f.write('\n') # 每个数据对象后添加换行符
f.close()
# 拉黑
def lahei(sec_user_id, user_id, Cookie):
# 拉黑对方需要sec_user_id和user_id
# sec_user_idMS4wLjABAAAAhZ85ZW5BVlcjvTvpTlA6rcGIr_nhpzCSS42uSENLEqE主页后面
# user_idto_uid
for __ in range(10):
try:
url = "https://www-hj.douyin.com/aweme/v1/web/user/block/?device_platform=webapp&aid=6383&channel=channel_pc_web&pc_client_type=1&pc_libra_divert=Windows&update_version_code=170400&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=2560&screen_height=1440&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=131.0.0.0&browser_online=true&engine_name=Blink&engine_version=131.0.0.0"
# payload = "block_type=1&sec_user_id=MS4wLjABAAAAhZ85ZW5BVlcjvTvpTlA6rcGIr_nhpzCSS42uSENLEqE&source=0&user_id=61163251429"
payload = f"block_type=1&sec_user_id={sec_user_id}&source=0&user_id={user_id}"
headers = {
'Connection': 'keep-alive',
'Content-Length': '110',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
'sec-ch-ua-platform': '"Windows"',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Accept': 'application/json, text/plain, */*',
'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'sec-ch-ua-mobile': '?0',
'Origin': 'https://www.douyin.com',
'Sec-Fetch-Site': 'same-site',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Dest': 'empty',
'Referer': 'https://www.douyin.com/',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cookie': Cookie
# 'Cookie': 'ttwid=1%7CU9RBkam_C1udCzD15RdVkhD45xIsm7PIoQlTltJYCTk%7C1732686970%7Cdc4ddd594048baeaa3df7dcdc967e36006df40e0cc901d457382909db2394dc0; UIFID_TEMP=c4a29131752d59acb78af076c3dbdd52744118e38e80b4b96439ef1e20799db082f1380d5cd13efd2ef3c0bf18206e4bfbe0e3610d3ab52bee57c5fcfdc2e02c97ca6e46bdd3de6f984ea807009371b5db9506690172d0a9a5cc4ef43373f876cd4bd5a4eac0347fff8889821f134cf0; hevc_supported=true; strategyABtestKey=%221732686972.739%22; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.5%7D; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; passport_csrf_token=52363725d47dd1229c220f0470e2f2d7; passport_csrf_token_default=52363725d47dd1229c220f0470e2f2d7; bd_ticket_guard_client_web_domain=2; d_ticket=935e0100ebe543aeb19fb88474608a1615f45; passport_assist_user=CkF9ZXWVA-iZbKerIKHDaEp1xcJZ5lh4uYUgNu1ymCM1HYElnwC0ln3nqAxRA8ByxW37RMx2pswZ8MEQWnOx-MGStBpKCjyc330xG_wrxyc791bEObH0B7n-lL2ZJD6OxxfDqLpVB69azowaOsHM72XIrf2i8PVqW5FEu4LZMQRDvogQhsriDRiJr9ZUIAEiAQMmaH5v; n_mh=07vLiXVhkr6Gw426Bs6p1qWtmm_l_Xu5Jlf1_2HXC3I; sso_uid_tt=f65780cd0e55de027bf9299f9b7dec53; sso_uid_tt_ss=f65780cd0e55de027bf9299f9b7dec53; toutiao_sso_user=331fa717c329a4f4f115118fe1f6f684; toutiao_sso_user_ss=331fa717c329a4f4f115118fe1f6f684; sid_ucp_sso_v1=1.0.0-KDY0MjVkYmNhNjBmMDUwYTRjYjQ2MDY1ZGQyNDZmZTMwMGNiZjg3NWYKIQir86C94o2KBBCZ6Zq6BhjvMSAMMM31iY8GOAZA9AdIBhoCbGYiIDMzMWZhNzE3YzMyOWE0ZjRmMTE1MTE4ZmUxZjZmNjg0; ssid_ucp_sso_v1=1.0.0-KDY0MjVkYmNhNjBmMDUwYTRjYjQ2MDY1ZGQyNDZmZTMwMGNiZjg3NWYKIQir86C94o2KBBCZ6Zq6BhjvMSAMMM31iY8GOAZA9AdIBhoCbGYiIDMzMWZhNzE3YzMyOWE0ZjRmMTE1MTE4ZmUxZjZmNjg0; login_time=1732687003098; passport_auth_status=0d63f05f5920f5fa86371e2c328c60e7%2C; passport_auth_status_ss=0d63f05f5920f5fa86371e2c328c60e7%2C; uid_tt=fe90a08ede420f1008382babb4a01af2; uid_tt_ss=fe90a08ede420f1008382babb4a01af2; sid_tt=27847273045ab5d1055ce9cc29a4cf90; sessionid=27847273045ab5d1055ce9cc29a4cf90; sessionid_ss=27847273045ab5d1055ce9cc29a4cf90; is_staff_user=false; publish_badge_show_info=%220%2C0%2C0%2C1732687004013%22; SelfTabRedDotControl=%5B%5D; _bd_ticket_crypt_doamin=2; _bd_ticket_crypt_cookie=388b6415a7b774ecbb771fd4e6bb8f78; __security_server_data_status=1; sid_guard=27847273045ab5d1055ce9cc29a4cf90%7C1732687005%7C5183999%7CSun%2C+26-Jan-2025+05%3A56%3A44+GMT; sid_ucp_v1=1.0.0-KDk2M2NmYmU2NjkxZTQxYTUwOGM4NzgxMmNhZmQ0YjUxZWYwODBlZmMKGwir86C94o2KBBCd6Zq6BhjvMSAMOAZA9AdIBBoCaGwiIDI3ODQ3MjczMDQ1YWI1ZDEwNTVjZTljYzI5YTRjZjkw; ssid_ucp_v1=1.0.0-KDk2M2NmYmU2NjkxZTQxYTUwOGM4NzgxMmNhZmQ0YjUxZWYwODBlZmMKGwir86C94o2KBBCd6Zq6BhjvMSAMOAZA9AdIBBoCaGwiIDI3ODQ3MjczMDQ1YWI1ZDEwNTVjZTljYzI5YTRjZjkw; store-region=cn-fj; store-region-src=uid; biz_trace_id=41025dff; is_dash_user=1; SEARCH_RESULT_LIST_TYPE=%22single%22; pwa2=%220%7C0%7C3%7C0%22; my_rd=2; live_use_vvc=%22false%22; h265ErrorNum=-1; webcast_local_quality=origin; stream_player_status_params=%22%7B%5C%22is_auto_play%5C%22%3A0%2C%5C%22is_full_screen%5C%22%3A0%2C%5C%22is_full_webscreen%5C%22%3A0%2C%5C%22is_mute%5C%22%3A0%2C%5C%22is_speed%5C%22%3A1%2C%5C%22is_visible%5C%22%3A0%7D%22; __live_version__=%221.1.2.5721%22; live_can_add_dy_2_desktop=%221%22; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A2560%2C%5C%22screen_height%5C%22%3A1440%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A28%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A0%7D%22; FOLLOW_LIVE_POINT_INFO=%22MS4wLjABAAAAcfYfvFRPvoxRdGJHhNk26Vx0J0Nf9RmuUggT6CeeVxivnBYc1nRoJTwq_N2a6dJs%2F1732723200000%2F0%2F0%2F1732697858379%22; FOLLOW_NUMBER_YELLOW_POINT_INFO=%22MS4wLjABAAAAcfYfvFRPvoxRdGJHhNk26Vx0J0Nf9RmuUggT6CeeVxivnBYc1nRoJTwq_N2a6dJs%2F1732723200000%2F0%2F1732697258380%2F0%22; bd_ticket_guard_client_data=eyJiZC10aWNrZXQtZ3VhcmQtdmVyc2lvbiI6MiwiYmQtdGlja2V0LWd1YXJkLWl0ZXJhdGlvbi12ZXJzaW9uIjoxLCJiZC10aWNrZXQtZ3VhcmQtcmVlLXB1YmxpYy1rZXkiOiJCTmRrNUtCTjlJMWk4TW15V1RVMzdxcC9aSEI4WWU2My81M0VDdFF6Nk9pWk4wRVl0K2V4M1UydFZ1bmZ4dFM0V0NxYnVTd1U0NE9HeTdHdFpPajR4STA9IiwiYmQtdGlja2V0LWd1YXJkLXdlYi12ZXJzaW9uIjoyfQ%3D%3D; home_can_add_dy_2_desktop=%221%22; WallpaperGuide=%7B%22showTime%22%3A0%2C%22closeTime%22%3A0%2C%22showCount%22%3A0%2C%22cursor1%22%3A29%2C%22cursor2%22%3A8%7D; odin_tt=1b03c18d171dadef1f2d74f0110f49f52593545553a4eef411d09c01a0fdc369f1aa8355e2dd9f85ce81034ff8c843c8; IsDouyinActive=true'
}
response = requests.request("POST", url, headers=headers, data=payload, timeout=3, verify=False)
# '{"status_code":0,"block_status":1,"extra":{"now":1732697940000,"fatal_item_ids":[],"logid":"20241127165900C4E8A38FAAFFE50C3E07"},"log_pb":{"impr_id":"20241127165900C4E8A38FAAFFE50C3E07"}}'
if '"status_code":0' in response.text:
return True
else:
# print(response.text)
return False
except Exception as e:
print('lahei', e)
return False
# 解除拉黑
def jclahei(sec_user_id, Cookie, user_id='7454438944119719433'):
'''
:param sec_user_id:
:param user_id:抖音的user_unique_id值
:param Cookie:
:return:
'''
for __ in range(10):
try:
url = "https://www.douyin.com/aweme/v1/web/user/block/?device_platform=webapp&aid=6383&channel=channel_pc_web&pc_client_type=1&pc_libra_divert=Windows&update_version_code=170400&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=2560&screen_height=1440&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=131.0.0.0&browser_online=true&engine_name=Blink&engine_version=131.0.0.0&os_name=Windows&os_version=10&cpu_core_num=28&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=0"
payload = f"block_type=0&sec_user_id={sec_user_id}&source=0&user_id={user_id}"
headers = {
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
'sec-ch-ua-platform': '"Windows"',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Accept': 'application/json, text/plain, */*',
'x-secsdk-csrf-token': 'fHFd=f24ms8IC7K0tv7Zr5yGw69vgstUyiXltzg3pxxtfaQOTRCbXlMU08taG5frPAnrKFo3FN6gXANTYVyn47qi=KY6IgaSiTYosAF939T',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Referer': f'https://www.douyin.com/user/{sec_user_id}',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
# 'Cookie': 'ttwid=1%7CKWXadMDhW9Ryw_ADwbeFK_FV9H-mbn3vFxyte2YAZL8%7C1735621839%7C2023a3817009a569d35894b430f6575ba57c352aa1c8d409409e8419fe2eeac2; UIFID_TEMP=c4a29131752d59acb78af076c3dbdd52744118e38e80b4b96439ef1e20799db02e8e7a5a86363a89fcec77e2d646615eca416b0564627981e02f280480cc7a0b5215a3f91585358e92dd2f7c4807c5002acaaeb100519902234feddc5b68b02bdfe0e29a074b2bf5645cc1afe4195533; s_v_web_id=verify_m5c0fj24_two4VH2Q_uopw_4bO1_9hhn_C0Tcq87kZcJx; hevc_supported=true; dy_swidth=2560; dy_sheight=1440; my_rd=2; fpk1=U2FsdGVkX19XIyl6qGLvr1yaDzNIntOXA6m8G57S4sifGptdOC7CTzX9RIcI5U2LTTFFHXrkPzUGHbjQ7CfRqw==; fpk2=f51bb482c660d0eeadd1f058058a2b35; bd_ticket_guard_client_web_domain=2; passport_csrf_token=8521596f974a978da1e4b354eb1d35c1; passport_csrf_token_default=8521596f974a978da1e4b354eb1d35c1; UIFID=c4a29131752d59acb78af076c3dbdd52744118e38e80b4b96439ef1e20799db02e8e7a5a86363a89fcec77e2d646615eca416b0564627981e02f280480cc7a0bed8fe6dddf462035cabdbffe88852cd4b880a1ac63ce66c05dd898d871d0d9a56122b3387b3aa1bca9b18d5e63727b923ccb09fb874d403178c3c7e258b20a2d2fd65f7e5e111c28ea1fa9ccfbeca9d86001470e9b5c68ef98f37b8469b938d87d0877f83a459825f9347573727217b7b20b2bedc1b0bbef9547713cd654f778; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%2C%22isForcePopClose%22%3A1%7D; is_dash_user=1; __ac_nonce=06775f84a00347ad53f19; __ac_signature=_02B4Z6wo00f01zRL7KAAAIDDA28o.PttSTc0a-gAAKpx60; csrf_session_id=6432c96e165f150b78c22e8447711030; passport_assist_user=Cjzgvg6j8zBZnJqRpkCuCFVCSD6GgohNh0pytKoNp5NXG8lLVmaH3x7_XmHVcBTSbN2B6zNCOQI6-gL6geAaSgo85CasOHZYo_u95TNfT5dF1YykMfnegAC-GyhVlQFvWalAh_Fm3XQuAdpHKHIKdDy5ZQZ441_9kQQZZWeXEPrc5Q0Yia_WVCABIgED7P5X0Q%3D%3D; n_mh=9-mIeuD4wZnlYrrOvfzG3MuT6aQmCUtmr8FxV8Kl8xY; sso_uid_tt=183c57659c43eeceaed318796ff7f102; sso_uid_tt_ss=183c57659c43eeceaed318796ff7f102; toutiao_sso_user=ca675dcc5f006efc313dc69f7e3e0ccb; toutiao_sso_user_ss=ca675dcc5f006efc313dc69f7e3e0ccb; sid_ucp_sso_v1=1.0.0-KGY3MDY2NWZlZjFlNTk2NDRjOTc4ZTc2YzdhOGIxNmY4YjFlYjEzMDYKHQicjOfinAIQ3vDXuwYY7zEgDDC7psTQBTgGQPQHGgJscSIgY2E2NzVkY2M1ZjAwNmVmYzMxM2RjNjlmN2UzZTBjY2I; ssid_ucp_sso_v1=1.0.0-KGY3MDY2NWZlZjFlNTk2NDRjOTc4ZTc2YzdhOGIxNmY4YjFlYjEzMDYKHQicjOfinAIQ3vDXuwYY7zEgDDC7psTQBTgGQPQHGgJscSIgY2E2NzVkY2M1ZjAwNmVmYzMxM2RjNjlmN2UzZTBjY2I; login_time=1735784542133; passport_auth_status=577638629195a1c78981dcc18eb6914d%2C; passport_auth_status_ss=577638629195a1c78981dcc18eb6914d%2C; uid_tt=be33504736d799b7e42458a52241a944; uid_tt_ss=be33504736d799b7e42458a52241a944; sid_tt=3a7970ea751f676dce010b635f8d19b1; sessionid=3a7970ea751f676dce010b635f8d19b1; sessionid_ss=3a7970ea751f676dce010b635f8d19b1; is_staff_user=false; _bd_ticket_crypt_doamin=2; _bd_ticket_crypt_cookie=c2194fa0fb2ed4598e93bbead8b2ec09; __security_server_data_status=1; publish_badge_show_info=%220%2C0%2C0%2C1735784550346%22; passport_fe_beating_status=true; sid_guard=3a7970ea751f676dce010b635f8d19b1%7C1735784552%7C5183993%7CMon%2C+03-Mar-2025+02%3A22%3A25+GMT; sid_ucp_v1=1.0.0-KGUyNWE1YzdkYjc1Zjg3ODMzZDQ4NTFjYjU4ODhlN2Y1MjI2ODkxZWEKGQicjOfinAIQ6PDXuwYY7zEgDDgGQPQHSAQaAmxxIiAzYTc5NzBlYTc1MWY2NzZkY2UwMTBiNjM1ZjhkMTliMQ; ssid_ucp_v1=1.0.0-KGUyNWE1YzdkYjc1Zjg3ODMzZDQ4NTFjYjU4ODhlN2Y1MjI2ODkxZWEKGQicjOfinAIQ6PDXuwYY7zEgDDgGQPQHSAQaAmxxIiAzYTc5NzBlYTc1MWY2NzZkY2UwMTBiNjM1ZjhkMTliMQ; FOLLOW_NUMBER_YELLOW_POINT_INFO=%22MS4wLjABAAAAHZbJJ5e8g4Lk0PIezttIs-bJdhhLb79nOZeFZVjop6o%2F1735833600000%2F1735784585664%2F1735784545513%2F0%22; SelfTabRedDotControl=%5B%5D; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.5%7D; strategyABtestKey=%221735784593.663%22; biz_trace_id=18f02cfb; store-region=cn-fj; store-region-src=uid; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A2560%2C%5C%22screen_height%5C%22%3A1440%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A28%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A0%7D%22; download_guide=%223%2F20250102%2F0%22; IsDouyinActive=true; home_can_add_dy_2_desktop=%221%22; bd_ticket_guard_client_data=eyJiZC10aWNrZXQtZ3VhcmQtdmVyc2lvbiI6MiwiYmQtdGlja2V0LWd1YXJkLWl0ZXJhdGlvbi12ZXJzaW9uIjoxLCJiZC10aWNrZXQtZ3VhcmQtcmVlLXB1YmxpYy1rZXkiOiJCSnhRZURwVm5RV2RCWHYyUDdsQkZBQ2grK3hnZW5DZElkS3pML0lqUy9aTXByVWo2ajJUQ1lxUzlxM2pqcThUbWVHR2lET3dpQkMwWnRkbDdKblB2Vnc9IiwiYmQtdGlja2V0LWd1YXJkLXdlYi12ZXJzaW9uIjoyfQ%3D%3D; odin_tt=6428f310d4802afd53a00105de9cc307b50976cb366ec2c003f57d3ad6a461b8a0bee9972f745cb565544ae3f7faab23c3376ad4c22dedbd04e5517c14b449bb'
}
response = requests.request("POST", url, headers=headers, data=payload, timeout=3, verify=False,
cookies=Cookie)
if response.status_code == 200:
if '"status_code":0' in response.text:
return True
else:
# print(response.text)
return response.text
else:
return response.status_code
except Exception as e:
print('jclahei', e)
return False
# 读取cookie
def load_cookies_from_file(filename):
# 以二进制写入模式打开文件
with open(filename, "rb") as f:
return pickle.load(f)
# 取随机ua
def zhengchang_ua(i):
# return 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42'
if i == 0:
first_num = random.randint(55, 62)
third_num = random.randint(0, 3200)
fourth_num = random.randint(0, 140)
os_type = [
"(Linux; Android 10; MI 9 Build/QKQ1.190825.002; wv)",
"(Linux; Android 8.1.0; PBCM30 Build/OPM1.171019.011; wv)",
"(Linux; Android 6.0; HUAWEI MLA-AL10 Build/HUAWEIMLA-AL10; wv)",
"(Linux; Android 6.0.1; OPPO A57t Build/MMB29M; wv)",
"(iPhone; CPU iPhone OS 10_3_3 like Mac OS X)",
"(Linux; U; Android 9; zh-cn; Redmi 7 Build/PKQ1.181021.001)",
"(Linux; Android 9; V1914A Build/PKQ1.181016.001; wv)",
"(Linux; U; Android 10; zh-CN; ALP-AL00 Build/HUAWEIALP-AL00)",
"(Linux; Android 10; VOG-TL00 Build/HUAWEIVOG-TL00; wv)",
"(Linux; Android 9; Nokia X7 Build/PPR1.180610.011; wv)",
"(Linux; Android 9.0; S5 Build/PKQ1.190319.001; wv)",
"(Linux; Android 10; PCT-AL10 Build/HUAWEIPCT-AL10; wv)",
"(Linux; Android 10; PCT-AL10 Build/HUAWEIPCT-AL10; wv)",
"(Linux; Android 9; Mi9 Pro 5G Build/PKQ1.190714.001; wv)",
"(iPhone; CPU iPhone OS 13_4 like Mac OS X)",
"(Linux; Android 10; OXF-AN00 Build/HUAWEIOXF-AN00; wv)",
"(Linux; U; Android 9; zh-cn; V1814A Build/PKQ1.180819.001)",
"(Linux; U; Android 7.0; zh-cn; Redmi Note 4X Build/NRD90M)",
"(Linux; Android 9; RMX1991 Build/PKQ1.190630.001; wv)",
"(Linux; Android 10; JNY-AL10 Build/HUAWEIJNY-AL10; wv)",
"(Linux; Android 10; ELE-AL00 Build/HUAWEIELE-AL00; wv)",
"(Linux; Android 9; RMX1991 Build/PKQ1.190630.001; wv)",
"(Linux; U; Android 10; zh-cn; MI 8 Build/QKQ1.190828.002)",
"(Linux; Android 10; VCE-AL00 Build/HUAWEIVCE-AL00; wv)",
"(Linux; Android 8.0.0; AUM-TL20 Build/HONORAUM-TL20; wv)",
"(Linux; Android 10; ALP-AL00 Build/HUAWEIALP-AL00; wv)",
"(Linux; U; Android 10; zh-cn; MI 8 SE Build/QKQ1.190828.002)",
"(Linux; Android 7.1.1; OPPO A83 Build/N6F26Q; wv)",
"(Linux; Android 10; VOG-AL10 Build/HUAWEIVOG-AL10; wv)",
"(iPhone; CPU iPhone OS 13_3_1 like Mac OS X)",
"(Linux; U; Android 10; zh-cn; MI 9 Build/QKQ1.190825.002)",
"(Linux; Android 9; INE-TL00 Build/HUAWEIINE-TL00; wv)",
"(Linux; Android 9; ONEPLUS A6000 Build/PKQ1.180716.001; wv)",
"(Linux; U; Android 9; zh-cn; Mi9 Pro 5G Build/PKQ1.190714.001)",
"(Linux; Android 8.1.0; OPPO R11 Plus Build/OPM1.171019.011; wv)",
"(Linux; Android 8.1.0; COR-AL00 Build/HUAWEICOR-AL00; wv)",
"(Linux; Android 7.1.2; M15 Build/N2G47H; wv)",
"(Linux; arm_64; Android 7.0; LG-H870DS)",
"(Linux; U; Android 9; zh-cn; MI CC9 Pro Build/PKQ1.190302.001)",
"(Linux; Android 10; SM-G9730 Build/QP1A.190711.020; wv)",
"(Linux; Android 7.1.2; Hisense A2T Build/N2G47H; wv)",
"(Linux; U; Android 8.1.0; zh-CN; 16th Plus Build/OPM1.171019.026)",
"(Linux; U; Android 9; zh-cn; MI 8 Lite Build/PKQ1.181007.001)",
"(Linux; Android 9; PAAM00 Build/PKQ1.190414.001; wv)",
"(iPhone; CPU iPhone OS 10_1_1 like Mac OS X)",
"(iPhone; CPU iPhone OS 11_4_1 like Mac OS X)",
"(Linux; Android 9; V1914A Build/PKQ1.181016.001; wv)",
"(Linux; Android 10; PCT-AL10 Build/HUAWEIPCT-AL10; wv)",
]
chrome_version = "Chrome/{}.0.{}.{}".format(first_num, third_num, fourth_num)
ua = " ".join(
[
"Mozilla/5.0",
random.choice(os_type),
"AppleWebKit/537.36",
"(KHTML, like Gecko)",
chrome_version,
"Safari/537.36",
]
)
return ua
elif i == 1:
os_type = [
"(Windows NT 6.1; WOW64)",
"(Windows NT 6.0; WOW64)",
"(Windows NT 6.2; WOW64)",
"(Windows NT 6.3; WOW64)",
"(Windows NT 5.1; WOW64)",
"(Windows NT 5.0; WOW64)",
"(Windows NT 5.2; WOW64)",
"(Windows NT 5.3; WOW64)",
"(Windows NT 10.1; WOW64)",
"(Windows NT 10.0; WOW64)",
"(Windows NT 10.2; WOW64)",
"(Windows NT 10.3; WOW64)",
"(Windows NT 6.1; WOW64; X64)",
"(Windows NT 6.0; WOW64; X64)",
"(Windows NT 6.2; WOW64; X64)",
"(Windows NT 6.3; WOW64; X64)",
"(Windows NT 5.1; WOW64; X64)",
"(Windows NT 5.0; WOW64; X64)",
"(Windows NT 5.2; WOW64; X64)",
"(Windows NT 5.3; WOW64; X64)",
"(Windows NT 10.1; WOW64; X64)",
"(Windows NT 10.0; WOW64; X64)",
"(Windows NT 10.2; WOW64; X64)",
"(Windows NT 10.3; WOW64; X64)",
"(Windows NT 6.1)",
"(Windows NT 6.0)",
"(Windows NT 6.2)",
"(Windows NT 6.3)",
"(Windows NT 5.1)",
"(Windows NT 5.0)",
"(Windows NT 5.2)",
"(Windows NT 5.3)",
"(Windows NT 10.1)",
"(Windows NT 10.0)",
"(Windows NT 10.2)",
"(Windows NT 10.3)",
]
banben = (
str(random.randint(47, 170))
+ ".0."
+ str(random.randint(2000, 2755))
+ "."
+ str(random.randint(0, 25))
)
ua = " ".join(
[
"Mozilla/5.0",
random.choice(os_type),
"AppleWebKit/537.36",
"(KHTML, like Gecko)",
"Chrome/" + banben,
"Safari/537.36",
]
)
return ua
elif i == 2:
os_type = [
"(Macintosh; U; PPC Mac OS X 10_5_8; ja-jp)",
"(Windows; U; Windows NT 6.1; cs-CZ)",
"(Windows; U; Windows NT 6.0; tr-TR)",
"(Windows; U; Windows NT 5.1; ru-RU)",
"(Windows; U; Windows NT 6.0; tr-TR)",
"(Macintosh; Intel Mac OS X 10_6_8)",
"(Windows; U; Windows NT 6.1; zh-HK)",
"(Windows; U; Windows NT 6.0; ja-JP)",
"(Windows; U; Windows NT 6.0; hu-HU)",
"(Macintosh; U; Intel Mac OS X 10_6_6; de-de)",
"(Windows; U; Windows NT 6.1; ko-KR)",
"(Macintosh; Intel Mac OS X 10_7_3)",
"(Macintosh; U; PPC Mac OS X 10_5_8; ja-jp)",
"(Windows; U; Windows NT 6.1; sv-SE)",
"(Macintosh; U; Intel Mac OS X 10_6_6; fr-ch)",
"(Windows; U; Windows NT 6.1; de-DE)",
"(Windows; U; Windows NT 6.0; de-DE)",
"(Macintosh; U; Intel Mac OS X 10_5_8; zh-cn)",
"(Macintosh; U; Intel Mac OS X 10_6_6; ja-jp)",
"(Windows; U; Windows NT 6.0; en-US)",
]
banben = (
str(random.randint(533, 534))
+ "."
+ str(random.randint(18, 21))
+ "."
+ str(random.randint(1, 27))
)
chrome_version = [
"Version/5.0.3",
"Version/5.0.4",
"Version/5.0.2",
"Version/7.0.3",
"Version/6.0 Mobile/10A5355d",
"Version/5.1.7",
"Version/5.1.6",
"Version/5.1.3",
"Version/5.1.4",
"Version/5.1.2",
"Version/5.1.3",
]
ua = " ".join(
[
"Mozilla/5.0",
random.choice(os_type),
"AppleWebKit/" + banben,
"(KHTML, like Gecko)",
random.choice(chrome_version),
"Safari/" + banben,
]
)
return ua
elif i == 3:
os_type = [
"(Windows NT 10.0; Win64; x64; rv:",
"(Windows NT 6.3; Win64; x64; rv:",
"(Windows NT 6.2; Win64; x64; rv:",
"(Windows NT 10; rv:",
"(Windows NT 6.3; rv:",
"(Windows NT 6.2; rv:",
"(Windows NT 6.1; rv:",
"(Windows NT 6.1; Win64; x64; rv:",
"(X11; Linux i586; rv:",
"(Windows NT 10.0; Win64; x64; rv:",
]
banben = str(random.randint(20, 50)) + ".0"
chrome_version = [
"Gecko/20100101 Firefox/",
"Gecko/20130405 Firefox/",
"Gecko/20130330 Firefox/",
"Gecko/20130430 Firefox/",
"Gecko/20140230 Firefox/",
"Gecko/20140630 Firefox/",
"Gecko/20140512 Firefox/",
"Gecko/20140712 Firefox/",
"Gecko/20100502 Firefox/",
]
ua = " ".join(
[
"Mozilla/5.0",
random.choice(os_type) + banben + ")",
random.choice(chrome_version) + banben,
]
)
return ua
elif i == 4:
os_type = [
"(Macintosh; U; Intel Mac OS X 10_6_7; ",
"(Macintosh; U; Intel Mac OS X 10_6_5; ",
"(Windows; U; Windows NT 6.1; ",
"(Macintosh; U; Intel Mac OS X 10_6_6; ",
"(Windows; U; Windows NT 6.0; ",
"(Windows; U; Windows NT 6.1; ",
"(Windows; U; Windows NT 5.1; ",
"(Macintosh; U; Intel Mac OS X 10_6_6; ",
"(Macintosh; U; PPC Mac OS X 10_5_8;",
"(Macintosh; U; Intel Mac OS X 10_6_7;",
"(Macintosh; U; Intel Mac OS X 10_6_5;",
"(Macintosh; U; Intel Mac OS X 10_6_6;",
]
diqu = [
"ja-jp)",
"de-de)",
"de-DE)",
"fr-ch)",
"en-US)",
"cs-CZ)",
"it-it)",
"ko-kr)",
"da-dk)",
"ar)",
"hu-HU)",
"ko-KR)",
"es-es)",
"zh-HK)",
"en-gb)",
]
banben = (
str(random.randint(532, 535))
+ "."
+ str(random.randint(19, 55))
+ "."
+ str(random.randint(1, 25))
)
ua = " ".join(
[
"Mozilla/5.0",
random.choice(os_type) + random.choice(diqu),
"AppleWebKit/" + banben,
"(KHTML, like Gecko)",
"Version/5.0." + str(random.randint(1, 5)),
"Safari/" + banben,
]
)
return ua
elif i == 5:
os_type = [
"(Windows; U; Windows NT 5.1",
"(Macintosh; U; Intel Mac OS X 10_6_6",
"(Macintosh; U; PPC Mac OS X 10_5_8",
"(Macintosh; U; Intel Mac OS X 10_6_7",
"(Macintosh; U; Intel Mac OS X 10_6_5",
"(Macintosh; U; Intel Mac OS X 10_6_6",
"(Macintosh; AMD Mac OS X 10_8_2",
"(Macintosh; Intel Mac OS X 10_10_1",
"(Macintosh; Intel Mac OS X 10_5_8",
"(Macintosh; Intel Mac OS X 10_6_0",
"(Macintosh; Intel Mac OS X 10_6_2",
"(Macintosh; Intel Mac OS X 10_6_3",
"(Macintosh; Intel Mac OS X 10_6_4",
"(Macintosh; Intel Mac OS X 10_6_5",
"(Macintosh; Intel Mac OS X 10_6_6",
"(Macintosh; Intel Mac OS X 10_6_7",
"(Macintosh; Intel Mac OS X 10_6_8",
"(Macintosh; Intel Mac OS X 10_7_0",
"(Macintosh; Intel Mac OS X 10_7_1",
"(Macintosh; Intel Mac OS X 10_7_2",
"(Macintosh; Intel Mac OS X 10_7_3",
"(Macintosh; Intel Mac OS X 10_7_4",
"(Macintosh; Intel Mac OS X 10_7_5",
"(Macintosh; Intel Mac OS X 10_8_0",
"(Macintosh; Intel Mac OS X 10_8_1",
"(Macintosh; Intel Mac OS X 10_8_2",
"(Macintosh; Intel Mac OS X 10_8_3",
"(Macintosh; Intel Mac OS X 10_9_0",
"(Macintosh; Intel Mac OS X 10_9_1",
"(Macintosh; Intel Mac OS X 10_9_2",
"(Macintosh; Intel Mac OS X 10_9_3",
"(Macintosh; PPC Mac OS X 10_6_7",
"(Macintosh; U; Intel Mac OS X 10_5_6",
"(Macintosh; U; Intel Mac OS X 10_5_7",
"(Macintosh; U; Intel Mac OS X 10_5_8",
"(Macintosh; U; Intel Mac OS X 10_5_9",
"(Macintosh; U; Intel Mac OS X 10_6_0",
"(Macintosh; U; Intel Mac OS X 10_6_1",
"(Macintosh; U; Intel Mac OS X 10_6_2",
"(Macintosh; U; Intel Mac OS X 10_6_3",
"(Macintosh; U; Intel Mac OS X 10_6_4",
"(Macintosh; U; Intel Mac OS X 10_6_5",
"(Macintosh; U; Intel Mac OS X 10_6_6",
"(Macintosh; U; Intel Mac OS X 10_6_7",
"(Macintosh; U; Intel Mac OS X 10_6_8",
"(Macintosh; U; Intel Mac OS X 10_8",
]
diqu = [
"; ja-jp)",
"; e-de)",
"; de-DE)",
"; fr-ch)",
"; en-US)",
"; cs-CZ)",
"; it-it)",
"; ko-kr)",
"; da-dk)",
"; ar)",
"; hu-HU)",
"; ko-KR)",
"; es-es)",
"; zh-HK)",
"; en-gb)",
"; id-ID)",
]
banben = (
str(random.randint(500, 535))
+ "."
+ str(random.randint(0, 55))
+ "."
+ str(random.randint(0, 25))
)
ua = " ".join(
[
"Mozilla/5.0",
random.choice(os_type) + random.choice(diqu),
"AppleWebKit/" + banben,
"(KHTML, like Gecko)",
"Version/5.0." + str(random.randint(1, 9)),
"Safari/" + banben,
]
)
return ua
else:
os_type = [
"(iPhone; U; CPU iPhone OS 4_3_1 like Mac OS X",
"(iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X",
"(iPhone; U; CPU iPhone OS 4_3 like Mac OS X",
"(iPhone; U; CPU iPhone OS 4_2_4 like Mac OS X",
"(iPhone; CPU iPhone OS 12_1_4 like Mac OS X",
"(iPhone; CPU iPhone OS 12_0 like Mac OS X",
"(iPhone; CPU iPhone OS 11_2 like Mac OS X",
"(iPhone 6s; CPU iPhone OS 11_4_1 like Mac OS X",
"(iPhone; CPU iPhone OS 10_1 like Mac OS X",
"(iPhone; CPU iPhone OS 11_0_2 like Mac OS X",
"(iPhone; CPU iPhone OS 11_4_1 like Mac OS X",
"(iPhone; CPU iPhone OS 10_1_1 like Mac OS X",
"(iPhone; CPU iPhone OS 13_5_1 like Mac OS X",
"(iPhone; CPU iPhone OS 8_3 like Mac OS X",
"(iPhone; CPU iPhone OS 14_4 like Mac OS X",
"(iPhone; CPU iPhone OS 13_6 like Mac OS X",
"(iPhone; CPU iPhone OS 14_1 like Mac OS X",
"(iPhone; CPU iPhone OS 13_6_1 like Mac OS X",
]
diqu = [
"; ja-jp)",
"; e-de)",
"; de-DE)",
"; fr-ch)",
"; en-US)",
"; cs-CZ)",
"; it-it)",
"; ko-kr)",
"; da-dk)",
"; ar)",
"; hu-HU)",
"; ko-KR)",
"; es-es)",
"; zh-HK)",
"; en-gb)",
"; id-ID)",
]
banben = (
str(random.randint(500, 535))
+ "."
+ str(random.randint(0, 55))
+ "."
+ str(random.randint(0, 25))
)
mobi = [
"Version/6.0 Mobile/10A5355d",
"Version/5.1 Mobile/9B176",
"Version/5.0.2 Mobile/8J2",
"Version/5.0.2 Mobile/8G4",
"Version/5.0.2 Mobile/8C148",
"Version/5.0.2 Mobile/8C148a",
"Version/5.0.2 Mobile/8G4",
"Version/5.0.2 Mobile/8F190",
"Version/4.0.5 Mobile/8B5097d",
"Version/4.0.5 Mobile/8B117",
"Version/4.0.4 Mobile/7B314",
"Version/4.0.4 Mobile/7B334b",
"Version/4.0.4 Mobile/7D11",
"Version/4.0.4 Mobile/7B500",
"Version/4.0.4 Mobile/7B360",
"Version/3.1.1 Mobile/5G77",
]
ua = " ".join(
[
"Mozilla/5.0",
random.choice(os_type) + random.choice(diqu),
"AppleWebKit/" + banben,
"(KHTML, like Gecko)",
random.choice(mobi),
"Safari/" + banben,
]
)
return ua
# wss链接加密 获取 signature
def generateSignature(wss):
"""
出现gbk编码问题则修改 python模块subprocess.py的源码中Popen类的__init__函数参数encoding值为 "utf-8"
"""
params = (
"live_id,aid,version_code,webcast_sdk_version,"
"room_id,sub_room_id,sub_channel_id,did_rule,"
"user_unique_id,device_platform,device_type,ac,"
"identity"
).split(",")
wss_params = urllib.parse.urlparse(wss).query.split("&")
wss_maps = {i.split("=")[0]: i.split("=")[-1] for i in wss_params}
tpl_params = [f"{i}={wss_maps.get(i, '')}" for i in params]
param = ",".join(tpl_params)
md5 = hashlib.md5()
md5.update(param.encode())
md5_param = md5.hexdigest()
# with codecs.open('D:\job_demo\demo\day04\h_sign.js', 'r', encoding='utf8') as f:
# script = f.read()
# ctx = MiniRacer()
# ctx.eval(script)
with open("h_sign.js", "r", encoding="utf-8") as f:
js_code = f.read()
ctx = execjs.compile(js_code)
try:
signature = ctx.call("get_sign", md5_param)
return signature
except Exception as e:
print(e)
# 检索关键词拉黑
def char_in_list(string, char_list):
"""
判断字符串中的某个字符是否在列表元素中
:param char: 要检查的字符
:param char_list: 字符列表
:return: 如果字符在列表中则返回True否则返回False
"""
for char in char_list.split('\n'):
if char == '':
continue
if char in string:
print(char)
return True
return False
# 查看用户主页信息
def View_user_home(uid, Cookies):
# 访问主页,获取用户信息,只有登录才能获取地区
for __ in range(10):
try:
# session = requests.Session()
# session.mount('https://www.douyin.com', DESAdapter())
url = "https://www.douyin.com/user/" + uid
headers = {
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
'User-Agent': zhengchang_ua(1),
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'cookie': Cookies
}
data = {'age': None, 'awemeCount': None, 'desc': None, 'enterpriseVerifyReason': None, 'ip': None,
'mplatformFollowersCount': None, "followingCount": None}
response = requests.get(url=url, headers=headers, timeout=1, verify=False)
# print(response.text)
rtext = response.text
if '>私密账号</p>' in rtext:
data['private'] = True
push = re.findall(f'freq_visit_msg.*secUid\\\\":\\\\"{uid}.*?redirectFrom', rtext)
if push:
ipLocation = re.findall('"ipLocation\\\\":\\\\"(.*?)\\\\"', push[0]) # IP归属地
if ipLocation:
# 未知是'$undefined'
if '$undefined' in ipLocation[0]:
data['ip'] = '未知'
else:
data['ipLocation'] = ipLocation[0].replace('IP属地', '')
country = re.findall('"country\\\\":\\\\"(.*?)\\\\"', push[0]) # 城市
province = re.findall('"province\\\\":\\\\"(.*?)\\\\"', push[0]) # 城市
city = re.findall('"city\\\\":\\\\"(.*?)\\\\"', push[0]) # 城市
# 未知是'$undefined'
if '$undefined' in country or not country:
data['country'] = '未知'
elif '$undefined' in province or not province:
data['country'] = country[0]
elif '$undefined' in city or not city:
data['country'] = country[0]
else:
data['country'] = city[0]
age = re.findall('"age\\\\":(.*?),', push[0]) # 年龄
if age:
# 未知是['null']
if 'null' in age[0] or '-1' in age[0]:
data['age'] = '未知'
else:
data['age'] = age[0]
awemeCount = re.findall('"awemeCount\\\\":(.*?),', push[0]) # 作品数量
if awemeCount:
if awemeCount[0] != '':
data['awemeCount'] = awemeCount[0]
# followingCount = re.findall('"followingCount\\\\":(.*?),', push[0]) # 关注数量
# if followingCount:
# if followingCount[0] != '':
# data['followingCount'] = followingCount[0]
mplatformFollowersCount = re.findall('"mplatformFollowersCount\\\\":(.*?),', push[0]) # 粉丝数量
if mplatformFollowersCount:
if mplatformFollowersCount[0] != '':
data['mplatformFollowersCount'] = mplatformFollowersCount[0]
desc = re.findall('"desc\\\\":\\\\"(.*?)\\\\"', push[0]) # 简介
if desc:
if desc[0] != '':
data['desc'] = desc[0]
enterpriseVerifyReason = re.findall('"enterpriseVerifyReason\\\\":\\\\"(.*?)\\\\"', push[0]) # 有内容就是蓝V
if enterpriseVerifyReason:
if enterpriseVerifyReason[0] != '':
data['enterpriseVerifyReason'] = True
return data
except Exception as e:
pass
# print('fwzy',e)
return False
# 年龄区间
def check_blacklist_age(age_dict, current_age):
"""检查当前年龄是否在拉黑的年龄段内"""
age_ranges = age_dict.get("nlqj", "")
if not age_ranges:
return False
# 处理特殊值 "未知"
if current_age == '未知':
return '-1' in age_ranges.split(',')
try:
current_age_num = int(current_age)
except ValueError:
return False # 非数字且非"未知"的年龄直接返回False
# 解析年龄段字符串
for range_str in age_ranges.split(','):
if range_str == '-1':
continue # 已在前面处理过-1
if '-' in range_str:
start, end = map(int, range_str.split('-'))
if start <= current_age_num <= end:
return True
else:
# 处理单独的年龄值
if current_age_num == int(range_str):
return True
return False
# 直播弹幕获取 拉黑 删除拉黑
class DouyinLiveWebFetcher:
def __init__(self, live_url, roomId, Cookie):
self.id_dict = {}
self.Cookies = Cookie
self.__ttwid = None
self.room_id = roomId
self.live_url = live_url
self.user_agent = zhengchang_ua(1)
# 启动
def start(self):
self._connectWebSocket()
# 结束
def stop(self):
if hasattr(self, 'ws'):
self.ws.close()
def _connectWebSocket(self):
"""
连接抖音直播间websocket服务器请求直播间数据
"""
wss = (
"wss://webcast5-ws-web-hl.douyin.com/webcast/im/push/v2/?app_name=douyin_web"
"&version_code=180800&webcast_sdk_version=1.0.14-beta.0"
"&update_version_code=1.0.14-beta.0&compress=gzip&device_platform=web&cookie_enabled=true"
"&screen_width=1536&screen_height=864&browser_language=zh-CN&browser_platform=Win32"
"&browser_name=Mozilla"
"&browser_version=5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,"
"%20like%20Gecko)%20Chrome/126.0.0.0%20Safari/537.36"
"&browser_online=true&tz_name=Asia/Shanghai"
"&cursor=d-1_u-1_fh-7392091211001140287_t-1721106114633_r-1"
f"&internal_ext=internal_src:dim|wss_push_room_id:{self.room_id}|wss_push_did:7319483754668557238"
f"|first_req_ms:1721106114541|fetch_time:1721106114633|seq:1|wss_info:0-1721106114633-0-0|"
f"wrds_v:7392094459690748497"
f"&host=https://live.douyin.com&aid=6383&live_id=1&did_rule=3&endpoint=live_pc&support_wrds=1"
f"&user_unique_id=7319483754668557238&im_path=/webcast/im/fetch/&identity=audience"
f"&need_persist_msg_count=15&insert_task_id=&live_reason=&room_id={self.room_id}&heartbeatDuration=0"
)
signature = generateSignature(wss)
wss += f"&signature={signature}"
headers = {
"cookie": f"ttwid={self.ttwid}",
"user-agent": self.user_agent,
}
self.ws = websocket.WebSocketApp(
wss,
header=headers,
on_open=self._wsOnOpen,
on_message=self._wsOnMessage,
on_error=self._wsOnError,
on_close=self._wsOnClose,
)
# 运行websocket连接并处理可能的异常
try:
self.ws.run_forever()
except websocket.WebSocketConnectionClosedException as e:
logging.error("_connectWebSocket--WebSocket连接已关闭: %s", e)
self.stop()
except websocket.WebSocketException as e:
logging.error("_connectWebSocket--WebSocket异常: %s", e)
self.stop()
except Exception as e:
logging.error("_connectWebSocket--发生未知异常: %s", e)
self.stop()
raise # 重新抛出异常,以便上层处理
def _wsOnOpen(self, ws):
"""
连接建立成功
"""
logging.info(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----直播间链接成功"
)
def heartbeat(ws: websocket.WebSocketApp):
"""发送心跳消息的定时任务"""
while True:
if ws.keep_running: # 检查WebSocket连接是否仍在运行
ws.send("hi") # 发送自定义的心跳消息
time.sleep(15) # 等待指定的时间间隔
else:
break
heartbeat_thread = Thread(target=heartbeat, args=(ws,))
heartbeat_thread.daemon = True # 设置为守护线程
heartbeat_thread.start()
def _wsOnMessage(self, ws: websocket.WebSocketApp, message: str):
"""
接收到数据
:param ws: websocket实例
:param message: 数据
"""
# while True:
# 根据proto结构体解析对象
if message:
try:
package = PushFrame().parse(message)
response = Response().parse(gzip.decompress(package.payload))
# 返回直播间服务器链接存活确认消息,便于持续获取数据
if response.need_ack:
ack = PushFrame(
log_id=package.log_id,
payload_type="ack",
payload=response.internal_ext.encode("utf-8"),
).SerializeToString()
ws.send(ack, websocket.ABNF.OPCODE_BINARY)
# 根据消息类别解析消息体
for msg in response.messages_list:
method = msg.method
try:
{
"WebcastChatMessage": self._parseChatMsg, # 聊天消息
"WebcastGiftMessage": self._parseGiftMsg, # 礼物消息
"WebcastLikeMessage": self._parseLikeMsg, # 点赞消息
"WebcastMemberMessage": self._parseMemberMsg, # 进入直播间消息
"WebcastSocialMessage": self._parseSocialMsg, # 关注消息
"WebcastRoomUserSeqMessage": self._parseRoomUserSeqMsg, # 直播间统计
"WebcastFansclubMessage": self._parseFansclubMsg, # 粉丝团消息
"WebcastControlMessage": self._parseControlMsg, # 直播间状态消息
"WebcastEmojiChatMessage": self._parseEmojiChatMsg, # 聊天表情包消息
"WebcastRoomStatsMessage": self._parseRoomStatsMsg, # 直播间统计信息
"WebcastRoomMessage": self._parseRoomMsg, # 直播间信息
"WebcastRoomRankMessage": self._parseRankMsg, # 直播间排行榜信息
}.get(method)(msg.payload)
except Exception as e:
pass
# logging.error(f"_wsOnMessage--error occurred: {e}")
except Exception as e:
logging.error(f"_wsOnMessage--error occurred: {e}")
def _wsOnError(self, ws, error):
# print("WebSocket error: ", error)
logging.info("WebSocket error: ", error)
def _wsOnClose(self, ws: websocket.WebSocketApp, *args):
logging.info(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----直播间断开")
# 聊天消息 拉黑功能需要实现 已实现 待测试
def _parseChatMsg(self, payload):
"""聊天消息"""
message = ChatMessage().parse(payload)
user_name = message.user.nick_name # 用户名称
user_id = message.user.id # 用户id
user_sid = message.user.sec_uid # 用户主页uid
display_id = message.user.display_id # 用户抖音ID
content = message.content # 用户发送的信息
print(
f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【聊天msg】- 用户名称:{user_name} - 用户id:{user_id} - 用户主页uid:{user_sid} - 用户抖音ID:{display_id} - 用户发送的信息:{content}"
)
if Settings_Options.get('dammugjz'):
if char_in_list(content, Settings_Options.get('dammugjz')):
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:该用户弹幕存在违规词")
write_user_data(user_name, user_id,user_sid, "该用户弹幕存在违规词")
def _parseGiftMsg(self, payload):
"""礼物消息"""
message = GiftMessage().parse(payload)
user_name = message.user.nick_name # 用户名称
gift_name = message.gift.name # 礼物信息
gift_cnt = message.combo_count # 礼物数量
print(
f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【礼物msg】-{user_name} - 送出了 {gift_name}x{gift_cnt}")
def _parseLikeMsg(self, payload):
"""点赞消息"""
message = LikeMessage().parse(payload)
user_name = message.user.nick_name # 用户名称
count = message.count # 点赞次数
print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【点赞msg】- {user_name} - 点了{count}个赞")
# 进入直播间信息 拉黑功能需要实现 已实现 待测试
def _parseMemberMsg(self, payload):
"""进入直播间信息"""
message = MemberMessage().parse(payload)
following_coun = message.user.follow_info.following_count # 用户关注数
follower_count = message.user.follow_info.follower_count # 用户粉丝数
user_name = message.user.nick_name # 用户名称
user_sid = message.user.sec_uid # 用户主页uid
user_id = message.user.id # 用户id
display_id = message.user.display_id # 用户抖音ID
gender = ['未知', "", ""][message.user.gender] # 用户性别 0未知 1男 2
# if 'ducking' in user_name:
# print(message)
# input(11111)
print(
f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【进场msg】- 用户名称:{user_name} - 用户id:{user_id} - 用户uid:{user_sid} - 性别:{gender} 进入了直播间"
)
# ID 白名单
if Settings_Options.get('IDbmd'):
if display_id in Settings_Options.get('IDbmd'):
print(f'{display_id}存在白名单中 跳过检查')
return
# ID 黑名单
if Settings_Options.get('IDhmd'):
if display_id in Settings_Options.get('IDhmd'):
print(f'{display_id}存在黑名单中 拉黑')
lahei(user_sid, user_id, self.Cookies)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:存在黑名单中")
write_user_data(user_name, display_id, user_sid, '黑名单')
return
rcfs = message.anchor_display_text.default_patter.replace('{0:user}', '').replace('{1:string} ', '关注')
if 'ducking' in user_name or '蛋仔' in user_name:
print('message.anchor_display_text',message.anchor_display_text)
print('message.anchor_display_text.default_patter',message.anchor_display_text.default_patter)
print(rcfs)
print('message.user', message.user)
input(1111)
# 统计用户进入次数
if display_id in self.id_dict:
self.id_dict[display_id] += 1
else:
self.id_dict[display_id] = 1
enter_sum = self.id_dict[display_id]
# 通过分享进入直播间 // 偶尔触发 人少的直播间可以
if '分享' in rcfs:
if Settings_Options.get('fkfx'):
print(f'通过分享进入直播间')
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:通过分享进入直播间")
write_user_data(user_name, display_id, user_sid, '分享进入直播间')
# 通过关注进入直播间 // 触发不了
if '关注' in rcfs:
if Settings_Options.get('fkgz'):
print(f'通过关注进入直播间')
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:通过关注进入直播间")
write_user_data(user_name, display_id, user_sid, '关注进入直播间')
# 性别未知 拉黑
if Settings_Options.get('xbwz') and gender == '未知':
lahei(user_sid, user_id, self.Cookies)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:未知性别")
write_user_data(user_name, display_id, user_sid, '未知性别')
# 性别男 拉黑
if Settings_Options.get('xbman') and gender == '':
lahei(user_sid, user_id, self.Cookies)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:男")
write_user_data(user_name, display_id, user_sid, '')
# 性别女 拉黑
if Settings_Options.get('xbmw') and gender == '':
lahei(user_sid, user_id, self.Cookies)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:女")
write_user_data(user_name, display_id, user_sid, '')
# 粉丝数量大于 拉黑
if Settings_Options.get('fsllsl'):
if int(follower_count) > int(Settings_Options.get('fsllsl')):
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:粉丝数量大于设置的值{Settings_Options.get('fsllsl')}")
write_user_data(user_name, display_id, user_sid,
f'粉丝数量大于设置的值{Settings_Options.get('fsllsl')}')
# 关注数量大于 拉黑
if Settings_Options.get('gzllsl'):
if int(following_coun) > int(Settings_Options.get('gzllsl')):
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:关注数量大于设置的值{Settings_Options.get('gzllsl')}")
write_user_data(user_name, display_id, user_sid,
f'关注数量大于设置的值{Settings_Options.get('gzllsl')}')
# 进入次数大于 拉黑
if Settings_Options.get('jrcssl'):
if int(enter_sum) > int(Settings_Options.get('jrcssl')):
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:进入次数大于设置的值{Settings_Options.get('jrcssl')}")
write_user_data(user_name, display_id, user_sid,
f'进入次数大于设置的值{Settings_Options.get('jrcssl')}')
# 昵称关键词 拉黑
if Settings_Options.get('nichenggjz'):
if char_in_list(user_name, Settings_Options.get('nichenggjz')):
lahei(user_sid, user_id, self.Cookies)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:昵称存在违规词")
write_user_data(user_name, display_id, user_sid, '昵称存在违规词')
# 访问用户主页
if Settings_Options.get('dqlh') or Settings_Options.get('gxqmgjz') or Settings_Options.get(
'IPgsd') or Settings_Options.get('nlqj') or Settings_Options.get('zpsldysl') or Settings_Options.get(
'ktlv') or Settings_Options.get('smzh') or Settings_Options.get('ktcc'):
user_data = View_user_home(user_sid, self.Cookies)
# 地区 拉黑
if Settings_Options.get('dqlh') and user_data.get('country'):
if char_in_list(user_data.get('country', ''), Settings_Options.get('dqlh')):
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:地区存在违规词")
write_user_data(user_name, display_id, user_sid, '地区存在违规词')
# 个性签名 拉黑
if Settings_Options.get('gxqmgjz') and user_data.get('desc'):
if char_in_list(user_data.get('desc', ''), Settings_Options.get('gxqmgjz')):
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:个性签名存在违规词")
write_user_data(user_name, display_id, user_sid, '个性签名存在违规词')
# IP归属地 拉黑
if Settings_Options.get('IPgsd') and user_data.get('ipLocation'):
if char_in_list(user_data.get('country', ''), Settings_Options.get('IPgsd')):
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:IP归属地存在违规词")
write_user_data(user_name, display_id, user_sid, 'IP归属地存在违规词')
# 年龄区间 拉黑
if Settings_Options.get('nlqj') and user_data.get('age'):
if check_blacklist_age(Settings_Options.get('nlqj'), user_data.get('age', '')):
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:年龄区间存在违规词")
write_user_data(user_name, display_id, user_sid, '年龄区间存在违规词')
# 作品数量大于 拉黑
if Settings_Options.get('zpsldysl') and user_data.get('awemeCount'):
if int(user_data.get('awemeCount', '')) > int(Settings_Options.get('zpsldysl')):
lahei(user_sid, user_id, self.Cookies)
print(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:作品数量大于设置的值{Settings_Options.get('zpsldysl')}")
write_user_data(user_name, display_id, user_sid,
f'作品数量大于设置的值{Settings_Options.get("zpsldysl")}')
# 开通蓝v 拉黑
if Settings_Options.get('ktlv') and user_data.get('enterpriseVerifyReason'):
lahei(user_sid, user_id, self.Cookies)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:开通蓝v")
write_user_data(user_name, display_id, user_sid, '开通蓝v')
# 私密账号 拉黑
if Settings_Options.get('smzh') and user_data.get('private'):
lahei(user_sid, user_id, self.Cookies)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:私密账号")
write_user_data(user_name, display_id, user_sid, '私密账号')
# 开通橱窗 拉黑 // 没有相关参数
# 疑似账号 拉黑 // 不做
# 关注 分享消息 拉黑功能需要实现 已实现 待测试
def _parseSocialMsg(self, payload):
"""关注 分享消息"""
message = SocialMessage().parse(payload)
user_name = message.user.nick_name # 用户名称
user_sid = message.user.sec_uid # 用户主页uid
user_id = message.user.id # 用户id
display_id = message.user.display_id # 用户抖音ID
print(f'message.follow_count-->{message.follow_count}')
if 'ducking' in user_name or '蛋仔' in user_name:
print('message.user', message.user)
input(1111)
# 分享 拉黑 // 无法确认社交媒体
if message.follow_count == 0:
print(
f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【分享msg】- 用户名称:{user_name} - 用户id:{user_id} 分享了主播")
if Settings_Options.get("quanbu") or Settings_Options.get("wx") or Settings_Options.get(
"qq") or Settings_Options.get("lj") or Settings_Options.get(
"dy") or Settings_Options.get("tp") or Settings_Options.get("qt"):
lahei(user_sid, user_id, self.Cookies)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:分享了直播间")
write_user_data(user_name, display_id, user_sid, '分享了直播间')
# 关注 拉黑
else:
print(
f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【关注msg】- 用户名称:{user_name} - 用户id:{user_id} 关注了主播")
if Settings_Options.get("gzlh"):
lahei(user_sid, user_id, self.Cookies)
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功:原因:关注了主播")
write_user_data(user_name, display_id, user_sid, '关注了主播')
def _parseRoomUserSeqMsg(self, payload):
"""直播间统计"""
message = RoomUserSeqMessage().parse(payload)
current = message.total # 当前观看人数
total = message.total_pv_for_anchor # 累计观看人数
print(
f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【统计msg】- 当前观看人数: {current} - 累计观看人数: {total}")
def _parseFansclubMsg(self, payload):
"""粉丝团消息"""
message = FansclubMessage().parse(payload)
content = message.content # 内容
print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【粉丝团msg】 {content}")
def _parseControlMsg(self, payload):
"""直播间状态消息"""
message = ControlMessage().parse(payload)
if message.status == 3:
print("直播间已结束")
print(f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}----直播间已结束')
self.stop()
def _parseEmojiChatMsg(self, payload):
"""聊天表情包消息"""
message = EmojiChatMessage().parse(payload)
emoji_id = message.emoji_id # 表情包id
user = message.user # 用户
common = message.common # 通用信息
default_content = message.default_content # 默认内容
print(
f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【聊天表情包id】- {emoji_id} - user{user} - common:{common} - default_content:{default_content}"
)
def _parseRoomStatsMsg(self, payload):
"""直播间统计msg"""
message = RoomStatsMessage().parse(payload)
display_long = message.display_long # 直播间统计信息
print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【直播间统计msg】- {display_long}")
def _parseRoomMsg(self, payload):
"""直播间msg"""
message = RoomMessage().parse(payload)
common = message.common
room_id = common.room_id # 直播间id
print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【直播间msg】- 直播间id:{room_id}")
def _parseRankMsg(self, payload):
"""直播间排行榜msg"""
message = RoomRankMessage().parse(payload)
ranks_list = message.ranks_list
print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【直播间排行榜msg】{ranks_list}")
@property
def ttwid(self):
"""
产生请求头部cookie中的ttwid字段访问抖音网页版直播间首页可以获取到响应cookie中的ttwid
:return: ttwid
"""
if self.__ttwid:
return self.__ttwid
headers = {
"User-Agent": self.user_agent,
}
try:
response = requests.get(
"https://live.douyin.com/", headers=headers, verify=False
)
response.raise_for_status()
except Exception as e:
logging.error(f"ttwid--error occurred: {e}")
else:
self.__ttwid = response.cookies.get("ttwid")
return self.__ttwid
if __name__ == "__main__":
if not os.path.exists('./user_data.json'):
open('./user_data.json', 'w', encoding='utf-8').close()
user_name = ""
with open(r"D:\job_demo\demo\测试\cookie_name.txt", "r", encoding="utf-8") as f:
user_name = f.read().split("|")[1].strip()
Cookie = load_cookies_from_file(
r"D:\job_demo\demo\测试\MS4wLjABAAAAc9m4vmspNsSiYP348XRC-OLVqSXRn8Rdtl618fbzYag.pkl"
)
# print(Cookie)
# print(type(Cookie))
cookies_dict = {c.name: c.value for c in Cookie}
cookie_str = "; ".join(f"{k}={v}" for k, v in cookies_dict.items())
# 账号的直播链接
# live_url = 'https://live.douyin.com/699830573874'
# roomId = '7502733944979360566'
live_url = 'https://live.douyin.com/873443295598'
roomId = '7502723859737955113'
DouyinLiveWebFetcher(live_url, roomId, cookie_str).start()