def __init__(self, dict_user: dict, task_ctrl: dict, task_arrangement: dict, dict_bili: dict, force_sleep: Callable): self.id = dict_user['id'] self.force_sleep = force_sleep self.name = dict_user['username'] self.password = dict_user['password'] self.alias = dict_user.get('alias', self.name) self.task_ctrl = task_ctrl self.task_arrangement = task_arrangement self.is_in_jail = False # 是否小黑屋 self.bililive_session = WebSession() self.login_session = WebSession() self.other_session = WebSession() # 每个user里面都分享了同一个dict,必须要隔离,否则更新cookie这些的时候会互相覆盖 self.pc = PcPlatform(dict_bili['pc_headers'].copy()) self.app = AppPlatform(dict_bili['app_headers'].copy(), dict_bili['app_params']) self.tv = TvPlatform(dict_bili['tv_headers'].copy(), dict_bili['tv_params']) self.dict_user = dict_user self.update_login_data(dict_user) self._waiting_login = None self._loop = asyncio.get_event_loop() self.repost_del_lock = asyncio.Lock( ) # 在follow与unfollow过程中必须保证安全(repost和del整个过程加锁) dyn_lottery_friends = [ (str(uid), name) for uid, name in task_ctrl['dyn_lottery_friends'].items() ] self.dyn_lottery_friends = dyn_lottery_friends # list (uid, name)
def __init__( self, dict_user: dict, task_ctrl: dict, task_arrangement: dict, dict_bili: dict, force_sleep: callable): self.id = next(self._ids) self.force_sleep = force_sleep self.name = dict_user['username'] self.password = dict_user['password'] self.alias = dict_user.get('alias', self.name) self.task_ctrl = task_ctrl self.task_arrangement = task_arrangement self.is_log_in = True # 登陆状态,cookie、token有效性 self.is_in_jail = False # 是否小黑屋 self.bililive_session = WebSession() self.login_session = WebSession() self.other_session = WebSession() # 每个user里面都分享了同一个dict,必须要隔离,否则更新cookie这些的时候会互相覆盖 self.dict_bili = copy.deepcopy(dict_bili) self.app_params = f'actionKey={dict_bili["actionKey"]}&' \ f'appkey={dict_bili["appkey"]}&build={dict_bili["build"]}&' \ f'device={dict_bili["device"]}&mobi_app={dict_bili["mobi_app"]}&' \ f'platform={dict_bili["platform"]}' self.update_login_data(dict_user) self.list_delay = [] self.repost_del_lock = asyncio.Lock() # 在follow与unfollow过程中必须保证安全(repost和del整个过程加锁) dyn_lottery_friends = [(str(uid), name) for uid, name in task_ctrl['dyn_lottery_friends'].items()] self.dyn_lottery_friends = dyn_lottery_friends # list (uid, name) self.storm_lock = asyncio.Semaphore(1) # 用于控制同时进行的风暴数目(注意是单个用户的) self.recording_tasks = {}
def __init__(self, dict_user: dict, task_ctrl: dict, task_arrangement: dict, dict_bili: dict, force_sleep: Callable): self.id = next(self._ids) self.force_sleep = force_sleep self.name = dict_user['username'] self.password = dict_user['password'] self.alias = dict_user.get('alias', self.name) self.manage_room = dict_user['manage_room'] self.alerts = dict_user['alerts'] self.gift_comb_delay = dict_user['gift_comb_delay'] self.alert_second = dict_user['alert_second'] self.gift_thx_format = dict_user['gift_thx_format'] self.focus_thx_format = dict_user['focus_thx_format'] self.danmu_length = dict_user.get('danmu_length', 30) self.medal_update_format = dict_user.get('medal_update_format', '') self.medal_update_check_delay = dict_user.get( 'medal_update_check_delay', 30) self.random_list_1 = dict_user.get('random_list_1', []) self.random_list_2 = dict_user.get('random_list_2', []) self.random_list_3 = dict_user.get('random_list_3', []) if len(self.random_list_1) == 0: self.random_list_1 = [""] if len(self.random_list_2) == 0: self.random_list_2 = [""] if len(self.random_list_3) == 0: self.random_list_3 = [""] self.task_ctrl = task_ctrl self.task_arrangement = task_arrangement self.is_in_jail = False # 是否小黑屋 self.bililive_session = WebSession() self.login_session = WebSession() self.other_session = WebSession() # 每个user里面都分享了同一个dict,必须要隔离,否则更新cookie这些的时候会互相覆盖 self.dict_bili = copy.deepcopy(dict_bili) self.app_params = { 'actionKey': dict_bili['actionKey'], 'appkey': dict_bili['appkey'], 'build': dict_bili['build'], 'device': dict_bili['device'], 'mobi_app': dict_bili['mobi_app'], 'platform': dict_bili['platform'], } self.update_login_data(dict_user) self._waiting_login = None self._loop = asyncio.get_event_loop() self.repost_del_lock = asyncio.Lock( ) # 在follow与unfollow过程中必须保证安全(repost和del整个过程加锁) dyn_lottery_friends = [ (str(uid), name) for uid, name in task_ctrl['dyn_lottery_friends'].items() ] self.dyn_lottery_friends = dyn_lottery_friends # list (uid, name) self.storm_lock = asyncio.Semaphore(1) # 用于控制同时进行的风暴数目(注意是单个用户的)
def __init__(self): dict_user = utils.get_1st_user('client_core/conf/user.toml') dict_bili = utils.get_dict_bili('client_core/conf/bili.toml') self.user = utils.new_user(dict_user, dict_bili) self.name = self.user.name self.password = self.user.password self.__web_session = WebSession()
def __init__(self, executable_path=None, no_selenium=False): if no_selenium: self.driver = None else: options = webdriver.ChromeOptions() options.add_argument("--log-level=3") options.add_argument("--window-size=350,560") self.driver = webdriver.Chrome(executable_path, options=options) self.session = WebSession()
class Bili: def __init__(self): dict_user = utils.get_1st_user('client_core/conf/user.toml') dict_bili = utils.get_dict_bili('client_core/conf/bili.toml') self.user = utils.new_user(dict_user, dict_bili) self.name = self.user.name self.password = self.user.password self.__web_session = WebSession() def get_key(self): url = f'https://passport.bilibili.com/api/oauth2/getKey' params = self.user.sort_and_sign() json_rsp = self.__web_session.request_json( 'POST', url, headers=self.user.dict_bili['appheaders'], params=params) data = json_rsp['data'] pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(data['key']) _hash = data['hash'] crypto_password = base64.b64encode( rsa.encrypt((_hash + self.password).encode('utf-8'), pubkey) ) url_password = parse.quote_plus(crypto_password) url_name = parse.quote_plus(self.name) return url_password, url_name def login(self, url_password, url_name, seccode, challenge, validate): extra_params = [ # f'captcha=', f'password={url_password}', f'username={url_name}', f'ts={utils.curr_time()}', f'seccode={"" if not seccode else parse.quote_plus(seccode)}', f'challenge={"" if not challenge else parse.quote_plus(challenge)}', f'validate={"" if not validate else parse.quote_plus(validate)}', ] params = self.user.sort_and_sign(extra_params) print(params) url = 'https://passport.bilibili.com/api/v3/oauth2/login' json_rsp = self.__web_session.request_json( 'POST', url, headers=self.user.dict_bili['appheaders'], params=params) print(json_rsp) if json_rsp['code'] == -105: url = json_rsp['data']['url'] return url raise Exception('get_captcha', json_rsp)
class CrackClient: def __init__(self, url): self.__web_session = WebSession() self.__url = url def request_crack(self, url): data = { 'url': url, } json_rsp = self.__web_session.request_json('POST', f'{self.__url}/crack', json=data) return json_rsp
def __init__(self, dict_user: dict, task_ctrl: dict, task_arrangement: dict, dict_bili: dict, dict_bilitv: dict, force_sleep: Callable): self.id = next(self._ids) self.force_sleep = force_sleep self.name = dict_user['username'] self.password = dict_user['password'] self.alias = dict_user.get('alias', self.name) self.task_ctrl = task_ctrl self.task_arrangement = task_arrangement self.is_in_jail = False # 是否小黑屋 self.bililive_session = WebSession() self.login_session = WebSession() self.other_session = WebSession() # 每个user里面都分享了同一个dict,必须要隔离,否则更新cookie这些的时候会互相覆盖 self.dict_bili = copy.deepcopy(dict_bili) self.dict_bilitv = copy.deepcopy(dict_bilitv) self.app_params = { 'actionKey': dict_bili['actionKey'], 'appkey': dict_bili['appkey'], 'build': dict_bili['build'], 'device': dict_bili['device'], 'mobi_app': dict_bili['mobi_app'], 'platform': dict_bili['platform'], } self.update_login_data(dict_user) self._waiting_login = None self._loop = asyncio.get_event_loop() self.repost_del_lock = asyncio.Lock( ) # 在follow与unfollow过程中必须保证安全(repost和del整个过程加锁) dyn_lottery_friends = [ (str(uid), name) for uid, name in task_ctrl['dyn_lottery_friends'].items() ] self.dyn_lottery_friends = dyn_lottery_friends # list (uid, name)
def __init__(self, dict_user: dict, dict_bili: dict): self.id = next(self._ids) self.name = dict_user['username'] self.password = dict_user['password'] self.alias = dict_user.get('alias', self.name) self.bililive_session = WebSession() self.login_session = WebSession() self.other_session = WebSession() # 每个user里面都分享了同一个dict,必须要隔离,否则更新cookie这些的时候会互相覆盖 self.dict_bili = copy.deepcopy(dict_bili) self.app_params = [ f'actionKey={dict_bili["actionKey"]}', f'appkey={dict_bili["appkey"]}', f'build={dict_bili["build"]}', f'device={dict_bili["device"]}', f'mobi_app={dict_bili["mobi_app"]}', f'platform={dict_bili["platform"]}', ] self.update_login_data(dict_user) self._waiting_login = None self._loop = asyncio.get_event_loop()
def other_session(self): if self._other_session is None: self._other_session = WebSession() return self._other_session
def login_session(self): if self._login_session is None: self._login_session = WebSession() # print('测试session') return self._login_session
def bililive_session(self): if self._bililive_session is None: self._bililive_session = WebSession() return self._bililive_session
def __init__(self, url): self.__web_session = WebSession() self.__url = url
class Cracker: DELAY = 5 CSS_SELECTOR_FULLBG_IMG = 'svg > defs > g[id=gt_fullbg_1] > g > image' CSS_SELECTOR_BG_IMG = 'svg > defs > g[id = gt_bg_1] > g > image' CSS_SELECTOR_GAP_IMG = 'a[target=_blank] > image' def __init__(self, executable_path=None, no_selenium=False): if no_selenium: self.driver = None else: options = webdriver.ChromeOptions() options.add_argument("--log-level=3") options.add_argument("--window-size=350,560") self.driver = webdriver.Chrome(executable_path, options=options) self.session = WebSession() def download_img(self, img_url: str) -> np.ndarray: content = self.session.request_binary('GET', img_url) arr = np.asarray(bytearray(content), dtype=np.uint8) return cv2.imdecode(arr, cv2.IMREAD_UNCHANGED) # 'Load it as it is' @staticmethod def reorder_img(unordered_img: np.ndarray) -> np.ndarray: reordered_img = np.zeros( (unordered_img.shape[0], 260, *unordered_img.shape[2:]), np.uint8) x_upper = 0 x_lower = 0 height = unordered_img.shape[0] for x, y in reorder_list: # assert y in (-58, 0) if y == -58: reordered_img[0: height // 2, x_upper: x_upper + 10] = \ unordered_img[height // 2: height, abs(x): abs(x) + 10] x_upper += 10 else: reordered_img[height // 2: height, x_lower: x_lower + 10] = \ unordered_img[0: height // 2, abs(x): abs(x) + 10] x_lower += 10 return reordered_img def load_url(self, url=None) -> int: if url is not None: self.driver.get(url) try: WebDriverWait(self.driver, self.DELAY).until( EC.presence_of_element_located(( By.CSS_SELECTOR, f'{self.CSS_SELECTOR_FULLBG_IMG}, div[class=error-box] span[class]' )), ) if not self.driver.find_elements_by_css_selector( self.CSS_SELECTOR_FULLBG_IMG): print("页面异常,即将自动重新刷新") return 1 WebDriverWait(self.driver, self.DELAY).until( EC.presence_of_element_located( (By.CSS_SELECTOR, self.CSS_SELECTOR_BG_IMG))) print("页面正常加载完毕") return 0 except TimeoutException: print("页面超时") return -1 def refresh(self): self.driver.find_element_by_css_selector( 'div[class=error-box] span[class]').click() def fetch_imgs(self) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: unordered_fullbg_img = self.download_img( self.driver.find_element_by_css_selector( self.CSS_SELECTOR_FULLBG_IMG).get_attribute('href')) unordered_bg_img = self.download_img( self.driver.find_element_by_css_selector( self.CSS_SELECTOR_BG_IMG).get_attribute('href')) gap_img = self.download_img( self.driver.find_element_by_css_selector( self.CSS_SELECTOR_GAP_IMG).get_attribute('href')) reordered_fullbg_img = self.reorder_img(unordered_fullbg_img) reordered_bg_img = self.reorder_img(unordered_bg_img) # cv2.imshow('reordered_fullbg_img', reordered_fullbg_img) # cv2.imshow('reordered_bg_img', reordered_bg_img) # cv2.imshow('gap_img', gap_img) # cv2.waitKey() # cv2.imwrite('img/reordered_fullbg_img.png', reordered_fullbg_img) # cv2.imwrite('img/reordered_bg_img.png', reordered_bg_img) # cv2.imwrite('img/gap_img.png', gap_img) return reordered_fullbg_img, reordered_bg_img, gap_img def position2actual_distance(self, reordered_bg_img: np.ndarray) -> float: # 进度条 element = self.driver.find_element_by_css_selector( 'svg > g:last-child') # https://stackoverflow.com/questions/51996121/screenshot-an-element-with-python-selenium-shows-image-of-wrong-section-of-scree # 但我测试发现:get_screenshot_as_png 与 the actual window size 的宽度比例始终为 1.0,应该修复了。在此仅作为日志 ratio = element.rect['width'] / reordered_bg_img.shape[1] return ratio def slide_slider(self, track, ratio): element = self.driver.find_element_by_css_selector( 'svg > g > g[transform][style]') ActionChains(self.driver).click_and_hold(element).perform() assert (track[1][0], track[1][1], track[1][2]) == (0, 0, 0) real_track = [(int(x * ratio), y) for x, y, _ in track] actions = ActionChains(self.driver) for i in range(2, len(real_track), 1): actions.move_by_offset( xoffset=(real_track[i][0] - real_track[i - 1][0]), yoffset=(real_track[i][1] - real_track[i - 1][1])) actions.perform() time.sleep(0.6) ActionChains(self.driver).release().perform() def test_slide_slider(self, distance, ratio): element = self.driver.find_element_by_css_selector( 'svg > g > g[transform][style]') ActionChains(self.driver).click_and_hold(element).perform() ActionChains(self.driver). \ move_by_offset(xoffset=(distance * ratio), yoffset=0). \ perform() time.sleep(1.0) ActionChains(self.driver).release().perform() def get_result(self): try: # geetest_seccode geetest_challenge geetest_validate WebDriverWait(self.driver, self.DELAY).until( EC.presence_of_element_located( (By.CSS_SELECTOR, '[class=geetest_challenge][value]')), ) element = self.driver.find_element_by_css_selector( '[class=geetest_seccode][value]') geetest_seccode = element.get_attribute('value') element = self.driver.find_element_by_css_selector( '[class=geetest_challenge][value]') geetest_challenge = element.get_attribute('value') element = self.driver.find_element_by_css_selector( '[class=geetest_validate][value]') geetest_validate = element.get_attribute('value') return geetest_seccode, geetest_challenge, geetest_validate except TimeoutException: print("FAILED") return None, None, None
def __init__(self, dict_user: dict, task_ctrl: dict, task_arrangement: dict, dict_bili: dict, force_sleep: Callable): self.id = next(self._ids) self.force_sleep = force_sleep self.name = dict_user['username'] self.password = dict_user['password'] self.alias = dict_user.get('alias', self.name) self.task_ctrl = task_ctrl self.task_arrangement = task_arrangement self.is_in_jail = False # 是否小黑屋 ## self.manage_room = dict_user['manage_room'] self.alerts = dict_user.get('alerts', []) self.gift_comb_delay = dict_user['gift_comb_delay'] self.alert_second = dict_user['alert_second'] self.gift_thx_format = dict_user.get( 'gift_thx_format', '感谢{username}投喂的{giftname}x{num}') self.silver_gift_thx_format = dict_user.get('silver_gift_thx_format', self.gift_thx_format) self.gold_gift_thx_format = dict_user.get('gold_gift_thx_format', self.gift_thx_format) self.focus_thx_format = dict_user['focus_thx_format'] self.guard_thx_format = dict_user.get('guard_thx_format', self.gift_thx_format) self.danmu_length = dict_user.get('danmu_length', 30) self.medal_update_format = dict_user.get('medal_update_format', '') self.medal_update_check_delay = dict_user.get( 'medal_update_check_delay', 30) self.only_live_thx = dict_user.get('only_live_thx', False) self.only_live_alert = dict_user.get('only_live_alert', True) self.anchor_alert_format = dict_user.get('anchor_alert_format', '') self.reply = dict_user.get('reply', []) self.ban = dict_user.get('ban', []) self.height = dict_user.get('height', 0) self.weight = dict_user.get('weight', 0) self.disable_gift_thx = dict_user.get('disable_gift_thx', False) if dict_user.get('const_json'): self.const_json = json.load(open(dict_user.get('const_json'), 'r')) else: self.const_json = {} self.fans_check_delay = dict_user.get('fans_check_delay', 20) self.random_list_1 = dict_user.get('random_list_1', []) self.random_list_2 = dict_user.get('random_list_2', []) self.random_list_3 = dict_user.get('random_list_3', []) if len(self.random_list_1) == 0: self.random_list_1 = [""] if len(self.random_list_2) == 0: self.random_list_2 = [""] if len(self.random_list_3) == 0: self.random_list_3 = [""] ## self.bililive_session = WebSession() self.login_session = WebSession() self.other_session = WebSession() # 每个user里面都分享了同一个dict,必须要隔离,否则更新cookie这些的时候会互相覆盖 self.pc = PcPlatform(dict_bili['pc_headers'].copy()) self.app = AppPlatform(dict_bili['app_headers'].copy(), dict_bili['app_params']) self.tv = TvPlatform(dict_bili['tv_headers'].copy(), dict_bili['tv_params']) self.dict_user = dict_user self.update_login_data(dict_user) self._waiting_login = None self._loop = asyncio.get_event_loop() self.repost_del_lock = asyncio.Lock( ) # 在follow与unfollow过程中必须保证安全(repost和del整个过程加锁) dyn_lottery_friends = [ (str(uid), name) for uid, name in task_ctrl['dyn_lottery_friends'].items() ] self.dyn_lottery_friends = dyn_lottery_friends # list (uid, name)