2025-03-28 14:50:37 +08:00
import io
2025-04-08 16:10:08 +08:00
import json
2025-04-27 16:19:10 +08:00
import os
2025-03-28 14:50:37 +08:00
import random
import sys
2025-04-27 16:19:10 +08:00
import threading
import time
import uuid
2025-04-24 15:55:08 +08:00
import pyotp
2025-04-27 16:19:10 +08:00
import pywintypes
import requests
2025-05-26 17:08:38 +08:00
from fake_useragent import UserAgent # 导入 UserAgent
2025-04-27 16:19:10 +08:00
import win32api
import win32con
2025-04-01 14:43:02 +08:00
from PIL import ImageGrab
2025-05-26 17:08:38 +08:00
from loguru import logger
from playwright . _impl . _page import Page
2025-04-27 16:19:10 +08:00
from playwright . sync_api import sync_playwright , Error , TimeoutError
2025-07-08 15:52:44 +08:00
from concurrent . futures import ThreadPoolExecutor
2025-04-27 16:19:10 +08:00
from const import BUCKET , BASE_PATH
from exceptions import AuthException , OperationFailed
from miniofile import client , put_object
2025-03-28 14:50:37 +08:00
2025-04-08 16:10:08 +08:00
# def get_dtsg_token(cookies):
# headers = {
# '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-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'cache-control': 'max-age=0',
# 'dpr': '2',
# 'priority': 'u=0, i',
# 'referer': 'https://www.facebook.com/?stype=lo&flo=1&deoia=1&jlou=AfchVgl8eRm2v_gCaPU1qqUi53hsIzJeyLP44jmPwCBLa7tUz9PYG-i0xhSc1SsyoN0UM8OfM2n4oImZKLL1OlDYm_2UMbJ2mRP3XWSR1jaRHg&smuh=27937&lh=Ac-9GdZW-IjAq1cdtk8',
# 'sec-ch-prefers-color-scheme': 'light',
# 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
# 'sec-ch-ua-full-version-list': '"Chromium";v="134.0.6998.89", "Not:A-Brand";v="24.0.0.0", "Google Chrome";v="134.0.6998.89"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-model': '""',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-ch-ua-platform-version': '"15.3.2"',
# 'sec-fetch-dest': 'document',
# 'sec-fetch-mode': 'navigate',
# 'sec-fetch-site': 'same-origin',
# 'sec-fetch-user': '?1',
# 'upgrade-insecure-requests': '1',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
# 'viewport-width': '743',
# }
#
# params = {
# 'sk': 'welcome',
# 'lsrc': 'lb',
# }
# response = requests.get('https://www.facebook.com/', params=params, cookies=cookies, headers=headers)
# pattern = '"dtsg":{"token":"(.*?)"'
# obj = re.search(pattern, response.text)
# return str(obj.group(1))
#
#
# def _gen_waterfall_id(user_id):
# a = 2147483647
# result = random.random() * a
# s = f'{user_id}{int(time.time())}{result}'
# md5 = hashlib.md5(s.encode('utf-8'))
# return md5.hexdigest()
#
#
# def _get_boundary():
# s = '1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'
# return ''.join(random.choices(s, k=16))
#
#
# def _upload_photo(cookies, filename, file, token):
# user_id = cookies['c_user']
# boundary = _get_boundary()
# headers = {
# 'accept': '*/*',
# 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'content-type': f'multipart/form-data; boundary=----WebKitFormBoundary{boundary}',
# 'origin': 'https://www.facebook.com',
# 'priority': 'u=1, i',
# 'referer': 'https://www.facebook.com/',
# 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-fetch-dest': 'empty',
# 'sec-fetch-mode': 'cors',
# 'sec-fetch-site': 'same-site',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
# }
#
# params = {
# 'av': user_id,
# '__aaid': '0',
# '__user': user_id,
# '__a': '1',
# '__req': '24',
# '__hs': '20160.HYP:comet_pkg.2.1...1',
# 'dpr': '2',
# '__ccg': 'EXCELLENT',
# '__rev': '1020837445',
# '__s': 'pywjy0:q8hbxy:j4h991',
# '__hsi': '7481088902259545192',
# '__dyn': '7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyUco5S3O2Saw8i2S1DwUx60GE3Qwb-q7oc81EEbbwto88422y11wBz83WwgEcEhwGxu782lwv89kbxS1Fwc61awkovwRwlE-U2exi4UaEW2au1jwUBwJK14xm3y11xfxmu3W3y261eBx_wHwdG7EbUG2-azqwaW223908O3216xi4UK2K2WEjxK2B08-269wkopg6C13xe3a3Gfw-KufxamEbbxG1fBG2-2K0E846fwk8eo',
# '__csr': 'g5rddNQ9n4MIyONklsARH4iiHazhb4ijqQKDWZvW8RKrndrShiSiA9h9adctAAOf99HSBFfVDFlJ9Frkwy8AWQleqVV95QXHh8GATKmh4QVEGjh49x7zdbBi-FEyiQnJXpp6KBhXyaVkhZoLVOaijxmmfxxaibyKmmtabHXyqAAx2GhonK9AV9KdAzbxai4Z7gHAizVoOEgy98KHDBAKq2TJ2EW8DG8yaFaV8C2DDxbiyrBWAzi4GcKuGG4UK8CCizRWCyeRx6iidyVA2am9CGdzqDAKuU8rxuu4WK7UXwAK9yqzo9axefxy9opwGxSfxeE8pqzHy8tKuazpFoO2qUG5UKi3C1ex-uEowce2Om4Ua8dUy0j-0Fo5K3K0C61hxfw9S2CE4MM2pg6q2uFGBiHg-7EcUG2W18w4BwwwbC4V8aEG3-4FA0EoaEO0GayGBwqF8rz88Ai0CEvwh85m48B0lmeAwgUfoaUpxmm3yawiWxei9wOU2uHwPxCehlwcC02jC02NK04fqRwj_wfHw0Cew8txugw02Ocw6Ry82Tw4Vwmotg3awrE7G2m08fwk86204M81KU0uWP07sCw5kg0Em08lg3Hwww8K0ka086g65w37U1poy1owjU1g8a84G4Q0lG08Py8Glw13i4U0v6Dw2Jo565m4r8U1uioK2ulZ1RagOgGu0lWrpE31yU-3q0Z81m81p8Iw0tywjpo6q0ssw',
# '__hsdp': '',
# '__hblp': '',
# '__comet_req': '15',
# 'fb_dtsg': token,
# 'jazoest': '25581',
# 'lsd': 'EuheViRhRnOVOfgS9HBpbx',
# '__spin_r': '1020837445',
# '__spin_b': 'trunk',
# '__spin_t': '1741826744',
# }
# content_type = MIMETYPE.get(filename.split('.')[-1])
# data = {
# 'source': '8',
# 'profile_id': user_id,
# 'waterfallxapp': 'comet',
# 'upload_id': 'jsc_c_5',
# }
#
# form_data = b''
# for k, v in data.items():
# form_data += b'------WebKitFormBoundary%s\r\nContent-Disposition: form-data; name="%s"\r\n\r\n%s\r\n' % (
# boundary.encode('utf-8'), k.encode('utf-8'), v.encode('utf-8')
# )
# form_data += b'------WebKitFormBoundary%s\r\nContent-Disposition: form-data; name="file"; filename="%s"\r\n' \
# b'Content-Type: %s\r\n\r\n%s\r\n------WebKitFormBoundary%s--\r\n' % \
# (boundary.encode('utf-8'), filename.encode('utf-8'), content_type.encode('utf-8'),
# file.getvalue(), boundary.encode('utf-8'))
#
# response = requests.post(
# 'https://upload.facebook.com/ajax/react_composer/attachments/photo/upload',
# params=params,
# cookies=cookies,
# headers=headers,
# data=form_data,
# )
# result = response.text[9:]
# photo_id = json.loads(result)['payload']['photoID']
# return photo_id
#
#
# def _upload_video(cookies, filename, file, token):
# user_id = cookies['c_user']
# content_type = MIMETYPE.get(filename.split('.')[-1])
# content = file.getvalue()
# file_size = str(len(content))
# uri = f'1741828726893-{filename}-{content_type}-{file_size}-' \
# f'498AEJ73tToOXuUki2xK88hus3f+nSxTuf4/921pFh4='
# uri = f"{hashlib.md5(uri.encode('utf-8'))}-0-{file_size}"
# start_headers = {
# 'accept': '*/*',
# 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'content-type': 'application/x-www-form-urlencoded',
# 'origin': 'https://www.facebook.com',
# 'priority': 'u=1, i',
# 'referer': 'https://www.facebook.com',
# 'sec-ch-prefers-color-scheme': 'light',
# 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
# 'sec-ch-ua-full-version-list': '"Chromium";v="134.0.6998.46", "Not:A-Brand";v="24.0.0.0", "Google Chrome";v="134.0.6998.46"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-model': '""',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-ch-ua-platform-version': '"15.3.2"',
# 'sec-fetch-dest': 'empty',
# 'sec-fetch-mode': 'cors',
# 'sec-fetch-site': 'same-origin',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
# 'x-asbd-id': file_size,
# 'x-fb-lsd': 'EuheViRhRnOVOfgS9HBpbx',
# 'x_fb_video_waterfall_id': '1162dcb62930e0a2f88aec53e2359276',
# }
#
# params = {
# '__a': '1',
# }
# file_extension = content_type.split('/')[-1]
# data = f'waterfall_id=1162dcb62930e0a2f88aec53e2359276&target_id={user_id}&source=composer&composer_entry_point_ref' \
# f'=timeline&supports_chunking=true&supports_file_api=true&file_size={file_size}&' \
# f'file_extension={file_extension}&partition_start_offset=0&partition_end_offset={file_size}&' \
# f'composer_dialog_version=V2&video_publisher_action_source&__aaid=0&__user={user_id}&__a=1&__req=51' \
# f'&__hs=20160.HYP%3Acomet_pkg.2.1...1&dpr=2&__ccg=EXCELLENT&__rev=1020837445&__s=r0kci7%3Aq8hbxy%3Aj4h991&' \
# f'__hsi=7481088902259545192&__dyn=7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyU8EW1twYwJyE24wJwkEkwUx60GE5O0BU2_CxS320qafxOU7m2210wEwgo9oO0-E4a3a4oaEnxO0Bo7O2l2Utwqob82kwiE567Udo5qfK0zEkxe2GewyDwkUe9obrwh8lwUwgojUlDw-wUwxwjFovUaU3qxW2-awLyESE2KwwwOg2cwMwhEkxebwHwKG4UrwFg2fwxyo566k1FwgUjwOwWzUfHDzUiBG2OUqwjVqwLwHwa211zU523C&__csr=g5r6Yt2lNcbjiNklsARR4iiHazhb4ih2R8DWtvW8RKrndrOdiShk9jhcYNSijbkACIGmA_JnTnQCBJi28yjHhkVHDAAkzKJ4yGjuVp4jqCyFdbh98hUPiVkLGqFpapuTJBAqWl7KiWVkhZpFfD8F9e5po-bz4Fay8HBBDiyW-VGGii4aF5x6mUCjACUCV8Na4F94dQterAiAyFoOEgy98KHDBAKq2TJ2ECi8DG8yaFaV8C2DDxbiBKVuF8MFazbDGGxeby9FAEZuFEzJogh98SbCg8FoCqESaGFVbDK26UkGu4WK7UXwAK9yqzo9axefxy9opwGxSfxeE8pqzHy8tKuazpFoO2qUG5VF98dGwjEvDG6833wIBxe2y3u8w4_wam1rwXw9xwkojU2twFG1cc0Ck1CwDGqFkGQfxW3eawKwi819o882Vxei2G9gfUiCg2xwGzawanoCFo6Gi6UO294w9G7U4i1lx29g5lzF84e3S2K6olBwUyE4KEjAyocK0DGUcUpzAlo39w0AVw0Irw13SJo4_U3WU0A3w1QK0xS5V200b8O0rm8wt84a0jC1pxR0cG1KwuE9o0w-1gwo80j0w6Xw1XHc0tOq0lh02xo0xl0eK220yU4i0_o0wp0om0vC0im0mm8wm84-0k22y1axd05qw2cUyaBo0gQxe0s204wEyaw5KDw4aw6GwkolohIzwf20y2oK2ulZ1RagOgGu0lWrpE31yU-3q0JEfo1m81p8Iw0tywjpo6q0ssw&__hsdp=&__hblp=&__comet_req=15&fb_dtsg={quote(token)}&jazoest=25581&lsd=EuheViRhRnOVOfgS9HBpbx&__spin_r=1020837445&__spin_b=trunk&__spin_t=1741826744'
#
# response = requests.post(
# 'https://www.facebook.com/ajax/video/upload/requests/start/',
# params=params,
# cookies=cookies,
# headers=start_headers,
# data=data,
# )
# result = response.text[9:]
#
# video_id = json.loads(result)['payload']['video_id']
# headers = {
# 'accept': '*/*',
# 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'composer_session_id': '1162dcb62930e0a2f88aec53e2359276',
# 'end_offset': file_size,
# 'id': 'undefined',
# 'offset': '0',
# 'origin': 'https://www.facebook.com',
# 'priority': 'u=1, i',
# 'product_media_id': video_id,
# 'referer': 'https://www.facebook.com/',
# 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-fetch-dest': 'empty',
# 'sec-fetch-mode': 'cors',
# 'sec-fetch-site': 'same-site',
# 'start_offset': '0',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
# 'x-entity-length': file_size,
# 'x-entity-name': filename,
# 'x-entity-type': content_type,
# 'x-total-asset-size': file_size,
# 'content-type': 'application/x-www-form-urlencoded',
# }
#
# params = {
# '__aaid': '0',
# '__user': user_id,
# '__a': '1',
# '__req': '1a',
# '__hs': '20160.HYP:comet_pkg.2.1...1',
# 'dpr': '2',
# '__ccg': 'EXCELLENT',
# '__rev': '1020850159',
# '__s': 'nc8uuq:q8hbxy:f9euk7',
# '__hsi': '7481168370954579081',
# '__dyn': '7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyUco5S3O2Saw8i2S1DwUx60GE3Qwb-q7oc81EEbbwto88422y11wBz83WwgEcEhwGxu782lwv89kbxS1Fwc61awkovwRwlE-U2exi4UaEW2au1jwUBwJK14xm3y11xfxmu3W3y261eBx_wHwdG7EbUG2-azqwaW223908O3216xi4UK2K2WEjxK2B08-269wkopg6C13xe3a3Gfw-KufxamEbbxG1fBG2-2K0E846fwk8eo',
# '__csr': 'gf5M84IBlR5Et22d5N7aT69shdb8BN-zbq49b8naVaQWhcJrb8Bj-O_RjipZSD8iZcXiHTyXmJqli6DlbJ4AgSRAQAWhrJ9erWgHKt4V8KFqCmRLyRQ8jChWXhkVkqvWKUTRBVamVDCDBV9V4UKumrKpBByWK5KeHDx2iuAuKVEZGnGF44VWz8xe4VFBJ4zUy5pUhy98Cpu8xiaVUycyK49oS9WUOfyFo-VvQUOppVQcgyHzKFEjAwFqGE-qquimeGiWxOrGQ9ADz6ql3Uycz9A9xqEmyJ1y6F-E-m6oSi7-ahk2O5U-5Gx2dgoDxy68pxyu6oWbJyU-9yUS2OFF9-icwww-wVKi3u48sK2iq9wTomwhUO0QEGpwea1-Dg-4Cm4o4yHUbP0v40iN2bUhh8721JwbO3m0tKEc82WCyZ7Wz86i1hwxx13Wwu8eo2xwa3wiS0RU4m0mq44u8gKq6A4EO6Q2J7Fd0a68wiA1iwm8BwDw7BxTw9CBy80mLg0dDU0aCo022-w0U-waq0d1z8b8vw6Me1jw5Uo3Yg1Vod86G3q17w2yoeo17U2dwoUco1docoao2dxm06kU4t02fyxmp02480PO0-o4W09sw3r80DCpm0gh09q0gm19z-588o0qVg09dU24w2Moao4yQ1Tyy01p8w0n0mfwCgkx91jw5HK0TUS1OO2o7UhbK2p0FVVCbCg',
# '__hsdp': '',
# '__hblp': '',
# '__comet_req': '15',
# 'fb_dtsg': token,
# 'jazoest': '25320',
# 'lsd': 'kr_xMDgwgZMvLcmrnMrL6A',
# '__spin_r': '1020850159',
# '__spin_b': 'trunk',
# '__spin_t': '1741845247',
# }
#
# response = requests.post(
# f'https://rupload-sin6-3.up.facebook.com/fb_video/{uri}',
# params=params,
# cookies=cookies,
# headers=headers,
# data=content,
# )
#
# video_file_chunk = response.json()['h']
# params = {
# '__a': '1',
# }
#
# data = {
# 'waterfall_id': '1162dcb62930e0a2f88aec53e2359276',
# 'target_id': user_id,
# 'video_id': video_id,
# 'source': 'composer',
# 'composer_entry_point_ref': 'timeline',
# 'supports_chunking': 'true',
# 'supports_upload_service': 'true',
# 'partition_start_offset': '0',
# 'partition_end_offset': file_size,
# 'start_offset': '0',
# 'end_offset': file_size,
# 'upload_speed': '0',
# 'fbuploader_video_file_chunk': video_file_chunk,
# 'composer_dialog_version': 'V2',
# '__aaid': '0',
# '__user': user_id,
# '__a': '1',
# '__req': '2w',
# '__hs': '20160.HYP:comet_pkg.2.1...1',
# 'dpr': '2',
# '__ccg': 'EXCELLENT',
# '__rev': '1020855273',
# '__s': 'wgfbjc:q8hbxy:0fgg9t',
# '__hsi': '7481172705613662617',
# '__dyn': '7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyUco5S3O2Saw8i2S1DwUx60GE3Qwb-q7oc81EEbbwto88422y11wBz83WwgEcEhwGxu782lwv89kbxS1Fwc61awkovwRwlE-U2exi4UaEW2au1jwUBwJK14xm3y11xfxmu3W3y261eBx_wHwdG7EbUG2-azqwaW223908O3216xi4UK2K2WEjxK2B08-269wkopg6C13xe3a3Gfw-KufxamEbbxG1fBG2-2K0E846fwk8eo',
# '__csr': 'g5fd4ONcuznkn5hsyqfONYhRYIB9R7jPTbnFuILa_SiT8HqZ99GAoyaOqnmGiEzGTkxQGKlfaBlaihkhbuh8HKaGAKHh5VfUOvkEyCV5KdQByUx9aSVAVWybhJCVpBK_UKjQm8rlenBFAgKAnCGHxmWBhUyXG8KiqRQqXo-VESWJ4BhEGQ6WiXylXLjDUGqFWyFEyQcgWJeumucK8BK8hEKuEKWgqDjVokjhpp9u8gkyWgiGbxmQdKmBxaq9z9p8GGADAUyUKi9DBBV9fzKAQubAyXy8S49pUgybgKezVEVedCDV898nCAgC2i4UkwCwxKVpFUrhpryogyElxW4UCi6lz88poB5x29DVo8EnK7EiK2OewkUvxebAwvFoy5E425-0Io57wRx-12xgF84m2u14w44ixm3C44aAxibgK3Sq18w9ady9k2q16wio4rx93URG6qwabwgQ2u5oWi37w4kxe0q6ay8xDU9UaybwbK8G0UUgAgaE2Gw40xO2OEggi-483rwp87S1x-7oF04dw6rhE1vU2Kh8C06XU1h83qG023e02Gi00wE80eiU2Lw3fQ1aw6_812wCw56glDU3QDw7tgy0DE7-0a8wj83hw4IwNw4oxO362C0zolw1Be17g0zykFA08Cw13q0J40uq0dXw2w30fOu0BU3Xwj9k3Gdw1HB00AUwrU0Ji2G3i5Q1_Ew0mcBo0m-bwsIw1r8aE7O18wrqZo22NfcE9A2NAy4',
# '__hsdp': '',
# '__hblp': '',
# '__comet_req': '15',
# 'fb_dtsg': token,
# 'jazoest': '25687',
# 'lsd': 'W2jWYsm50EoSzDoSO5Ue9n',
# '__spin_r': '1020855273',
# '__spin_b': 'trunk',
# '__spin_t': '1741846256',
# }
#
# requests.post(
# 'https://www.facebook.com/ajax/video/upload/requests/receive/',
# params=params,
# cookies=cookies,
# headers=start_headers,
# data=data,
# )
# return video_id
#
#
# def _upload_comment_video(cookies, filename, file, token):
# user_id = cookies['c_user']
# waterfall_id = _gen_waterfall_id(user_id)
# composer_session_id = _gen_waterfall_id(user_id)
# content_type = MIMETYPE.get(filename.split('.')[-1])
# content = file.getvalue()
# file_size = str(len(content))
# uri = f'1741828726893-{filename}-{content_type}-{file_size}-' \
# f'498AEJ73tToOXuUki2xK88hus3f+nSxTuf4/921pFh4='
# uri = f"{hashlib.md5(uri.encode('utf-8'))}-0-{file_size}"
# file_extension = content_type.split('/')[-1]
# headers = {
# 'accept': '*/*',
# 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'content-type': 'application/x-www-form-urlencoded',
# 'origin': 'https://www.facebook.com',
# 'priority': 'u=1, i',
# 'referer': 'https://www.facebook.com/',
# 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-fetch-dest': 'empty',
# 'sec-fetch-mode': 'cors',
# 'sec-fetch-site': 'same-site',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
# 'x_fb_video_waterfall_id': waterfall_id,
# }
#
# params = {
# '__a': '1',
# }
# data = f'file_size={file_size}&file_extension={file_extension}&target_id={user_id}&source=comment&composer_dialog_version&waterfall_id={waterfall_id}&composer_session_id={composer_session_id}&composer_entry_point_ref=feed_story&composer_work_shared_draft_mode&has_file_been_replaced=false&supports_chunking=true&supports_file_api=true&partition_start_offset=0&partition_end_offset={file_size}&creator_product=2&spherical=false&video_publisher_action_source&__aaid=0&__user={user_id}&__a=1&__req=2s&__hs=20161.HYP%3Acomet_pkg.2.1...1&dpr=2&__ccg=EXCELLENT&__rev=1020896933&__s=a6lpwr%3Av72pg5%3Alvg2er&__hsi=7481534814351260330&__dyn=7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyUco5S3O2Saw8i2S1DwUx60GE5O0BU2_CxS320qa2OU7m2210wEwgo9oO0-E4a3a4oaEnxO0Bo7O2l2Utwqo31wiE567Udo5qfK0zEkxe2GewyDwkUe9obrwh8lwUwgojUlDw-wUwxwjFovUaU3qxW2-awLyESE2KwwwOg2cwMwhEkxebwHwKG4UrwFg2fwxyo566k1FwgUjwOwWzUfHDzUiBG2OUqwjVqwLwHwa211zU523C&__csr=geI2ex4D7NYfTfshvbN7i94jjWq6l9OqZ4EzVsQx2dqGAACCPZiqinWORrt9ajKnl5IGSiGZbJ4F4CoyWRhd5iZ95CAOtLy4jBhkjt29F8KiABJyqQ9yFIDjiZ7Lhi5HhCZrXDUCAum598gzEWuUR7ADHDqK-tUTymayF9ECjCBXG8h8iQmaQ4LzVECh1Omh1u4USjy8CmuiSFbhbCy8gyGVoSuWy94Wig-4EKmcG8yqBVoXGWZ2ECXAxmb-mFoLgGUvz9u8z9eqm7Hy9bCiHKU-3mUsyoKcxaGKaBLyqGm7-8xy2KcDAh8hxK4EiAx7xq8wGBxycxy2S79pZ29EPxy5FUd8y5E9EB1a3m8xe482qwzxC4o3ux11e1wKaJkWuqF898RwAwaxwaO3C8yEOum1LWghxy4o8m0z3o0wqU7C3DxO2R4xeShrBCUO740zoLCy4by8ct0Lwyxe0D8y68bWyE8o6608Dw9m3G2C0Fk0F8nwCx-0D8-7FUnG8wro10o0ey80zO0p3wdrl0Lye00JSE0fvE-0bWCw960k66p81X60it0oOKu0kN282wwv80D21FwbG0iC0iO1bwSwAw9i582sw1ta1izU0yOkFQ0ne04Z82Pg1Y80mSBt044g7W0hW1bgeES06Kk02dm0he08Cwm88o5h0TwiE0mry8Gu05JUhwCghG4C4aw5Kxq0Ao4y1MDDyVE6EAyy89A2CcdyHu&__hsdp=&__hblp=&__comet_req=15&fb_dtsg={quote(token)}&jazoest=25421&lsd=sBdlvZ7xyxJeCPFduGOZlc&__spin_r=1020896933&__spin_b=trunk&__spin_t=1741930566'
# print(data)
# response = requests.post(
# 'https://vupload-edge.facebook.com/ajax/video/upload/requests/start/',
# params=params,
# cookies=cookies,
# headers=headers,
# data=data,
# )
# result = response.text[9:]
# video_id = json.loads(result)['payload']['video_id']
#
# headers = {
# 'accept': '*/*',
# 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'composer_session_id': waterfall_id,
# 'end_offset': file_size,
# 'id': 'undefined',
# 'offset': '0',
# 'origin': 'https://www.facebook.com',
# 'priority': 'u=1, i',
# 'product_media_id': video_id,
# 'referer': 'https://www.facebook.com/',
# 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-fetch-dest': 'empty',
# 'sec-fetch-mode': 'cors',
# 'sec-fetch-site': 'same-site',
# 'start_offset': '0',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
# 'x-entity-length': file_size,
# 'x-entity-name': 'undefined',
# 'x-entity-type': 'application/octet-stream',
# 'x-total-asset-size': file_size,
# 'content-type': 'application/x-www-form-urlencoded',
# }
#
# params = {
# '__aaid': '0',
# '__user': user_id,
# '__a': '1',
# '__req': '2v',
# '__hs': '20161.HYP:comet_pkg.2.1...1',
# 'dpr': '2',
# '__ccg': 'EXCELLENT',
# '__rev': '1020896933',
# '__s': 'a6lpwr:v72pg5:lvg2er',
# '__hsi': '7481534814351260330',
# '__dyn': '7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyUco5S3O2Saw8i2S1DwUx60GE5O0BU2_CxS320qa2OU7m2210wEwgo9oO0-E4a3a4oaEnxO0Bo7O2l2Utwqo31wiE567Udo5qfK0zEkxe2GewyDwkUe9obrwh8lwUwgojUlDw-wUwxwjFovUaU3qxW2-awLyESE2KwwwOg2cwMwhEkxebwHwKG4UrwFg2fwxyo566k1FwgUjwOwWzUfHDzUiBG2OUqwjVqwLwHwa211zU523C',
# '__csr': 'geI2ex4D7NYfTfshvbN7i94jjWq6l9OqZ4EzVsQx2dqGAACCPZiqinWORrt9ajKnl5IGSiGZbJ4F4CoyWRhd5iZ95CAOtLy4jBhkjt29F8KiABJyqQ9yFIDjiZ7Lhi5HhCZrXDUCAum598gzEWuUR7ADHDqK-tUTymayF9ECjCBXG8h8iQmaQ4LzVECh1Omh1u4USjy8CmuiSFbhbCy8gyGVoSuWy94Wig-4EKmcG8yqBVoXGWZ2ECXAxmb-mFoLgGUvz9u8z9eqm7Hy9bCiHKU-3mUsyoKcxaGKaBLyqGm7-8xy2KcDAh8hxK4EiAx7xq8wGBxycxy2S79pZ29EPxy5FUd8y5E9EB1a3m8xe482qwzxC4o3ux11e1wKaJkWuqF898RwAwaxwaO3C8yEOum1LWghxy4o8m0z3o0wqU7C3DxO2R4xeShrBCUO740zoLCy4by8ct0Lwyxe0D8y68bWyE8o6608Dw9m3G2C0Fk0F8nwCx-0D8-7FUnG8wro10o0ey80zO0p3wdrl0Lye00JSE0fvE-0bWCw960k66p81X60it0oOKu0kN282wwv80D21FwbG0iC0iO1bwSwAw9i582sw1ta1izU0yOkFQ0ne04Z82Pg1Y80mSBt044g7W0hW1bgeES06Kk02dm0he08Cwm88o5h0TwiE0mry8Gu05JUhwCghG4C4aw5Kxq0Ao4y1MDDyVE6EAyy89A2CcdyHu',
# '__hsdp': '',
# '__hblp': '',
# '__comet_req': '15',
# 'fb_dtsg': token,
# 'jazoest': '25421',
# 'lsd': 'sBdlvZ7xyxJeCPFduGOZlc',
# '__spin_r': '1020896933',
# '__spin_b': 'trunk',
# '__spin_t': '1741930566',
# }
# response = requests.post(
# f'https://rupload-sin6-3.up.facebook.com/fb_video/{uri}',
# params=params,
# cookies=cookies,
# headers=headers,
# data=content,
# )
# video_file_chunk = response.json()['h']
#
# boundary = _get_boundary()
# headers = {
# 'accept': '*/*',
# 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'content-type': f'multipart/form-data; boundary=----WebKitFormBoundary{boundary}',
# 'origin': 'https://www.facebook.com',
# 'priority': 'u=1, i',
# 'referer': 'https://www.facebook.com/',
# 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-fetch-dest': 'empty',
# 'sec-fetch-mode': 'cors',
# 'sec-fetch-site': 'same-site',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
# 'x_fb_video_waterfall_id': waterfall_id,
# }
# params = {
# "composer_session_id": composer_session_id,
# "video_id": video_id,
# "start_offset": "0",
# "end_offset": file_size,
# "source": "comment",
# "target_id": user_id,
# "waterfall_id": waterfall_id,
# "composer_entry_point_ref": "feed_story",
# "has_file_been_replaced": "false",
# "supports_chunking": "true",
# "partition_start_offset": "0",
# "partition_end_offset": file_size,
# "__aaid": "0",
# "__user": user_id,
# "__a": "1",
# "__req": "2w",
# "__hs": "20161.HYP:comet_pkg.2.1...1",
# "dpr": "2",
# "__ccg": "EXCELLENT",
# "__rev": "1020896933",
# "__s": "a6lpwr:v72pg5:lvg2er",
# "__hsi": "7481534814351260330",
# "__dyn": "7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyUco5S3O2Saw8i2S1DwUx60GE5O0BU2_CxS320qa2OU7m2210wEwgo9oO0-E4a3a4oaEnxO0Bo7O2l2Utwqo31wiE567Udo5qfK0zEkxe2GewyDwkUe9obrwh8lwUwgojUlDw-wUwxwjFovUaU3qxW2-awLyESE2KwwwOg2cwMwhEkxebwHwKG4UrwFg2fwxyo566k1FwgUjwOwWzUfHDzUiBG2OUqwjVqwLwHwa211zU523C",
# "__csr": "geI2ex4D7NYfTfshvbN7i94jjWq6l9OqZ4EzVsQx2dqGAACCPZiqinWORrt9ajKnl5IGSiGZbJ4F4CoyWRhd5iZ95CAOtLy4jBhkjt29F8KiABJyqQ9yFIDjiZ7Lhi5HhCZrXDUCAum598gzEWuUR7ADHDqK-tUTymayF9ECjCBXG8h8iQmaQ4LzVECh1Omh1u4USjy8CmuiSFbhbCy8gyGVoSuWy94Wig-4EKmcG8yqBVoXGWZ2ECXAxmb-mFoLgGUvz9u8z9eqm7Hy9bCiHKU-3mUsyoKcxaGKaBLyqGm7-8xy2KcDAh8hxK4EiAx7xq8wGBxycxy2S79pZ29EPxy5FUd8y5E9EB1a3m8xe482qwzxC4o3ux11e1wKaJkWuqF898RwAwaxwaO3C8yEOum1LWghxy4o8m0z3o0wqU7C3DxO2R4xeShrBCUO740zoLCy4by8ct0Lwyxe0D8y68bWyE8o6608Dw9m3G2C0Fk0F8nwCx-0D8-7FUnG8wro10o0ey80zO0p3wdrl0Lye00JSE0fvE-0bWCw960k66p81X60it0oOKu0kN282wwv80D21FwbG0iC0iO1bwSwAw9i582sw1ta1izU0yOkFQ0ne04Z82Pg1Y80mSBt044g7W0hW1bgeES06Kk02dm0he08Cwm88o5h0TwiE0mry8Gu05JUhwCghG4C4aw5Kxq0Ao4y1MDDyVE6EAyy89A2CcdyHu",
# "__comet_req": "15",
# "fb_dtsg": token,
# "jazoest": "25421",
# "lsd": "sBdlvZ7xyxJeCPFduGOZlc",
# "__spin_r": "1020896933",
# "__spin_b": "trunk",
# "__spin_t": "1741930566"
# }
# form_data = b'------WebKitFormBoundary%s\r\nContent-Disposition: form-data; ' \
# b'name="fbuploader_video_file_chunk"\r\n\r\n%s\r\n' % (
# boundary.encode('utf-8'), video_file_chunk.encode('utf-8')
# )
# requests.post(
# 'https://vupload-edge.facebook.com/ajax/video/upload/requests/receive/',
# cookies=cookies,
# headers=headers,
# params=params,
# data=form_data,
# )
# return video_id
#
#
# def post(cookies, message, image_key=None):
# user_id = cookies['c_user']
# dtsg_token = get_dtsg_token(cookies)
# headers = {
# 'accept': '*/*',
# 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'content-type': 'application/x-www-form-urlencoded',
# 'origin': 'https://www.facebook.com',
# 'priority': 'u=1, i',
# 'referer': f'https://www.facebook.com/',
# 'sec-ch-prefers-color-scheme': 'light',
# 'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
# 'sec-ch-ua-full-version-list': '"Not(A:Brand";v="99.0.0.0", "Google Chrome";v="133.0.6943.127", "Chromium";v="133.0.6943.127"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-model': '""',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-ch-ua-platform-version': '"15.3.2"',
# 'sec-fetch-dest': 'empty',
# 'sec-fetch-mode': 'cors',
# 'sec-fetch-site': 'same-origin',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
# 'x-asbd-id': '359341',
# 'x-fb-friendly-name': 'ComposerStoryCreateMutation',
# 'x-fb-lsd': 'aQBZ0Gh5mfQSPgCywj081r',
# }
# uuid4_token = str(uuid.uuid4())
#
# # 处理图片或视频上传
# attachments = []
# if image_key:
# # bio = client.download_bytes_file(BUCKET, image_key)
# with open('../files/xmbl.mp4', 'rb') as f:
# bio = io.BytesIO(f.read())
# filename = image_key.split('/')[-1]
# content_type = MIMETYPE.get(filename.split('.')[-1])
# if not content_type:
# raise OperationFailed('文件类型暂不支持')
# if content_type in PIC_TYPE:
# # 上传图片
# photo_id = _upload_photo(cookies, filename, bio, dtsg_token)
# attachments = [{'photo': {'id': photo_id}}]
# else:
# # 上传视频
# video_id = _upload_video(cookies, filename, bio, dtsg_token)
# attachments = [{'video': {'id': video_id, 'notify_when_processed': True}}]
#
# data = {
# 'av': user_id,
# '__aaid': '0',
# '__user': user_id,
# '__a': '1',
# '__req': '42',
# '__hs': '20159.HYP:comet_pkg.2.1...1',
# 'dpr': '2',
# '__ccg': 'EXCELLENT',
# '__rev': '1020809040',
# '__s': 'itr9j4:q8hbxy:4gveux',
# '__hsi': '7480795543745950771',
# '__dyn': '7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyUco5S3O2Saw8i2S1DwUx60GE5O0BU2_CxS320qa2OU7m221Fwgo9oO0-E4a3a4oaEnxO0Bo7O2l2Utwqo31wiE567Udo5qfK0zEkxe2GewyDwkUe9obrwh8lwUwgojUlDw-wSU8o4Wm7-2K1ywtUuwLyEbUGdG0HE88cA0z8c84q58jyUaUbGxe6Uak0zU8oC1hxB0qo4e4UcEeE-3WVU-4FqwIK6E4-mEbUaU2wwgo623C',
# '__csr': 'g4r1p3O7ZNk4kn4gxn2lkIIp7iLlsZSQyO8yaXOEy9H8qAOsqXkGi8yGmzSXldtnhqh2nO4FkIFttVVQKmLnhZ9Jq8GJ6iybBt6QiF95iunUBF4gCqhSGrhWSuDCildrLCpVBC-VlDy-jK8n_DmlCBhJQUym-i6pahFVkVV9aCyGpKnXmfDiBBBgRaqXCAh8hnAypS4UKGKQvQWBzqAx3HVSjKip2qUi-mEgDAVkVaxai4WCCF5ypKqdKi9ypHCAGrBV_jAAxuHLV98hxCnAWV6GADy8Ci8hkFXiJ7K6omzrLh8x1a2qUjiJ38Na8znwzzXU-UkzXGdyrx50Ixei58OQ9ybxau2i4qDyku4U8ax516eLy8KcwAxi9xiufxiU8Q7EK2i14G5ocS2yHDwDwMwmEcE2LwLz9o15EN122i2GAp6hQGwIHyUZw867k18EE6Wao2_woo2lwEx61lye0x86Wi2u3ZCy9Q1tQ0F8lny8iye1kwOGcECUlwcu0Ko5m9J1by5GlU62ewYwXw9m0G846i0zEeUcVu2twuuE0n_w0wdw2cU1QEd8721iocE0OG2Dm5E081Enw08xG03HK1fw8a0nq0oeu1dw72a16wyw55wBo3jg1X48wa21-w2w85e0PoKu0hy0iy18wgEfE7uhxa5o8y3U9EK04SK9w4zDg0zygEyaw7Xw3mE3Vwbx07yw3IU1N306Ew9G0WVFmm1eBg0n9wcp0fafw17i0s60s60ju0rypo4O15w8e2a5o987S05wpQaw1eK0EkK464WzQ2C09tDxGE3qOuiA5f472dKLm',
# '__hsdp': '',
# '__hblp': '',
# '__comet_req': '15',
# 'fb_dtsg': dtsg_token,
# 'jazoest': '25494',
# 'lsd': 'WgZt97AQ_LCDMTfuw-sO6Y',
# '__spin_r': '1020809040',
# '__spin_b': 'trunk',
# '__spin_t': '1741758441',
# 'fb_api_caller_class': 'RelayModern',
# 'fb_api_req_friendly_name': 'ComposerStoryCreateMutation',
# 'variables': '{"input":{"composer_entry_point":"inline_composer","composer_source_surface":"timeline","idempotence_token":"%s_FEED","source":"WWW","attachments":%s,"audience":{"privacy":{"allow":[],"base_state":"EVERYONE","deny":[],"tag_expansion_state":"UNSPECIFIED"}},"message":{"ranges":[],"text":"%s"},"with_tags_ids":null,"inline_activities":[],"text_format_preset_id":"0","publishing_flow":{"supported_flows":["ASYNC_SILENT","ASYNC_NOTIF","FALLBACK"]},"logging":{"composer_session_id":"%s"},"navigation_data":{"attribution_id_v2":"ProfileCometTimelineListViewRoot.react,comet.profile.timeline.list,tap_bookmark,1741758458056,864702,61573941575877,,"},"tracking":[null],"event_share_metadata":{"surface":"timeline"},"actor_id":"%s","client_mutation_id":"9"},"feedLocation":"TIMELINE","feedbackSource":0,"focusCommentID":null,"gridMediaWidth":230,"groupID":null,"scale":2,"privacySelectorRenderLocation":"COMET_STREAM","checkPhotosToReelsUpsellEligibility":true,"renderLocation":"timeline","useDefaultActor":false,"inviteShortLinkKey":null,"isFeed":false,"isFundraiser":false,"isFunFactPost":false,"isGroup":false,"isEvent":false,"isTimeline":true,"isSocialLearning":false,"isPageNewsFeed":false,"isProfileReviews":false,"isWorkSharedDraft":false,"hashtag":null,"canUserManageOffers":false,"__relay_internal__pv__CometUFIShareActionMigrationrelayprovider":true,"__relay_internal__pv__GHLShouldChangeSponsoredDataFieldNamerelayprovider":false,"__relay_internal__pv__GHLShouldChangeAdIdFieldNamerelayprovider":false,"__relay_internal__pv__IsWorkUserrelayprovider":false,"__relay_internal__pv__CometUFIReactionsEnableShortNamerelayprovider":false,"__relay_internal__pv__CometFeedStoryDynamicResolutionPhotoAttachmentRenderer_experimentWidthrelayprovider":500,"__relay_internal__pv__CometImmersivePhotoCanUserDisable3DMotionrelayprovider":false,"__relay_internal__pv__WorkCometIsEmployeeGKProviderrelayprovider":false,"__relay_internal__pv__IsMergQAPollsrelayprovider":false,"__relay_internal__pv__FBReels_deprecate_short_form_video_context_gkrelayprovider":false,"__relay_internal__pv__FBReelsMediaFooter_comet_enable_reels_ads_gkrelayprovider":false,"__relay_internal__pv__StoriesArmadilloReplyEnabledrelayprovider":false,"__relay_internal__pv__FBReelsIFUTileContent_reelsIFUPlayOnHoverrelayprovider":false,"__relay_internal__pv__EventCometCardImage_prefetchEventImagerelayprovider":false,"__relay_internal__pv__GHLShouldChangeSponsoredAuctionDistanceFieldNamerelayprovider":false}' % (
# uuid4_token, json.dumps(attachments), message, uuid4_token, user_id
# ),
# 'server_timestamps': 'true',
# 'doc_id': '9835564903120639',
# }
# response = requests.post('https://www.facebook.com/api/graphql/', cookies=cookies, headers=headers, data=data)
# if response.status_code != 200:
# raise OperationFailed(f'发帖异常 response: {response.text}')
#
# if response.json() and response.json().get('data'):
# if not response.json()['data']['story_create'].get('timeline_feed_units_edge'):
# return
# post_id = response.json()['data']['story_create']['timeline_feed_units_edge']['node']['feedback']['id']
# return {'reso_id': post_id}
# else:
# raise OperationFailed(f'参数错误, response: {response.text}')
#
#
# def like(cookies, post_id):
# user_id = cookies['c_user']
# dtsg_token = get_dtsg_token(cookies)
# headers = {
# 'accept': '*/*',
# 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'content-type': 'application/x-www-form-urlencoded',
# 'origin': 'https://www.facebook.com',
# 'priority': 'u=1, i',
# 'referer': 'https://www.facebook.com/',
# 'sec-ch-prefers-color-scheme': 'light',
# 'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
# 'sec-ch-ua-full-version-list': '"Not(A:Brand";v="99.0.0.0", "Google Chrome";v="133.0.6943.127", "Chromium";v="133.0.6943.127"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-model': '""',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-ch-ua-platform-version': '"15.3.1"',
# 'sec-fetch-dest': 'empty',
# 'sec-fetch-mode': 'cors',
# 'sec-fetch-site': 'same-origin',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
# 'x-asbd-id': '359341',
# 'x-fb-friendly-name': 'CometUFIFeedbackReactMutation',
# 'x-fb-lsd': 'pSe8b3OaUeIWyqreatk6Bt',
# }
#
# data = {
# 'av': user_id,
# '__aaid': '0',
# '__user': user_id,
# '__a': '1',
# '__req': '73',
# '__hs': '20159.HYP:comet_pkg.2.1...1',
# 'dpr': '2',
# '__ccg': 'EXCELLENT',
# '__rev': '1020805083',
# '__s': 'rkcs6h:q8hbxy:ud5a0g',
# '__hsi': '7480739570773453695',
# '__dyn': '7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyUco5S3O2Saw8i2S1DwUx60GE3Qwb-q7oc81EEbbwto886C11wBz83WwgEcEhwGxu782lwv89kbxS1Fwc61awkovwRwlE-U2exi4UaEW2au1jwUBwJK14xm3y11xfxmu3W3iU8o4Wm7-2K1ywtUuwLyEbUGdG0HE88cA0z8c84q58jyUaUbGxe6Uak0zU8oC1hxB0qo4e4UcEeE-3WVU-4FqwIK6E4-mEbUaU2wwgomwioeo',
# '__csr': 'g4v2Qp2I8MB2sBiMP6hWT94Pi8BOh4JEAjOIAYkOkCOl8TFfXAlOEhi4QySYQQJ99Qyjh3uRIBtEDDqkREOQBWFa-leLCnfKGHflRKZpkAJQAnllFkQhrEDZ5h2pV7AFd6BA9LBFTG-nyJKAeh8yCgPKC8iBLAHKKmAayUGCQKjSF4ibCz6qhkX-V6pWBWCWLSHHmmJi2qKKQbXyp8-FqKclAgzylmiimHCdyQFQhCXWGq8jQpABnWGGGcDxbBJ6VpXFx69gygxAqmt2eiKjK-jQppoWu9JapzZknWiFf-h4y9VXBBDp5LKp3rFXimaBKihGijBLyAqAfBCxVUCuXx6EVScAx22Oezebx2UyWV9bCGrx279EqyGG5bF3e2uuFFEPDAK4UB3oHxp5UOvDAUG4ElymESeCCxLzVFAawNolgpw8i4o1hEd87u48swt81mS2C3pa1FAwcG2GeBl11240xo-2e11wzwXm598jx61xwTo9qwygBQ0Ho8EO5E36yt2Ah5UrBwJBAhe6VXjXwsy0aS7UZ1GeJ5Owxxa6U4x0OF2A4o4O8Ujg4G2K291i9Z08a4EnOel1-19wGCK7FEKK4VpU7W9y8RwDwCw0Bbw3s81DU0qfw3388Elwk_m1mo0Gm3W069UeU10ooAo7yU4K7802Nkw4YxS1fp86e0ZEaocE5iawDwuo2kwo8jwXwoo27wdu1aw9a0E8Dh411w3k8gwh8CA9w3pE7a08Swho9E1x83ww51waegB019W0G9U1hFE4e1byE6W0N87a08c4kq0F8hg3-Dw_Dw5rwroqw6wxXg6G11wgU3LmifwIwSgK0pu1jCw6yxkE1PXhE0AR0da48iw9i10wVw1wTw2FUGl0HxkwgBto3Qw80LOAwDWqQi5eAPJ4BBo2Qwax6Qu0FU4O540GUeUK2u0mK0jUw0tzwKx20EU1BO0',
# '__hsdp': '',
# '__hblp': '',
# '__comet_req': '15',
# 'fb_dtsg': dtsg_token,
# 'jazoest': '25686',
# 'lsd': 'pSe8b3OaUeIWyqreatk6Bt',
# '__spin_r': '1020805083',
# '__spin_b': 'trunk',
# '__spin_t': '1741745409',
# 'fb_api_caller_class': 'RelayModern',
# 'fb_api_req_friendly_name': 'CometUFIFeedbackReactMutation',
# 'variables': '{"input":{"attribution_id_v2":"ProfileCometTimelineListViewRoot.react,comet.profile.timeline.list,via_cold_start,1741762579222,259553,190055527696468,,","feedback_id":"%s","feedback_reaction_id":"1635855486666999","feedback_source":"NEWS_FEED","feedback_referrer":"/","is_tracking_encrypted":true,"tracking":["AZU7Uu1mm-QEQWdf13bCqxa9BLW6XkzoVE0sGm0QPL4CVtIl4WisVkoklN9Br-D0Au3gMFW4r6MvQ0nT00cAJa6iF6KyFW3HCZaxjanGT-stTURNU_RPjcB29mJ-hLkoviYK03qDPP41KJKtNwLxhWyj6z_wd3i__pyfdS8FecVlOj8qHhr2s6LJq32sUIqQ8omYEHGRnDN99kb9BW8HS_x4C8ZY8-fDY5abf-cXMixnohPQBtAqhQhwB2DxkFwqYxPHy6psbCYTCVyjbhPsFyvEfSO7bVN4_foTsx9dzcyhY820L0NB847Fzu77vWNC0wHffoD_SCOnJQTU8m-TcjVTbZu0vwoam47IPOi0DK3xSSxG_8bDXdbv86prssWEsvi7vkbERsPACyi9JcuGCiO0cIpOnJSsJkbuOU_BqYq7SrR9h254Px8T85lj5F_OmWCvOuKYJ8IAUS6cyc56dw-cGPBkQ2R5ewEDCl5uwfB0rg"],"session_id":"121da0a0-58ab-4ab0-93dd-6a7e3c42625e","actor_id":"%s","client_mutation_id":"1"},"useDefaultActor":false,"__relay_internal__pv__CometUFIReactionsEnableShortNamerelayprovider":false}' % (
# post_id, user_id
# ),
# 'server_timestamps': 'true',
# 'doc_id': '9232085126871383',
# }
#
# response = requests.post('https://www.facebook.com/api/graphql/', cookies=cookies, headers=headers, data=data)
# if response.status_code != 200:
# raise OperationFailed(f'点赞异常 response: {response.text}')
#
#
# def comment(cookies, post_id, message, image_key=None):
# user_id = cookies['c_user']
# uuid4_token = str(uuid.uuid4())
# dtsg_token = get_dtsg_token(cookies)
# headers = {
# 'accept': '*/*',
# 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
# 'content-type': 'application/x-www-form-urlencoded',
# 'origin': 'https://www.facebook.com',
# 'priority': 'u=1, i',
# 'referer': 'https://www.facebook.com/',
# 'sec-ch-prefers-color-scheme': 'light',
# 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
# 'sec-ch-ua-full-version-list': '"Chromium";v="134.0.6998.89", "Not:A-Brand";v="24.0.0.0", "Google Chrome";v="134.0.6998.89"',
# 'sec-ch-ua-mobile': '?0',
# 'sec-ch-ua-model': '""',
# 'sec-ch-ua-platform': '"macOS"',
# 'sec-ch-ua-platform-version': '"15.3.2"',
# 'sec-fetch-dest': 'empty',
# 'sec-fetch-mode': 'cors',
# 'sec-fetch-site': 'same-origin',
# 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
# 'x-asbd-id': '359341',
# 'x-fb-friendly-name': 'useCometUFICreateCommentMutation',
# 'x-fb-lsd': 'sBdlvZ7xyxJeCPFduGOZlc',
# }
#
# # 处理图片或视频上传
# attachments = 'null'
# if image_key:
# # bio = client.download_bytes_file(BUCKET, image_key)
# with open('../xzpq.mp4', 'rb') as f:
# bio = io.BytesIO(f.read())
# filename = image_key.split('/')[-1]
# content_type = MIMETYPE.get(filename.split('.')[-1])
# if not content_type:
# raise OperationFailed('文件类型暂不支持')
# if content_type in PIC_TYPE:
# # 上传图片
# photo_id = _upload_photo(cookies, filename, bio, dtsg_token)
# attachments = json.dumps([{'media': {'id': photo_id}}])
# else:
# # 上传视频
# video_id = _upload_comment_video(cookies, filename, bio, dtsg_token)
# attachments = json.dumps([{'media': {'id': video_id}}])
# data = {
# 'av': user_id,
# '__aaid': '0',
# '__user': user_id,
# '__a': '1',
# '__req': '2z',
# '__hs': '20161.HYP:comet_pkg.2.1...1',
# 'dpr': '2',
# '__ccg': 'EXCELLENT',
# '__rev': '1020896933',
# '__s': 'a6lpwr:v72pg5:lvg2er',
# '__hsi': '7481534814351260330',
# '__dyn': '7xeXzWK1ixt0mUyEqxemh0noeEb8nwgUao4u5QdwSwAyUco5S3O2Saw8i2S1DwUx60GE5O0BU2_CxS320qa2OU7m2210wEwgo9oO0-E4a3a4oaEnxO0Bo7O2l2Utwqo31wiE567Udo5qfK0zEkxe2GewyDwkUe9obrwh8lwUwgojUlDw-wUwxwjFovUaU3qxW2-awLyESE2KwwwOg2cwMwhEkxebwHwKG4UrwFg2fwxyo566k1FwgUjwOwWzUfHDzUiBG2OUqwjVqwLwHwa211zU523C',
# '__csr': 'geI2ex4D7NYfTfshvbN7i94jjWq6l9OqZ4EzVsQx2dqGAACCPZiqinWORrt9ajKnl5IGSiGZbJ4F4CoyWRhd5iZ95CAOtLy4jBhkjt29F8KiABJyqQ9yFIDjiZ7Lhi5HhCZrXDUCAum598gzEWuUR7ADHDqK-tUTymayF9ECjCBXG8h8iQmaQ4LzVECh1Omh1u4USjy8CmuiSFbhbCy8gyGVoSuWy94Wig-4EKmcG8yqBVoXGWZ2ECXAxmb-mFoLgGUvz9u8z9eqm7Hy9bCiHKU-3mUsyoKcxaGKaBLyqGm7-8xy2KcDAh8hxK4EiAx7xq8wGBxycxy2S79pZ29EPxy5FUd8y5E9EB1a3m8xe482qwzxC4o3ux11e1wKaJkWuqF898RwAwaxwaO3C8yEOum1LWghxy4o8m0z3o0wqU7C3DxO2R4xeShrBCUO740zoLCy4by8ct0Lwyxe0D8y68bWyE8o6608Dw9m3G2C0Fk0F8nwCx-0D8-7FUnG8wro10o0ey80zO0p3wdrl0Lye00JSE0fvE-0bWCw960k66p81X60it0oOKu0kN282wwv80D21FwbG0iC0iO1bwSwAw9i582sw1ta1izU0yOkFQ0ne04Z82Pg1Y80mSBt044g7W0hW1bgeES06Kk02dm0he08Cwm88o5h0TwiE0mry8Gu05JUhwCghG4C4aw5Kxq0Ao4y1MDDyVE6EAyy89A2CcdyHu',
# '__hsdp': '',
# '__hblp': '',
# '__comet_req': '15',
# 'fb_dtsg': dtsg_token,
# 'jazoest': '25421',
# 'lsd': 'sBdlvZ7xyxJeCPFduGOZlc',
# '__spin_r': '1020896933',
# '__spin_b': 'trunk',
# '__spin_t': '1741930566',
# 'fb_api_caller_class': 'RelayModern',
# 'fb_api_req_friendly_name': 'useCometUFICreateCommentMutation',
# 'variables': '{"feedLocation":"DEDICATED_COMMENTING_SURFACE","feedbackSource":110,"groupID":null,"input":{"client_mutation_id":"9","actor_id":"%s","attachments":%s,"feedback_id":"%s","formatting_style":null,"message":{"ranges":[],"text":"%s"},"reply_target_clicked":false,"attribution_id_v2":"ProfileCometTimelineListViewRoot.react,comet.profile.timeline.list,via_cold_start,1741930566987,158144,190055527696468,,","vod_video_timestamp":null,"is_tracking_encrypted":true,"tracking":["AZUnHF90UjvMroqev0xy6W_qNXEYnMdkDf2rOE-nm5QixlfrYaVfAvJUqno_2QpxLLNNH4DHVW3nOxZV7bQ8g-mFD5gsNi8pyl3TCLHIoaVbwibiTs-HdYDZiIkx1x3XW0xFcl8qgJvOjvbxKJfELSMgvIzV41LuBiCsetCc90f-Ix5k-9BspWI2AMnOMvYsWfxZ59yHxUtvL_D9lAdfopanDANfA5LeeDThbw5uaixa8GwokZpZGlwj0prU9qeQ9JWrOy6praN_WrvO2bZhFu3rhSBG_oKZ_bYZITmkN6uKs4eN4EVFhPfeVzGafPB5LoKIsY0Qs5zYTQdn8-KLvdYLHHhzcSxArKjActiRETyNQ8ZdZGThr0yyLy1weKmbRSKSoHSXC9eMJYF6ApK_zA2KFapQv_w2j9bIdnML9A9SbHYajroIofnXJ5eAHWv83TVbotU0gw-kl5zRzV25Am0tZ8-p7K8Two2ai0HxkF0MMTi60mI96lTmzLviyj8om76TLDB7-u-X5MLukgzHfqmTSnhd5KyVIrx77kLaXr4E-5mDMjPvAF5jcunXAJBjDl5rRmFze0rO1PgWwFEAvCvnjC8ftDH4VdRbW0wUMmQAMA","{\\"assistant_caller\\":\\"comet_above_composer\\",\\"conversation_guide_session_id\\":\\"d75579ed-48e4-4aac-8975-84cf698151f4\\",\\"conversation_guide_shown\\":null}"],"feedback_source":"DEDICATED_COMMENTING_SURFACE","idempotence_token":"client:%s","session_id":"cce85c8c-eb4e-4304-9e86-ac7d27d7f642"},"inviteShortLinkKey":null,"renderLocation":null,"scale":2,"useDefaultActor":false,"focusCommentID":null,"__relay_internal__pv__IsWorkUserrelayprovider":false}' % (
# user_id, attachments, post_id, message, uuid4_token
# ),
# 'server_timestamps': 'true',
# 'doc_id': '9389802714420896',
# }
# response = requests.post('https://www.facebook.com/api/graphql/', cookies=cookies, headers=headers, data=data)
# if response.status_code != 200:
# raise OperationFailed(f'评论异常 response: {response.text}')
#
# if response.json() and response.json().get('data'):
# return {'resp_id': response.json()['data']['comment_create']['feedback_comment_edge']['node']['id']}
# else:
# raise OperationFailed(f'参数错误, response: {response.text}')
2025-03-28 14:50:37 +08:00
2025-04-24 17:26:11 +08:00
def sleep ( a , b = None ) :
if not b :
return time . sleep ( a )
2025-03-28 14:50:37 +08:00
return time . sleep ( round ( random . uniform ( a , b ) , 1 ) )
2025-04-01 14:43:02 +08:00
def _full_screenshot ( ) :
im = ImageGrab . grab ( )
mem_file = io . BytesIO ( )
# 保存到内存中
im . save ( mem_file , " png " )
return mem_file
2025-03-28 14:50:37 +08:00
def update_windows_distinguish ( x = 1920 , y = 1080 ) :
""" 更改windows分辨率 """
if sys . platform == " win32 " :
devmode = pywintypes . DEVMODEType ( )
# screenSize = [1280,800]
screenSize = [ x , y ]
devmode . PelsWidth = screenSize [ 0 ]
devmode . PelsHeight = screenSize [ 1 ]
devmode . Fields = win32con . DM_PELSWIDTH | win32con . DM_PELSHEIGHT
win32api . ChangeDisplaySettings ( devmode , 0 )
def _change_language ( page ) :
2025-07-14 18:14:23 +08:00
sleep ( 2 , 3 )
2025-06-06 10:43:35 +08:00
# 找到顶部头像按钮并点击
page . wait_for_selector ( ' div[role= " button " ] svg image[style*= " height:40px " ][style*= " width:40px " ] ' ,
2025-06-24 13:53:59 +08:00
timeout = 10000 ) . click ( force = True )
2025-06-06 11:01:02 +08:00
sleep ( 1 , 2 )
2025-05-26 17:08:38 +08:00
# 点击设置图标
2025-07-14 18:14:23 +08:00
page . wait_for_selector ( ' //div[@role= " list " ]/div[@role= " listitem " ][1] ' , timeout = 30000 ) . click ( force = True )
2025-06-06 11:01:02 +08:00
sleep ( 1 , 2 )
2025-05-26 17:08:38 +08:00
# 点击语言
2025-06-24 13:53:59 +08:00
page . wait_for_selector ( ' //div[@role= " menu " ]/div[2] ' , timeout = 10000 ) . click ( force = True )
2025-06-06 11:01:02 +08:00
sleep ( 1 , 2 )
2025-06-06 10:43:35 +08:00
# 点击切换语言
2025-07-14 18:14:23 +08:00
page . query_selector_all ( ' //div[@role= " list " ]/div[@role= " listitem " ] ' ) [ 6 ] . click ( force = True )
2025-03-28 14:50:37 +08:00
sleep ( 1 , 2 )
2025-06-06 10:43:35 +08:00
# 点击英文
2025-06-24 13:53:59 +08:00
page . wait_for_selector ( ' //span[text()= " English (US) " ][1] ' , timeout = 10000 ) . click ( force = True )
2025-03-28 14:50:37 +08:00
sleep ( 3 , 5 )
def _edit_privacy ( page ) :
sleep ( 1 , 2 )
page . click ( ' //div[contains(@aria-label, " Edit privacy " )] ' )
sleep ( 1 , 2 )
page . click ( ' //div[@aria-label= " Select audience " ]//span[text()= " Public " ] ' )
page . click ( ' //div[@aria-label= " Done " ] ' )
sleep ( 1 , 2 )
2025-04-08 16:10:08 +08:00
def parse_cookies ( cookies ) :
if isinstance ( cookies , str ) :
try :
cookies = json . loads ( cookies )
if isinstance ( cookies , list ) :
return cookies
except ValueError :
c = [ ]
for i in cookies . split ( ' ; ' ) :
2025-04-14 14:45:16 +08:00
kv = i . strip ( ) . split ( ' = ' )
2025-04-08 16:10:08 +08:00
if kv :
k , v = kv [ 0 ] , kv [ 1 ]
c . append ( { ' name ' : k , ' value ' : v , ' domain ' : ' .facebook.com ' , ' path ' : ' / ' } )
return c
if isinstance ( cookies , dict ) :
return [
2025-04-23 15:28:02 +08:00
{ ' name ' : k , ' value ' : v , ' domain ' : ' .facebook.com ' , ' path ' : ' / ' } for k , v in cookies . items ( )
]
2025-04-08 16:10:08 +08:00
else :
return cookies
2025-05-27 10:33:32 +08:00
def check_freeze_account ( uid , max_retries = 3 , retry_delay = 2 , timeout = 5 ) :
"""
检查账号是否被冻结 , 超时自动重试
"""
2025-04-27 16:19:10 +08:00
headers = {
' user-agent ' : ' Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 ' ,
}
url = f " https://graph.facebook.com/ { uid } /picture?type=normal "
2025-05-27 10:33:32 +08:00
for attempt in range ( max_retries ) :
try :
response = requests . get ( url , headers = headers , allow_redirects = False , verify = False , timeout = timeout )
if response . status_code == 302 :
if response . headers . get ( ' Location ' ) == ' https://static.xx.fbcdn.net/rsrc.php/v1/yh/r/C5yt7Cqf3zU.jpg ' :
raise AuthException ( ' 该账号已被冻结 ' , ' frozen ' )
# 正常返回就 break
break
except ( requests . exceptions . Timeout , requests . exceptions . ConnectionError ) as e :
print ( f " 请求超时或连接错误,第 { attempt + 1 } 次重试: { e } " )
if attempt < max_retries - 1 :
time . sleep ( retry_delay )
else :
raise OperationFailed ( " 验证账号冻结失败 " ) # 最后一次失败则抛出异常
2025-05-08 15:35:41 +08:00
2025-05-23 15:20:16 +08:00
def check_account_status ( page , cookies ) :
# 检查是否冻结
cookies = { i [ ' name ' ] : i [ ' value ' ] for i in cookies }
uid = cookies [ ' c_user ' ]
check_freeze_account ( uid )
2025-05-08 15:35:41 +08:00
# 校验Cookies 是否失效
# 登录页面判断
2025-07-08 15:52:44 +08:00
retry_goto ( page , ' https://www.facebook.com ' )
time . sleep ( 3 )
2025-05-08 15:35:41 +08:00
login_btn = page . query_selector_all ( ' //button[@name= " login " ] ' )
if login_btn :
raise AuthException ( ' 该账户登录状态失效 ' , ' invalid ' )
2025-07-08 15:52:44 +08:00
# 判断是否被检测到自动化,这种情况只需要点击按钮就可以继续
2025-07-17 16:26:25 +08:00
if page . query_selector (
' //span[text()= " We suspect automated behaviour on your account " or text()= " We suspect automated behavior on your account " ] ' ) is not None :
2025-07-08 15:52:44 +08:00
page . click ( ' //span[text()= " Dismiss " ] ' )
time . sleep ( 3 )
retry_goto ( page , ' https://www.facebook.com ' )
2025-05-30 15:09:10 +08:00
# 判断是否为英文
lang = page . locator ( ' html ' ) . get_attribute ( ' lang ' )
if lang != " en " :
try :
_change_language ( page )
except TimeoutError :
raise OperationFailed ( ' 更改语言异常 ' )
2025-04-08 16:10:08 +08:00
2025-03-28 14:50:37 +08:00
class RLock ( threading . _RLock ) :
pass
lock = RLock ( )
2025-07-08 15:52:44 +08:00
login_semaphore = threading . Semaphore ( 2 )
2025-03-28 14:50:37 +08:00
2025-04-14 14:45:16 +08:00
def playwright_like ( cookies , target_url ) :
2025-03-28 14:50:37 +08:00
path = os . path . join ( BASE_PATH , ' chrome ' , ' 130-0008 ' , ' chrome.exe ' )
with lock :
with sync_playwright ( ) as playwright :
update_windows_distinguish ( )
browser = playwright . chromium . launch (
headless = False , args = [ ' --start-maximized ' ] , executable_path = path
)
context = browser . new_context ( no_viewport = True )
2025-04-08 16:10:08 +08:00
context . add_cookies ( parse_cookies ( cookies ) )
2025-03-28 14:50:37 +08:00
page = context . new_page ( )
2025-07-08 15:52:44 +08:00
check_account_status ( page , parse_cookies ( cookies ) )
2025-03-28 14:50:37 +08:00
url = ' https://facebook.com '
2025-04-08 16:10:08 +08:00
try :
2025-07-08 15:52:44 +08:00
2025-04-08 16:10:08 +08:00
page . goto ( url )
2025-05-08 15:15:39 +08:00
time . sleep ( random . randint ( 3 , 10 ) )
2025-04-14 14:45:16 +08:00
if ' permalink.php?story_fbid ' in target_url or ' /posts/ ' in target_url :
2025-04-08 16:10:08 +08:00
# 文字或图片类型
button_xpath = ' //div[@class= " __fb-light-mode x1n2onr6 x1vjfegm " ]//span[@data-ad-rendering-role= " like_button " ] '
2025-05-22 12:46:37 +08:00
elif ' watch/?v ' in target_url or ' /videos/ ' in target_url :
# 视频类型, 视频类型,
2025-04-08 16:10:08 +08:00
button_xpath = ' //span[@data-ad-rendering-role= " like_button " ][1] '
2025-05-22 12:46:37 +08:00
elif ' /permalink/ ' in target_url :
# 永久链接
button_xpath = ' //*[@role= " dialog " ]//span[@data-ad-rendering-role= " like_button " ] '
2025-04-14 14:45:16 +08:00
elif ' /reel/ ' in target_url :
2025-04-08 16:10:08 +08:00
# 短视频类型
button_xpath = ' //div[@class= " __fb-dark-mode x1afcbsf x1uhb9sk x1swf91x " ]//div[@aria-label= " Like " ]//div[@aria-label= " Like " ] '
else :
2025-04-14 14:45:16 +08:00
raise OperationFailed ( f ' 不支持的帖子类型POST: { target_url } ' )
2025-03-28 14:50:37 +08:00
2025-04-14 14:45:16 +08:00
page . goto ( target_url )
2025-04-08 16:10:08 +08:00
sleep ( 1 , 2 )
2025-05-22 10:42:29 +08:00
# 判断按钮是否存在
button = page . query_selector ( button_xpath )
if button :
# 滚动到按钮所在处
button . scroll_into_view_if_needed ( )
# 判断按钮是否已经点过赞
if button . get_attribute ( ' style ' ) == " " or button . get_attribute ( ' style ' ) is None :
# 未点过赞进行点赞操作
button . click ( force = True )
else :
raise OperationFailed ( " 未找到点赞按钮 " )
2025-04-08 16:10:08 +08:00
time . sleep ( 10 )
except Error as e :
raise OperationFailed ( f ' 操作超时,请重试 { e } ' )
2025-03-28 14:50:37 +08:00
2025-04-14 14:45:16 +08:00
screenshot_content = _full_screenshot ( )
2025-03-28 14:50:37 +08:00
context . close ( )
browser . close ( )
2025-04-01 14:43:02 +08:00
key = f ' { uuid . uuid4 ( ) } .png '
2025-04-14 14:45:16 +08:00
put_object ( key , screenshot_content )
return {
' response_url ' : target_url ,
2025-04-23 15:28:02 +08:00
' screenshot_key ' : key
2025-04-14 14:45:16 +08:00
}
2025-03-28 14:50:37 +08:00
2025-04-08 16:10:08 +08:00
def playwright_post ( cookies , content , image_key = None ) :
2025-03-28 14:50:37 +08:00
path = os . path . join ( BASE_PATH , ' chrome ' , ' 130-0008 ' , ' chrome.exe ' )
with lock :
with sync_playwright ( ) as playwright :
update_windows_distinguish ( )
browser = playwright . chromium . launch (
headless = False , args = [ ' --start-maximized ' ] , executable_path = path
)
context = browser . new_context ( no_viewport = True )
2025-04-08 16:10:08 +08:00
context . add_cookies ( parse_cookies ( cookies ) )
2025-03-28 14:50:37 +08:00
page = context . new_page ( )
2025-07-08 15:52:44 +08:00
check_account_status ( page , parse_cookies ( cookies ) )
2025-03-28 14:50:37 +08:00
url = ' https://facebook.com '
2025-04-08 16:10:08 +08:00
try :
page . goto ( url )
2025-05-08 15:15:39 +08:00
time . sleep ( random . randint ( 3 , 10 ) )
2025-03-28 14:50:37 +08:00
time . sleep ( 5 )
2025-04-08 16:10:08 +08:00
if image_key :
filename = image_key . split ( ' / ' ) [ - 1 ]
file_path = os . path . join ( BASE_PATH , ' files ' , filename )
client . fget_object ( BUCKET , image_key , file_path )
page . click ( ' //span[text()= " Photo/video " ] ' )
sleep ( 1 , 2 )
with page . expect_file_chooser ( ) as fc_info :
page . click ( ' //span[text()= " Add photos/videos " ] ' )
file_chooser = fc_info . value
file_chooser . set_files ( file_path )
time . sleep ( 5 )
if not image_key :
page . click ( ''' //span[contains(text(), " What ' s on your mind " )] ''' )
_edit_privacy ( page )
2025-04-24 15:55:08 +08:00
page . type ( ''' //div[contains(@aria-placeholder, " What ' s on your mind " )] ''' , content , delay = 50 )
2025-04-08 16:10:08 +08:00
page . click ( ' //div[@aria-label= " Post " ] ' )
time . sleep ( 15 )
2025-04-23 15:28:02 +08:00
post_index = page . locator ( ' //div[@aria-posinset= " 1 " ]//a[@role= " link " ] ' ) . nth ( 2 )
post_index . click ( )
2025-04-08 16:10:08 +08:00
time . sleep ( 5 )
2025-04-23 15:28:02 +08:00
page . reload ( )
post_url = page . url
2025-04-08 16:10:08 +08:00
except Error as e :
raise OperationFailed ( f ' 操作超时,请重试 { e } ' )
2025-03-31 15:50:47 +08:00
2025-04-14 14:45:16 +08:00
screenshot_content = _full_screenshot ( )
2025-04-01 14:43:02 +08:00
if image_key :
os . remove ( file_path )
2025-03-28 14:50:37 +08:00
context . close ( )
browser . close ( )
2025-04-01 14:43:02 +08:00
key = f ' { uuid . uuid4 ( ) } .png '
2025-04-14 14:45:16 +08:00
put_object ( key , screenshot_content )
2025-04-23 15:28:02 +08:00
return { ' response_url ' : post_url , ' screenshot_key ' : key }
2025-03-28 14:50:37 +08:00
2025-04-14 14:45:16 +08:00
def playwright_comment ( cookies , target_url , content , image_key = None ) :
2025-03-28 14:50:37 +08:00
path = os . path . join ( BASE_PATH , ' chrome ' , ' 130-0008 ' , ' chrome.exe ' )
with lock :
with sync_playwright ( ) as playwright :
update_windows_distinguish ( )
browser = playwright . chromium . launch (
headless = False , args = [ ' --start-maximized ' ] , executable_path = path
)
context = browser . new_context ( no_viewport = True )
2025-04-08 16:10:08 +08:00
context . add_cookies ( parse_cookies ( cookies ) )
2025-03-28 14:50:37 +08:00
page = context . new_page ( )
2025-07-08 15:52:44 +08:00
check_account_status ( page , parse_cookies ( cookies ) )
try :
retry_goto ( page , target_url )
2025-03-28 14:50:37 +08:00
sleep ( 1 , 2 )
2025-05-21 17:37:14 +08:00
if ' permalink.php?story_fbid ' in target_url or ' /posts/ ' in target_url or " /permalink/ " in target_url :
2025-04-08 16:10:08 +08:00
# 文字或图片类型
2025-06-27 15:45:32 +08:00
input_xpath = ' //div[@role= " dialog " ]//span[@data-ad-rendering-role= " comment_button " ] '
2025-04-08 16:10:08 +08:00
attach_xpath = ' //div[@id= " focused-state-actions-list " ]//div[@aria-label= " Attach a photo or video " ] '
comment_xpath = ' //div[@aria-label= " Comment " ] '
page . click ( input_xpath )
sleep ( 1 , 2 )
2025-05-21 17:11:31 +08:00
elif ' watch/?v ' in target_url or ' /videos/ ' in target_url :
2025-04-08 16:10:08 +08:00
# 视频类型
input_xpath = ' //div[@aria-label= " Write a comment… " ] '
attach_xpath = ' //div[@aria-label= " Attach a photo or video " ] '
comment_xpath = ' //div[@aria-label= " Comment " ] '
2025-04-14 14:45:16 +08:00
elif ' /reel/ ' in target_url :
2025-04-08 16:10:08 +08:00
# 短视频类型
input_xpath = ' //div[@aria-label= " Write a comment… " ] '
attach_xpath = ' //div[@aria-label= " Attach a photo or video " ] '
comment_xpath = ' //div[@role= " complementary " ]//div[@aria-label= " Comment " ] '
page . click ( ' //div[@aria-label= " Comment " ][1] ' )
sleep ( 1 , 2 )
else :
2025-04-14 14:45:16 +08:00
raise OperationFailed ( f ' 不支持的帖子类型POST: { target_url } ' )
2025-04-08 16:10:08 +08:00
if image_key :
filename = image_key . split ( ' / ' ) [ - 1 ]
file_path = os . path . join ( BASE_PATH , ' files ' , filename )
client . fget_object ( BUCKET , image_key , file_path )
sleep ( 1 , 2 )
with page . expect_file_chooser ( ) as fc_info :
page . click ( attach_xpath )
file_chooser = fc_info . value
file_chooser . set_files ( file_path )
time . sleep ( 5 )
2025-04-24 15:55:08 +08:00
page . type ( input_xpath , content , delay = 50 )
2025-04-08 16:10:08 +08:00
page . click ( comment_xpath )
2025-03-28 14:50:37 +08:00
time . sleep ( 5 )
2025-04-08 16:10:08 +08:00
except Error as e :
raise OperationFailed ( f ' 操作超时,请重试 { e } ' )
2025-03-28 14:50:37 +08:00
2025-04-14 14:45:16 +08:00
screenshot_content = _full_screenshot ( )
2025-04-01 14:43:02 +08:00
if image_key :
os . remove ( file_path )
2025-03-28 14:50:37 +08:00
context . close ( )
browser . close ( )
2025-04-01 14:43:02 +08:00
key = f ' { uuid . uuid4 ( ) } .png '
2025-04-14 14:45:16 +08:00
put_object ( key , screenshot_content )
return {
' response_url ' : target_url ,
2025-04-23 15:28:02 +08:00
' screenshot_key ' : key
2025-04-14 14:45:16 +08:00
}
2025-04-01 14:43:02 +08:00
2025-03-28 14:50:37 +08:00
2025-04-08 16:10:08 +08:00
def playwright_get_user_profile ( cookies , username = None ) :
2025-03-28 14:50:37 +08:00
path = os . path . join ( BASE_PATH , ' chrome ' , ' 130-0008 ' , ' chrome.exe ' )
2025-07-08 15:52:44 +08:00
with login_semaphore :
2025-03-28 14:50:37 +08:00
with sync_playwright ( ) as playwright :
update_windows_distinguish ( )
browser = playwright . chromium . launch (
2025-07-17 16:27:59 +08:00
headless = True , args = [ ' --start-maximized ' ] , executable_path = path
2025-03-28 14:50:37 +08:00
)
context = browser . new_context ( no_viewport = True )
2025-04-08 16:10:08 +08:00
context . add_cookies ( parse_cookies ( cookies ) )
2025-03-28 14:50:37 +08:00
page = context . new_page ( )
2025-07-08 15:52:44 +08:00
check_account_status ( page , parse_cookies ( cookies ) )
2025-07-17 16:26:25 +08:00
cookies_dict = { i [ ' name ' ] : i [ ' value ' ] for i in parse_cookies ( cookies ) }
uid = cookies_dict [ " c_user " ]
url = f ' https://accountscenter.facebook.com/profiles/ { uid } '
2025-04-08 16:10:08 +08:00
try :
2025-07-08 15:52:44 +08:00
retry_goto ( page , url )
2025-05-08 15:15:39 +08:00
time . sleep ( random . randint ( 3 , 10 ) )
2025-07-17 16:26:25 +08:00
profile_pic_url = page . query_selector ( ' //*[@preserveAspectRatio= " xMidYMid slice " ] ' ) . get_attribute (
2025-04-23 15:28:02 +08:00
' xlink:href ' )
2025-07-17 16:26:25 +08:00
page . query_selector ( ' //div[@role= " dialog " ]//div[@role= " listitem " ] ' ) . click ( )
firstname = page . locator ( ' //label[text()= " First name " ]/../input ' ) . input_value ( )
lastname = page . locator ( ' //label[text()= " Last name " ]/../input ' ) . input_value ( )
2025-04-08 16:10:08 +08:00
except Error as e :
raise OperationFailed ( f ' 操作超时,请重试 { e } ' )
2025-03-28 14:50:37 +08:00
context . close ( )
browser . close ( )
response = requests . get (
url = profile_pic_url ,
2025-04-23 15:28:02 +08:00
headers = {
' user-agent ' : ' Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 ' } ,
2025-04-01 14:43:02 +08:00
# proxies={
# 'http': 'http://127.0.0.1:10889',
# 'https': 'http://127.0.0.1:10889',
# }
2025-03-28 14:50:37 +08:00
)
bio = io . BytesIO ( response . content )
2025-07-17 16:26:25 +08:00
key = f " { lastname + firstname . replace ( ' ' , ' _ ' ) } .png "
2025-04-01 14:43:02 +08:00
put_object ( key , bio )
2025-07-17 16:26:25 +08:00
return { ' avatar_key ' : key , ' username ' : lastname + firstname , ' first_name ' : firstname , ' last_name ' : lastname }
2025-03-28 14:50:37 +08:00
2025-04-14 14:45:16 +08:00
def playwright_set_user_profile ( cookies , username = None , first_name = None , last_name = None , avatar_key = None ) :
if not first_name and not last_name and not avatar_key and not username :
2025-03-28 14:50:37 +08:00
return
path = os . path . join ( BASE_PATH , ' chrome ' , ' 130-0008 ' , ' chrome.exe ' )
2025-07-08 16:55:49 +08:00
with login_semaphore :
2025-03-28 14:50:37 +08:00
with sync_playwright ( ) as playwright :
update_windows_distinguish ( )
browser = playwright . chromium . launch (
2025-07-08 16:55:49 +08:00
headless = True , args = [ ' --start-maximized ' ] , executable_path = path
2025-03-28 14:50:37 +08:00
)
context = browser . new_context ( no_viewport = True )
2025-04-08 16:10:08 +08:00
context . add_cookies ( parse_cookies ( cookies ) )
2025-03-28 14:50:37 +08:00
page = context . new_page ( )
2025-07-08 15:52:44 +08:00
check_account_status ( page , parse_cookies ( cookies ) )
2025-04-08 16:10:08 +08:00
try :
url = ' https://accountscenter.facebook.com/?entry_point=app_settings '
2025-07-08 15:52:44 +08:00
retry_goto ( page , url )
2025-04-08 16:10:08 +08:00
page . locator ( ' //div[@role= " list " ]/div ' ) . first . click ( )
2025-04-14 14:45:16 +08:00
if username :
page . click ( ' //a[@aria-label= " Username " ] ' )
page . locator ( ' //input ' ) . first . fill ( username )
page . click ( ' //span[text()= " Done " ] ' )
if first_name or last_name :
if first_name and last_name :
2025-04-08 16:10:08 +08:00
# 修改名称
page . click ( ' //a[@aria-label= " Name " ] ' )
2025-04-14 14:45:16 +08:00
page . locator ( ' //input ' ) . first . fill ( first_name )
page . locator ( ' //input ' ) . last . fill ( last_name )
2025-04-08 16:10:08 +08:00
page . locator ( ' //div[@role= " button " ] ' ) . last . click ( )
page . click ( ' //span[text()= " Done " ] ' )
else :
raise OperationFailed ( ' 名称中必须有First name和Last name ' )
2025-04-14 14:45:16 +08:00
if avatar_key :
2025-04-08 16:10:08 +08:00
# 修改头像
page . click ( ' //a[@aria-label= " Profile picture " ] ' )
2025-04-14 14:45:16 +08:00
filename = avatar_key . split ( ' / ' ) [ - 1 ]
2025-04-08 16:10:08 +08:00
file_path = os . path . join ( BASE_PATH , ' files ' , filename )
2025-04-14 14:45:16 +08:00
client . fget_object ( BUCKET , avatar_key , file_path )
2025-04-08 16:10:08 +08:00
sleep ( 1 , 2 )
with page . expect_file_chooser ( ) as fc_info :
page . click ( ' //div[text()= " Upload new photo " ] ' )
file_chooser = fc_info . value
file_chooser . set_files ( file_path )
page . locator ( ' //span[text()= " Save " ] ' ) . last . click ( )
time . sleep ( 5 )
os . remove ( file_path )
except Error as e :
raise OperationFailed ( f ' 操作超时,请重试 { e } ' )
2025-03-28 14:50:37 +08:00
context . close ( )
browser . close ( )
2025-04-14 14:45:16 +08:00
return {
' username ' : username ,
' first_name ' : first_name ,
' last_name ' : last_name ,
' avatar_key ' : avatar_key ,
}
2025-03-28 14:50:37 +08:00
2025-04-08 16:10:08 +08:00
def playwright_check_account_cookies ( cookies ) :
2025-03-31 15:50:47 +08:00
path = os . path . join ( BASE_PATH , ' chrome ' , ' 130-0008 ' , ' chrome.exe ' )
2025-07-08 15:52:44 +08:00
with login_semaphore :
2025-03-31 15:50:47 +08:00
with sync_playwright ( ) as playwright :
update_windows_distinguish ( )
browser = playwright . chromium . launch (
2025-07-08 16:55:49 +08:00
headless = True , args = [ ' --start-maximized ' ] , executable_path = path
2025-03-31 15:50:47 +08:00
)
context = browser . new_context ( no_viewport = True )
2025-04-08 16:10:08 +08:00
context . add_cookies ( parse_cookies ( cookies ) )
2025-03-31 15:50:47 +08:00
page = context . new_page ( )
2025-04-24 17:26:11 +08:00
check_account_status ( page , parse_cookies ( cookies ) )
2025-07-08 15:52:44 +08:00
2025-03-31 15:50:47 +08:00
context . close ( )
browser . close ( )
2025-04-08 16:10:08 +08:00
return { }
2025-03-31 15:50:47 +08:00
2025-05-08 11:59:12 +08:00
def get_login_continue_btn ( page ) :
bs = page . query_selector_all ( ' //span[text()= " Continue " ] ' )
for b in bs :
if b . is_visible ( ) and b . is_enabled ( ) :
return b
return None
2025-05-26 17:08:38 +08:00
def retry_goto ( page : " Page " , url : str , max_retries : int = 3 , retry_delay : int = 5 ) :
"""
Attempts to navigate to a URL with retries on timeout using synchronous Playwright .
Args :
page : The synchronous Playwright Page object .
url : The URL to navigate to .
max_retries : Maximum number of retry attempts ( including the initial attempt ) .
retry_delay : Delay in seconds between retries .
"""
# ... potentially other code before goto ...
for attempt in range ( max_retries ) :
try :
if attempt > 0 :
logger . info ( f " Retrying navigation to { url } , attempt { attempt + 1 } / { max_retries } ... " )
else :
logger . info ( f " Navigating to { url } , initial attempt... " )
# Make the synchronous goto call within the try block
# Use wait_until='load' as in your traceback, or adjust if needed
2025-05-27 09:19:05 +08:00
page . goto ( url , timeout = 30000 , wait_until = " domcontentloaded " ) # Use the synchronous call
2025-05-26 17:08:38 +08:00
print ( f " Successfully navigated to { url } on attempt { attempt + 1 } " )
break # Navigation was successful, exit the retry loop
except TimeoutError as e :
print ( f " Navigation to { url } timed out on attempt { attempt + 1 } . " )
if attempt < max_retries - 1 :
print ( f " Waiting { retry_delay } seconds before retrying... " )
time . sleep ( retry_delay ) # Use synchronous sleep
else :
print ( f " All { max_retries } attempts failed for { url } . " )
# If all retries fail, re-raise the exception
raise e
except Exception as e :
# Catch any other unexpected errors during goto
print ( f " An unexpected error occurred during navigation to { url } on attempt { attempt + 1 } : { e } " )
# Decide if other exceptions should also trigger retries
# For now, we'll just re-raise other exceptions immediately
raise e
2025-04-24 15:55:08 +08:00
def playwright_login ( username , password , code_2fa = None ) :
2025-05-26 17:08:38 +08:00
logger . info ( f " 登录账号 { username } " )
2025-05-23 15:20:16 +08:00
# 检查是否冻结
check_freeze_account ( username )
2025-04-24 15:55:08 +08:00
path = os . path . join ( BASE_PATH , ' chrome ' , ' 130-0008 ' , ' chrome.exe ' )
2025-07-08 15:52:44 +08:00
with login_semaphore :
2025-04-24 15:55:08 +08:00
with sync_playwright ( ) as playwright :
update_windows_distinguish ( )
browser = playwright . chromium . launch (
2025-04-24 17:26:11 +08:00
headless = False , args = [ ' --start-maximized ' ] , executable_path = path
2025-04-24 15:55:08 +08:00
)
2025-05-26 17:08:38 +08:00
random_user_agent = UserAgent ( ) . getBrowser ( " Chrome " ) . get ( " useragent " )
logger . info ( f " 使用ua= { random_user_agent } " )
context = browser . new_context ( no_viewport = True , user_agent = random_user_agent )
2025-04-25 15:21:31 +08:00
# 设置语言为英文
context . add_cookies ( [
{
" name " : " locale " ,
" value " : " en_US " ,
" domain " : " .facebook.com " ,
" path " : " / " ,
" expires " : - 1 ,
" httpOnly " : True ,
" secure " : False ,
} ,
] )
2025-05-26 17:08:38 +08:00
page = context . new_page ( )
url = ' https://www.facebook.com '
retry_goto ( page , url )
page . locator ( ' //input[@id= " email " ] ' ) . type ( username , delay = 30 )
2025-05-23 15:20:16 +08:00
time . sleep ( random . randint ( 1 , 3 ) )
2025-05-26 17:08:38 +08:00
page . locator ( ' //input[@id= " pass " ] ' ) . type ( password , delay = 30 )
2025-05-23 15:20:16 +08:00
time . sleep ( random . randint ( 1 , 3 ) )
2025-05-26 17:08:38 +08:00
page . click ( ' //button[@name= " login " ] ' )
page . wait_for_load_state ( )
time . sleep ( random . randint ( 3 , 5 ) )
arkose_captcha = page . query_selector ( ' #arkose-captcha ' )
if arkose_captcha :
logger . info ( f " 账号 { username } 弹语音识别验证 " )
raise OperationFailed ( " 操作失败 " )
arkose_captcha = page . query_selector ( ' #captcha-recaptcha ' )
if arkose_captcha :
logger . info ( f " 账号 { username } 弹谷歌验证 " )
raise OperationFailed ( " 操作失败 " )
2025-04-25 15:21:31 +08:00
2025-05-26 10:44:16 +08:00
captcha_img = page . query_selector ( ' //img[contains(@src, " captcha " )] ' )
2025-05-21 17:57:08 +08:00
if captcha_img :
2025-05-26 17:08:38 +08:00
logger . info ( f " 账号 { username } 需要验证 " )
2025-05-26 10:44:16 +08:00
data = {
' user ' : ' ycxxkj ' ,
' pass2 ' : ' B4DBF06831577C6558F823879061626C ' ,
' softid ' : ' 951004 ' ,
' codetype ' : ' 3006 ' ,
}
response = requests . post ( ' http://upload.chaojiying.net/Upload/Processing.php ' , data = data ,
timeout = 60 , files = { ' userfile ' : ( ' ccc.jpg ' , captcha_img . screenshot ( ) ) } )
2025-05-21 17:57:08 +08:00
result = response . json ( )
if result [ ' err_no ' ] == 0 :
pic_str = result [ ' pic_str ' ]
page . fill ( ' //img[contains(@src, " captcha " )]/parent::div/parent::div//input ' , pic_str )
page . locator ( ' //img[contains(@src, " captcha " )]/parent::div/parent::div/div ' ) . nth ( 4 ) . click ( )
else :
raise OperationFailed ( ' 验证码解析错误 ' )
2025-05-26 17:08:38 +08:00
# 检查是否还有验证码, 隐式等待60秒
page . wait_for_selector (
' //span[@class= " x1lliihq x1plvlek xryxfnj x1n2onr6 x1ji0vk5 x18bv5gf x193iq5w xeuugli x1fj9vlw x13faqbe x1vvkbs x1s928wv xhkezso x1gmr53x x1cpjm7i x1fgarty x1943h6x x1qo61fq x81x36d xa4e6wy x1rhavg7 xzsf02u x1yc453h xudqn12 x3x7a5m x1yztbdb " ] ' ,
timeout = 60000 )
h2 = page . wait_for_selector (
' //div[@class= " x1n2onr6 x1ja2u2z x9f619 x78zum5 xdt5ytf x2lah0s x193iq5w " ]//h2/span ' , timeout = 60000 )
2025-04-25 15:21:31 +08:00
if h2 is None :
raise OperationFailed ( ' 页面有误 ' )
else :
2025-05-08 11:59:12 +08:00
text_contexts = [
" Go to your authentication app " ,
" Check your notifications on another device "
]
if not h2 . text_content ( ) in text_contexts :
2025-05-26 17:08:38 +08:00
logger . info ( f " 账号 { username } 操作失败 " )
2025-04-25 15:21:31 +08:00
raise OperationFailed ( " 操作失败 " )
2025-04-24 17:26:11 +08:00
auth_span = page . query_selector ( ' //span[text()= " Try Another Way " or text()= " Try another way " ] ' )
2025-04-24 15:55:08 +08:00
if auth_span :
if not code_2fa :
raise OperationFailed ( ' 缺少2FA密钥 ' )
auth_code = pyotp . TOTP ( code_2fa ) . now ( )
auth_span . click ( )
2025-05-08 11:59:12 +08:00
time . sleep ( 1 )
2025-04-24 15:55:08 +08:00
page . click ( ' //div[text()= " Authentication app " ] ' )
2025-05-08 11:59:12 +08:00
time . sleep ( 1 )
# 可能会有多个Continue
btn = get_login_continue_btn ( page )
if btn is None :
raise OperationFailed ( " 操作失败 " )
btn . click ( )
2025-04-24 15:55:08 +08:00
time . sleep ( 1 )
page . locator ( ' //label[text()= " Code " ]/preceding-sibling::input ' ) . fill ( auth_code )
page . click ( ' //span[text()= " Continue " ] ' )
2025-05-26 17:08:38 +08:00
# 等待登录成功页面出来
page . wait_for_selector (
" xpath=//h2[normalize-space()= ' You’ re logged in. Trust this device? ' ] or //span[text()= ' Save ' ] " ,
timeout = 60000 )
2025-04-24 15:55:08 +08:00
c = { i [ ' name ' ] : i [ ' value ' ] for i in context . cookies ( ) }
2025-05-23 15:20:16 +08:00
if c [ " c_user " ] is None :
raise OperationFailed ( " 操作失败 " )
2025-05-26 17:08:38 +08:00
logger . info ( f " 登录账号 { username } 登录成功 " )
2025-05-23 15:20:16 +08:00
2025-04-24 15:55:08 +08:00
context . close ( )
browser . close ( )
return { ' cookies ' : json . dumps ( c ) }
2025-05-27 08:52:24 +08:00
def playwright_m_login ( username , password , code_2fa = None ) :
logger . info ( f " 登录账号 { username } " )
# 检查是否冻结
check_freeze_account ( username )
2025-05-27 10:33:32 +08:00
logger . info ( f " 账号 { username } 未冻结 " )
2025-05-27 08:52:24 +08:00
path = os . path . join ( BASE_PATH , ' chrome ' , ' 130-0008 ' , ' chrome.exe ' )
with lock :
with sync_playwright ( ) as playwright :
update_windows_distinguish ( )
browser = playwright . chromium . launch (
2025-07-08 16:55:49 +08:00
headless = True , args = [ ' --start-maximized ' ] , executable_path = path
2025-05-27 08:52:24 +08:00
)
# random_user_agent = UserAgent().getBrowser(["Chrome Mobile iOS"]).get("useragent")
random_user_agent = " Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Mobile Safari/537.36 "
logger . info ( f " 使用ua= { random_user_agent } " )
context = browser . new_context ( no_viewport = True , user_agent = random_user_agent )
# 设置语言为英文
context . add_cookies ( [
{
" name " : " locale " ,
" value " : " en_US " ,
" domain " : " .facebook.com " ,
" path " : " / " ,
" expires " : - 1 ,
" httpOnly " : True ,
" secure " : False ,
} ,
] )
page = context . new_page ( )
2025-05-27 09:19:05 +08:00
url = ' https://m.facebook.com/login '
2025-05-27 08:52:24 +08:00
retry_goto ( page , url )
2025-05-27 10:33:32 +08:00
# 概率会跳到首页
have_account = ' div[role= " button " ][aria-label= " I already have an account " ] '
# 用户名输入框框
input_email = " input#m_login_email "
2025-05-27 08:52:24 +08:00
2025-05-27 10:33:32 +08:00
try :
page . wait_for_selector ( f ' { have_account } , { input_email } ' , timeout = 60000 )
except Exception as e :
logger . error ( f " 页面加载异常, 未定位到按钮 " , exc_info = True )
raise OperationFailed ( " 系统异常 " )
hava_account_btn = page . query_selector ( have_account )
if hava_account_btn :
hava_account_btn . click ( )
page . wait_for_selector ( f ' { input_email } ' , timeout = 60000 ) . type ( username , delay = 30 )
time . sleep ( 1 )
page . wait_for_selector ( f ' //input[@id= " m_login_password " ] ' , timeout = 60000 ) . type ( password , delay = 30 )
page . click ( ' div[aria-label= " Log in " ] ' )
2025-05-27 13:53:20 +08:00
success_login_selector1 = ' span:has-text( " Check your notifications on another device " ) '
success_login_selector2 = ' span:has-text( " Go to your authentication app " ) '
2025-05-27 10:33:32 +08:00
failed_login_selector = ' div[data-bloks-name= " bk.components.dialog.Dialog " ] > div[aria-label= " Wrong Credentials " ] > div:nth-child(1) '
2025-06-26 21:46:36 +08:00
# 等成功或失败
2025-06-27 09:33:25 +08:00
page . wait_for_selector ( f ' { success_login_selector1 } , { success_login_selector2 } , { failed_login_selector } ' ,
2025-05-27 13:53:20 +08:00
timeout = 60000 )
2025-05-27 08:52:24 +08:00
# 判断是否失败
failed_login = page . query_selector ( failed_login_selector )
if failed_login :
# 登录失败, 返回失败信息
2025-05-27 09:19:05 +08:00
logger . info ( f " 用户名: { username } 密码错误 { failed_login . text_content ( ) } " )
2025-05-27 08:52:24 +08:00
raise OperationFailed ( failed_login . text_content ( ) )
2025-05-27 13:53:20 +08:00
# 判断是否有多重验证
success_login1 = page . query_selector ( success_login_selector1 )
if success_login1 :
# 点击尝试另一种方式验证账号
page . query_selector ( ' div[role= " button " ][aria-label= " Try another way " ] ' ) . click ( )
2025-05-27 10:33:32 +08:00
2025-05-27 13:53:20 +08:00
# 点击选择app验证
page . wait_for_selector (
' span[data-bloks-name= " bk.components.TextSpan " ]:has-text( " Authentication app " ) ' ) . click ( )
2025-05-27 10:33:32 +08:00
2025-05-27 13:53:20 +08:00
# 点击继续
page . query_selector ( ' div[role= " button " ][aria-label= " Continue " ] ' ) . click ( )
2025-05-27 10:33:32 +08:00
# 等待页面
2025-05-27 13:53:20 +08:00
page . wait_for_selector ( ' span:has-text( " Go to your authentication app " ) ' , timeout = 60000 )
2025-05-27 10:33:32 +08:00
# 输入2faCode
auth_code = pyotp . TOTP ( code_2fa ) . now ( )
page . wait_for_selector ( ' input[aria-label= " Code " ][type= " text " ] ' , timeout = 60000 ) . fill ( auth_code )
# 点击继续
page . query_selector ( ' div[role= " button " ][aria-label= " Continue " ] ' ) . click ( )
# 等待登录成功
2025-05-30 14:01:29 +08:00
page . wait_for_selector ( ' img[data-bloks-name= " bk.components.Image " ][src*= " .fbcdn.net/v/t " ] ' , timeout = 60000 )
2025-05-27 10:33:32 +08:00
# 成功
2025-05-27 08:52:24 +08:00
logger . info ( f " 用户名: { username } 账号密码正确 " )
2025-05-27 10:33:32 +08:00
c = { i [ ' name ' ] : i [ ' value ' ] for i in context . cookies ( ) }
if c [ " c_user " ] is None :
raise OperationFailed ( " 操作失败 " )
logger . info ( f " 登录账号 { username } 登录成功 " )
context . close ( )
browser . close ( )
return { ' cookies ' : json . dumps ( c ) }
2025-05-27 08:52:24 +08:00
2025-05-30 14:01:29 +08:00
def playwright_share ( cookies , target_url , content ) :
path = os . path . join ( BASE_PATH , ' chrome ' , ' 130-0008 ' , ' chrome.exe ' )
with lock :
with sync_playwright ( ) as playwright :
update_windows_distinguish ( )
browser = playwright . chromium . launch (
headless = False , args = [ ' --start-maximized ' ] , executable_path = path
)
context = browser . new_context ( no_viewport = True )
context . add_cookies ( parse_cookies ( cookies ) )
page = context . new_page ( )
try :
page . goto ( target_url )
2025-06-06 10:43:35 +08:00
check_account_status ( page , parse_cookies ( cookies ) )
2025-06-27 09:34:59 +08:00
if ' permalink.php?story_fbid ' in target_url or ' /posts/ ' in target_url or " /permalink/ " in target_url :
2025-05-30 14:01:29 +08:00
# 文字或图片类型
share_button = ' //div[@aria-label= " Send this to friends or post it on your profile. " ]//span[@data-ad-rendering-role= " share_button " ] '
input_box = ' //form[@method= " POST " and count(@*) = 1]/div/div/div[2] '
share_now_button = ' //span[text()= " Share now " ] '
page . locator ( share_button ) . last . click ( )
elif ' watch/?v ' in target_url or ' /videos/ ' in target_url or ' watch?v ' in target_url :
# 视频类型, 视频类型,
share_button = ' //span[@dir= " auto " and text()= " Share " ] '
input_box = ' //form[@method= " POST " and count(@*) = 1]/div/div/div[2] '
share_now_button = ' //span[text()= " Share now " ] '
page . locator ( share_button ) . first . click ( )
elif ' /reel/ ' in target_url :
# 短视频类型
share_button = ' //div[@aria-label= " Share " ] '
input_box = ' //form[@method= " POST " and count(@*) = 1]/div/div/div[2] '
share_now_button = ' //span[text()= " Share now " ] '
page . locator ( share_button ) . click ( )
else :
raise OperationFailed ( f ' 不支持的帖子类型: { target_url } ' )
page . locator ( input_box ) . type ( content , delay = 30 )
_edit_privacy ( page )
page . click ( share_now_button )
time . sleep ( 1 )
page . wait_for_selector ( ' //span[text()= " Posting... " ] ' , state = ' detached ' )
time . sleep ( 1 )
2025-06-25 10:12:06 +08:00
success_tag = page . wait_for_selector ( ' //span[text()= " Shared to your profile " ] ' )
2025-05-30 14:01:29 +08:00
if not success_tag :
raise OperationFailed ( ' 转发失败,原因未知 ' )
2025-06-25 10:03:21 +08:00
cookies = { i [ ' name ' ] : i [ ' value ' ] for i in parse_cookies ( cookies ) }
2025-05-30 14:01:29 +08:00
uid = cookies [ ' c_user ' ]
page . goto ( f ' https://facebook.com/profile.php?id= { uid } ' )
page . wait_for_load_state ( )
post_index = page . locator ( ' //div[@aria-posinset= " 1 " ]//a[@role= " link " ] ' ) . nth ( 2 )
post_index . click ( )
time . sleep ( 5 )
page . reload ( )
post_url = page . url
screenshot_content = _full_screenshot ( )
except Error as e :
raise OperationFailed ( f ' 操作超时,请重试 { e } ' )
context . close ( )
browser . close ( )
key = f ' { uuid . uuid4 ( ) } .png '
put_object ( key , screenshot_content )
return { ' response_url ' : post_url , ' screenshot_key ' : key }
2025-03-28 14:50:37 +08:00
if __name__ == ' __main__ ' :
2025-04-08 16:10:08 +08:00
# cookies = 'sb=mC6pxQuLvNLPTNpF-b9Tk8tK;c_user=61570961343759;xs=18:fBZ4XJkFA69uNg:2:1734940655:-1:-1;fr=0JjwzD0HEedbQSHGt.AWUHNQcfxnkbZ3j5rVd1NgTTGhA.BnaRfv..AAA.0.0.BnaRfv.AWWF3uukqmQ;datr=7xdpZzxiItbht8A5aCDBAhQU'
2025-05-21 17:11:31 +08:00
# cookies = {"c_user":"61565823476070","datr":"q13hZowje6bbViFxECQpYyp8","fr":"01C6Lt4VArm5hELvx.AWXg75HOo-QNJgbiDl8qFtw_5lc.Bm4V2r..AAA.0.0.Bm4V25.AWWHzUeMTuI","m_pixel_ratio":"1.875","sb":"q13hZgJARsRIDmNJG8xUauAe","wd":"384x686","xs":"50%3A8luhgQ-Ea0vnhg%3A2%3A1726045627%3A-1%3A-1"}
2025-06-06 10:43:35 +08:00
# cookies = {"locale": "en_US", "datr": "yDw1aAdAMlMi5KGob7DNfBGF", "sb": "yDw1aGVdzkvrkFcP7az4Ptar",
# "m_pixel_ratio": "1", "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576501144993",
# "fr": "0zCSUrgRrEYTrSxvK.AWe78M4ykg9WKaQBuTTquWE-6BtYQsXSP0nsHkMiQLjp3VBYWys.BoNTzI..AAA.0.0.BoNTzS.AWdJagzrdnwXB73maN02UklQBn8",
# "xs": "9%3AGpZOVoPh8zaXoQ%3A2%3A1748319443%3A-1%3A-1"}
2025-03-28 14:50:37 +08:00
# post(cookies, 'cs2025')
# like(cookies, 'ZmVlZGJhY2s6MTIyMTA5NjE0NjU0NzkzNzc5')
2025-04-01 14:43:02 +08:00
# comment(cookies, 'ZmVlZGJhY2s6MTIyMTA5NjE0NjU0NzkzNzc5', 'game la', 'xzpq.mp4')
2025-03-28 14:50:37 +08:00
# playwright_like(cookies, 'https://www.facebook.com/watch/?v=1007800324567828')
2025-04-14 14:45:16 +08:00
# print(playwright_post(cookie, '2025-3-230~like'))
2025-04-01 14:43:02 +08:00
# playwright_post(cookies, '2025-3-26~like', 'rg.jpg')
2025-03-28 14:50:37 +08:00
# playwright_comment(
# cookies,
2025-04-01 14:43:02 +08:00
# 'https://www.facebook.com/permalink.php?story_fbid=122096663738814448&id=61574433449058',
2025-03-28 14:50:37 +08:00
# # 'https://www.facebook.com/watch/?v=1603348023628396',
# # 'https://www.facebook.com/permalink.php?story_fbid=635052906055594&id=100086526695858',
2025-04-01 14:43:02 +08:00
# # 'https://www.facebook.com/reel/3578555425778137',
2025-03-28 14:50:37 +08:00
# '2025-3-26~like',
2025-04-01 14:43:02 +08:00
# # 'rg.jpg'
2025-03-28 14:50:37 +08:00
# )
2025-06-06 10:43:35 +08:00
# print(playwright_get_user_profile(cookies))
2025-05-30 15:09:10 +08:00
# print(_change_language(cookies))
2025-03-28 14:50:37 +08:00
# playwright_set_user_profile(
# cookies,
2025-04-14 14:45:16 +08:00
# username='facebaby66'
# # firstname='Lisa',
# # lastname='Keals',
# # image_key='rg.jpg'
2025-03-28 14:50:37 +08:00
# )
2025-05-22 12:46:37 +08:00
# cookies = '{"c_user":"61565405263653","datr":"-YDhZoLWu5zbUIw5cOB2In9s","fr":"0ZmsqLWbmV0Onlspt.AWW1JRfVxQAF-jl0oGY7lBQLYq4.Bm4YD5..AAA.0.0.Bm4YED.AWVf1ae03r4","m_page_voice":"61565405263653","m_pixel_ratio":"2.625","sb":"-YDhZs8LozUoyLe1gj2MCUwW","wd":"412x759","xs":"21%3A8Gt3CwtjVWJUhQ%3A2%3A1726054660%3A-1%3A-1"}'
2025-05-27 08:52:24 +08:00
# cookies = '{"datr": "mm0taNtaPfOxWhpxdzpkVjV0", "sb": "mm0taFuFnO_L1FpzkKDiA4lw", "wd": "1920x953", "locale": "en_US", "c_user": "61575901481649", "fr": "0c0y2KyMv8lRJ6NNq.AWe7DLt-TSkoOyn3DhRjhA4ByOITAhfSwaiIw4eQE5ilq4Q4KAY.BoLW2a..AAA.0.0.BoLW3M.AWfHVOhZIAGgDh_3BvPFPi8-YhE", "xs": "29%3ASM0qc4U4Ile_MA%3A2%3A1747807693%3A-1%3A-1", "presence": "C%7B%22t3%22%3A%5B%5D%2C%22utc3%22%3A1747807698911%2C%22v%22%3A1%7D"}'
2025-07-17 16:26:25 +08:00
cookies = ' { " locale " : " en_US " , " datr " : " PaB4aGZCgstQYUkBHpEVnEe8 " , " sb " : " PaB4aAgR68sRQtATM6v7gEu5 " , " m_pixel_ratio " : " 1 " , " wd " : " 1920x1080 " , " test_cookie " : " CheckForPermission " , " c_user " : " 100094571602733 " , " fr " : " 0g0qqVhuLyyrKSaUv.AWdif7wExy29FD7aMjwFvrQFqoBzz-S7Qbeg8la4QMVeGv43eLg.BoeKA9..AAA.0.0.BoeKBQ.AWdj3k5XKtwF766wY3n-cro4yw8 " , " xs " : " 15 % 3A52m6IVmYaMzM3Q % 3A2 % 3A1752735825 % 3A-1 % 3A-1 " } '
2025-06-27 15:45:32 +08:00
# print(playwright_share(cookies, "https://www.facebook.com/groups/1702958116839437/permalink/2210833932718517/", ""))
2025-07-17 16:26:25 +08:00
print ( playwright_get_user_profile ( cookies ) )
2025-05-27 08:52:24 +08:00
# # 永久链接的帖子点赞
2025-06-24 13:53:59 +08:00
# print(playwright_like(cookies, "https://www.facebook.com/groups/1070754870427928/permalink/1873461830157224/"))
2025-05-27 08:52:24 +08:00
#
2025-06-06 10:43:35 +08:00
# # # 视频链接的帖子点赞
# print(playwright_like(cookies, "https://www.facebook.com/groups/1070754870427928/permalink/1873461830157224/"))
2025-05-27 08:52:24 +08:00
#
2025-06-06 10:43:35 +08:00
# cookies = playwright_login('61576195641387', 'osman@@5', 'Z7U32HAU3RDVE6JE5WEXATOOH6DLPUHV')
# print(cookies)
2025-05-27 08:52:24 +08:00
# pass
2025-06-27 09:33:25 +08:00
# cookies = playwright_m_login('61576995257902', 'djkufhhh', 'R56AR2LXBK664C6N4AQX2CPV2SL6FOFW')
2025-06-06 10:43:35 +08:00
# print(cookies)
# 点赞
2025-06-24 13:53:59 +08:00
# cookies_list = [
# # {"locale": "en_US", "datr": "edo_aHbvz3EnE6wLxMErpyJN", "sb": "edo_aB7zwegWek0KTQ1tx-FY", "m_pixel_ratio": "1",
# # "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576223713268",
# # "fr": "0g90xhA5Gl8ZgOqxG.AWfoCPjWPzbDQn6pLym-URV-n2fHl9Ht9QSsvq-N2gHrVT4XfDk.BoP9p5..AAA.0.0.BoP9qH.AWcANS7YIylX14NqadUIosIZKdI",
# # "xs": "48%3ASpsqohj8-YUsYw%3A2%3A1749015176%3A-1%3A-1"},
# # {"locale": "en_US", "datr": "Yds_aBYaJ-fce50yt7zP7ar7", "sb": "Yds_aKXiSyiKmG8a3SoFbwkZ", "m_pixel_ratio": "1",
# # "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576668058350",
# # "fr": "0h7K7g58Qvbr1AK5k.AWfmgzZGs7oGSA3Ix7tGZjU2-UwTs7W2TjY7JW1K2Tq1eZfOgDM.BoP9th..AAA.0.0.BoP9tw.AWe4d26SD_BUw7vAd7hmkFe7Akc",
# # "xs": "38%3APKGnjRBkSQ_TGg%3A2%3A1749015409%3A-1%3A-1"},
# {"locale": "en_US", "datr": "n9s_aFz_DGtnnY4ykLeM3K4t", "sb": "n9s_aIU7TDGsUvpTmZ3WEI2z", "m_pixel_ratio": "1",
# "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576555533160",
# "fr": "0M0A9DWmQqX090mhO.AWfLUhjX_kx8rBpnmFZQexb649CZfCySYWg2W7PxjpQM_ssHfeY.BoP9uf..AAA.0.0.BoP9un.AWeP2pc6-g_ZYLQOq_bUWKseAfo",
# "xs": "38%3AkHgOiwbxyT7sfw%3A2%3A1749015463%3A-1%3A-1"},
# {"locale": "en_US", "datr": "_Ns_aFWk_p0EElGrAi_tNXEg", "sb": "_Ns_aEsFh0KeghxVRRafVAUZ", "m_pixel_ratio": "1",
# "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576802091944",
# "fr": "0Z0WLbZCuM5XHjXDJ.AWdmWevd43Nen9oYwCFjg5iWlx86SAkcCWVXx_4HwQy6-gRgjBc.BoP9v8..AAA.0.0.BoP9wI.AWfK64zgJ71c76MCv2gazDXBzbI",
# "xs": "31%3AtV4oOWHr4Il5ug%3A2%3A1749015561%3A-1%3A-1"},
# {"locale": "en_US", "datr": "E-E_aIwPKZ30BUqS4q8JIfQI", "sb": "E-E_aNEmMEV78u_Vnm8tQGX6", "m_pixel_ratio": "1",
# "wd": "1920x1080", "ps_l": "1", "ps_n": "1", "test_cookie": "CheckForPermission", "c_user": "61576325558767",
# "fr": "0VvlERRijEeTAnppZ.AWcqoATDLUSVislwUMXIuDQYxxxf7ksmECHv--94j-wGTMQzk6U.BoP-ET..AAA.0.0.BoP-Eg.AWdR6VNnZSfB-_YWaA5XEWcyQvA",
# "xs": "30%3AxljD-RO8defzCA%3A2%3A1749016865%3A-1%3A-1"},
# {"locale": "en_US", "datr": "JeE_aAX1P5smkZmQvLInd4ks", "sb": "JeE_aOyuAZsfMGpeUxsovVZD", "m_pixel_ratio": "1",
# "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576711106140",
# "fr": "07RdoRUs1SsUlq7ef.AWe3jMvGjMqd54IxTDl5vbLvGoOHRT1myhxqRRny7GRaIRszFTA.BoP-El..AAA.0.0.BoP-Eu.AWfyXHJMmkeyX0iwh1UXv_0if8Q",
# "xs": "10%3AkZhoUr10WNy9ww%3A2%3A1749016879%3A-1%3A-1"},
# {"locale": "en_US", "datr": "MuE_aAucRyXVDioA3HWs1N0O", "sb": "MuE_aOmJUt_HZCAEkkimKKm4", "m_pixel_ratio": "1",
# "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576218193987",
# "fr": "0PTX91SU4KYxo8wSl.AWeeaJ5RiZemCmgKMZriUg8ZNd9rfzvzuM8mGYVxApULaImQUXk.BoP-Ey..AAA.0.0.BoP-FB.AWdQzDjj8jtqe9lKIvOExq6qF84",
# "xs": "37%3ATE2pxPfwNwdj1g%3A2%3A1749016898%3A-1%3A-1"},
# {"locale": "en_US", "datr": "R-E_aNsGqOYN8pdKKM7W_Uex", "sb": "R-E_aNoFf6JeSlOoOmwMdYI4", "m_pixel_ratio": "1",
# "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576332729468",
# "fr": "0nU85lvzIaFTsdxjz.AWd0opLHfWkafYnwBhC_CzkdQFUXOQn65cetutGpbG3rSiuJRSo.BoP-FH..AAA.0.0.BoP-FU.AWfrmCKdqXpjSeHcu8z8xOTeKp4",
# "xs": "50%3AJ9Xi34a6amKV1g%3A2%3A1749016917%3A-1%3A-1"},
# {"locale": "en_US", "datr": "WeE_aFQbLkcj3fSF25ZeCcfe", "sb": "WeE_aNEPhbw60DgzKrwPX_jE", "m_pixel_ratio": "1",
# "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576570803564",
# "fr": "0n8aDHJ9N2QuRqfQk.AWcKYZI4zd7qXFvbKAoYZGJ8rhUsOPJ1b8hdOR5fJpuEXRZK5mg.BoP-FZ..AAA.0.0.BoP-Fv.AWd8GCiXev5g05qJV1X_h-Wc5hQ",
# "xs": "16%3AOYTGTKbKdBko6g%3A2%3A1749016944%3A-1%3A-1"},
# {"locale": "en_US", "datr": "d-E_aKwMl9BeWWx1cR4MzMad", "sb": "d-E_aBZiULc0sw8LQEoqj--A", "m_pixel_ratio": "1",
# "wd": "1920x1080", "test_cookie": "CheckForPermission", "c_user": "61576547344605",
# "fr": "0Kccfs8cK4FoRKsFz.AWcjtGqjJwkD6lC_oTSjduL1w4AKD3ErAk877IvJKI3YI1-pUxQ.BoP-F3..AAA.0.0.BoP-GD.AWeg-MT8xtV9JelBtZuPnCkwg18",
# "xs": "45%3AI8xuKEPRy222pA%3A2%3A1749016964%3A-1%3A-1"},
# ]
# for cookies in cookies_list:
# # # 视频链接的帖子点赞
# print(playwright_like(cookies, "https://www.facebook.com/groups/1070754870427928/permalink/1873461830157224/"))
2025-06-27 15:45:32 +08:00
# 评论
2025-07-14 18:14:23 +08:00
# print(playwright_comment(cookies, "https://www.facebook.com/groups/7423373454348259/permalink/24322822973976709/",
# "6"))