154 lines
10 KiB
Python
154 lines
10 KiB
Python
|
|
import selenium
|
||
|
|
from selenium import webdriver
|
||
|
|
from selenium.webdriver.common.by import By
|
||
|
|
from selenium.webdriver.support.ui import WebDriverWait
|
||
|
|
from selenium.webdriver.support import expected_conditions as EC
|
||
|
|
|
||
|
|
import json
|
||
|
|
import base64
|
||
|
|
class xhsPublisher():
|
||
|
|
def __init__(self, driver, cookies_path):
|
||
|
|
self.driver = driver
|
||
|
|
self.cookies_path = cookies_path
|
||
|
|
self.cookies = json.loads(open(self.cookies_path, "r").read())
|
||
|
|
self.load_cookies()
|
||
|
|
|
||
|
|
self.WEB_URL = "https://creator.xiaohongshu.com/publish/publish?from=menu"
|
||
|
|
|
||
|
|
def load_cookies(self):
|
||
|
|
for cookie in self.cookies:
|
||
|
|
# 确保每个cookie都有'sameSite'属性
|
||
|
|
if True:
|
||
|
|
# if 'sameSite' not in cookie:
|
||
|
|
cookie['sameSite'] = 'Strict' # 或者根据需要设置为'Strict'或'None'
|
||
|
|
|
||
|
|
self.driver.add_cookie(cookie)
|
||
|
|
return True
|
||
|
|
|
||
|
|
def open_web(self):
|
||
|
|
self.driver.get(self.WEB_URL)
|
||
|
|
return True
|
||
|
|
|
||
|
|
def select_upload_type(self, upload_type):
|
||
|
|
## 这里没改好
|
||
|
|
if upload_type == "image":
|
||
|
|
# 图文
|
||
|
|
self.driver.find_element(By.XPATH, "//div[@data-v-16fdb080 and @data-v-a964f0b4 and @class='creator-tab active']").click()
|
||
|
|
elif upload_type == "video":
|
||
|
|
# 视频
|
||
|
|
self.driver.find_element(By.XPATH, "//div[@data-v-7cbccdb2 and @data-v-08fc0cfe and @class='drag-over']").click()
|
||
|
|
return True
|
||
|
|
|
||
|
|
def upload_image(self, image_path):
|
||
|
|
image_base64 = self.transbase64(image_path)
|
||
|
|
self.driver.find_element(By.XPATH, "//input[@data-v-4fabe6c5 and @data-v-7cbccdb2-s and @class='upload-input']").send_keys(image_base64)
|
||
|
|
return True
|
||
|
|
|
||
|
|
def upload_video(self, video_path):
|
||
|
|
video_base64 = self.transbase64(video_path)
|
||
|
|
self.driver.find_element(By.XPATH, "//input[@data-v-4fabe6c5 and @data-v-7cbccdb2-s and @class='upload-input']").send_keys(video_base64)
|
||
|
|
return True
|
||
|
|
|
||
|
|
def transbase64(self, file_path):
|
||
|
|
with open(file_path, "rb") as image_file:
|
||
|
|
return base64.b64encode(image_file.read()).decode('utf-8')
|
||
|
|
|
||
|
|
def publish(self, title, content):
|
||
|
|
self.driver.find_element(By.XPATH, "//input[@class='d-text']").send_keys(title)
|
||
|
|
self.driver.find_element(By.XPATH, "//div[@class='ql-editor ql-blank']").send_keys(content)
|
||
|
|
return True
|
||
|
|
|
||
|
|
def click_publish(self):
|
||
|
|
self.driver.find_element(By.XPATH, "//button[@data-v-34b0c0bc and @data-v-9bfbb062 and @data-v-1fed608d-s and @type='button' and @class='d-button d-button-large --size-icon-large --size-text-h6 d-button-with-content --color-static bold --color-bg-fill --color-text-paragraph custom-button red publishBtn' and @data-eaglet-imp='true']").click()
|
||
|
|
return True
|
||
|
|
|
||
|
|
def publish_article(self, title, content, image_path, video_path):
|
||
|
|
self.select_upload_type("image")
|
||
|
|
self.upload_image(image_path)
|
||
|
|
self.publish(title, content)
|
||
|
|
self.click_publish()
|
||
|
|
return True
|
||
|
|
|
||
|
|
def publish_video(self, title, content, video_path):
|
||
|
|
self.select_upload_type("video")
|
||
|
|
self.upload_video(video_path)
|
||
|
|
self.publish(title, content)
|
||
|
|
self.click_publish()
|
||
|
|
return True
|
||
|
|
|
||
|
|
def work(self, type, title, content, image_path, video_path):
|
||
|
|
try:
|
||
|
|
self.open_web()
|
||
|
|
self.driver.maximize_window()
|
||
|
|
self.driver.implicitly_wait(500)
|
||
|
|
if type == "article":
|
||
|
|
self.publish_article(title, content, image_path, video_path)
|
||
|
|
elif type == "video":
|
||
|
|
self.publish_video(title, content, video_path)
|
||
|
|
else:
|
||
|
|
raise ValueError("Invalid type")
|
||
|
|
self.driver.quit()
|
||
|
|
except Exception as e:
|
||
|
|
print(e)
|
||
|
|
finally:
|
||
|
|
self.driver.quit()
|
||
|
|
return True
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
driver = webdriver.Safari()
|
||
|
|
# 设置浏览器全屏
|
||
|
|
driver.maximize_window()
|
||
|
|
# 设置模拟位置(经度和纬度)
|
||
|
|
driver.execute_script("navigator.geolocation.getCurrentPosition = function(success) {"
|
||
|
|
"success({coords: {latitude: 37.7749, longitude: -122.4194}});"
|
||
|
|
"};")
|
||
|
|
|
||
|
|
cookies_path = "/Users/yarrow/Spider/seleniumXH/cookies.json"
|
||
|
|
cookies = json.loads(open(cookies_path, "r").read())
|
||
|
|
# print(cookies)
|
||
|
|
for cookie in cookies:
|
||
|
|
# 确保每个cookie都有'sameSite'属性
|
||
|
|
if True:
|
||
|
|
# if 'sameSite' not in cookie:
|
||
|
|
cookie['sameSite'] = 'Strict' # 或者根据需要设置为'Strict'或'None'
|
||
|
|
|
||
|
|
driver.add_cookie(cookie)
|
||
|
|
|
||
|
|
driver.get("https://creator.xiaohongshu.com/publish/publish?from=menu")
|
||
|
|
# input("press any key to quit")
|
||
|
|
driver.implicitly_wait(3000)
|
||
|
|
## 图文
|
||
|
|
# <div data-v-16fdb080="" data-v-a964f0b4="" class="creator-tab active"><span data-v-16fdb080="" class="title">上传图文</span><div data-v-16fdb080="" class="underline"></div></div>
|
||
|
|
driver.find_element(By.XPATH, "//div[@data-v-16fdb080 and @data-v-a964f0b4 and @class='creator-tab']").click()
|
||
|
|
# <input data-v-4fabe6c5="" data-v-7cbccdb2-s="" class="upload-input" type="file" multiple="" accept=".jpg,.jpeg,.png">
|
||
|
|
# 视频 ## <div data-v-7cbccdb2="" data-v-08fc0cfe="" class="drag-over"><input data-v-08fc0cfe="" data-v-7cbccdb2-s="" class="upload-input" type="file" accept=".mp4,.mov,.flv,.f4v,.mkv,.rm,.rmvb,.m4v,.mpg,.mpeg,.ts"><div data-v-08fc0cfe="" data-v-7cbccdb2-s="" class="wrapper"><img data-v-08fc0cfe="" data-v-7cbccdb2-s="" src="//fe-static.xhscdn.com/formula-static/ugc/public/img/upload-large.e52d3e7.png" class="upload-icon"><p data-v-08fc0cfe="" data-v-7cbccdb2-s="">拖拽视频到此或点击上传</p><button data-v-08fc0cfe="" data-v-7cbccdb2-s="" aria-disabled="false" type="button" class="el-button upload-button" style="--el-button-bg-color: #ff2442; --el-button-text-color: var(--el-color-white); --el-button-border-color: #ff2442; --el-button-hover-bg-color: rgb(255, 102, 123); --el-button-hover-text-color: var(--el-color-white); --el-button-hover-border-color: rgb(255, 102, 123); --el-button-active-bg-color: rgb(208, 33, 57); --el-button-active-border-color: rgb(208, 33, 57);"><!--v-if--><span class="">上传视频</span></button></div></div>
|
||
|
|
driver.find_element(By.XPATH, "//input[@data-v-4fabe6c5 and @data-v-7cbccdb2-s and @class='upload-input']").send_keys("/Users/yarrow/Spider/cableCar.jpg")
|
||
|
|
print("send keys /Users/yarrow/Spider/cableCar.jpg")
|
||
|
|
driver.implicitly_wait(10)
|
||
|
|
print("wait 10 seconds")
|
||
|
|
# 标题
|
||
|
|
# <input class="d-text" type="text" placeholder="填写标题会有更多赞哦~" value="">
|
||
|
|
driver.find_element(By.XPATH, "//input[@class='d-text']").send_keys("缆车")
|
||
|
|
print("send keys 缆车")
|
||
|
|
# 正文
|
||
|
|
# <div class="ql-editor ql-blank" contenteditable="true" aria-owns="quill-mention-list" data-placeholder="输入正文描述,真诚有价值的分享予人温暖"><p><br></p></div>
|
||
|
|
driver.find_element(By.XPATH, "//div[@class='ql-editor ql-blank']").send_keys("""缆车 \n
|
||
|
|
#周末去哪儿玩
|
||
|
|
""")
|
||
|
|
print("send keys 缆车")
|
||
|
|
# 发布
|
||
|
|
|
||
|
|
# <button data-v-34b0c0bc="" data-v-9bfbb062="" data-v-1fed608d-s="" type="button" class="d-button d-button-large --size-icon-large --size-text-h6 d-button-with-content --color-static bold --color-bg-fill --color-text-paragraph custom-button red publishBtn" data-impression="{"noteTarget":{"type":"NoteTarget","value":{"noteEditSource":1,"noteType":1}},"event":{"type":"Event","value":{"targetType":{"type":"RichTargetType","value":"note_compose_target"},"action":{"type":"NormalizedAction","value":"impression"},"pointId":50979}},"page":{"type":"Page","value":{"pageInstance":{"type":"PageInstance","value":"creator_service_platform"}}}}" data-eaglet-imp="true"><div class="d-button-content"><!----><span class="d-text --color-static --color-current --size-text-paragraph d-text-nowrap d-text-ellipsis d-text-nowrap" style="text-underline-offset: auto;"><!---->发布<!----><!----><!----></span><!----></div></button>
|
||
|
|
# <button data-v-34b0c0bc="" data-v-9bfbb062="" data-v-1fed608d-s="" type="button" class="d-button d-button-large --size-icon-large --size-text-h6 d-button-with-content --color-static bold --color-bg-fill --color-text-paragraph custom-button red publishBtn" data-impression="{"noteTarget":{"type":"NoteTarget","value":{"noteEditSource":1,"noteType":1}},"event":{"type":"Event","value":{"targetType":{"type":"RichTargetType","value":"note_compose_target"},"action":{"type":"NormalizedAction","value":"impression"},"pointId":50979}},"page":{"type":"Page","value":{"pageInstance":{"type":"PageInstance","value":"creator_service_platform"}}}}" data-eaglet-imp="true"><div class="d-button-content"><!----><span class="d-text --color-static --color-current --size-text-paragraph d-text-nowrap d-text-ellipsis d-text-nowrap" style="text-underline-offset: auto;"><!---->发布<!----><!----><!----></span><!----></div></button>
|
||
|
|
# <span class="d-text --color-static --color-current --size-text-paragraph d-text-nowrap d-text-ellipsis d-text-nowrap" style="text-underline-offset: auto;"><!---->发布<!----><!----><!----></span>
|
||
|
|
driver.find_element(By.XPATH, "//button[@data-v-34b0c0bc and @data-v-9bfbb062 and @data-v-1fed608d-s and @type='button' and @class='d-button d-button-large --size-icon-large --size-text-h6 d-button-with-content --color-static bold --color-bg-fill --color-text-paragraph custom-button red publishBtn' and @data-eaglet-imp='true']").click()
|
||
|
|
## 找到span内容为发布的
|
||
|
|
# driver.find_element(By.XPATH, "//span[@class='d-text --color-static --color-current --size-text-paragraph d-text-nowrap d-text-ellipsis d-text-nowrap' and @style='text-underline-offset: auto;']").click()
|
||
|
|
driver.implicitly_wait(500)
|
||
|
|
input("press any key to quit")
|
||
|
|
driver.quit()
|
||
|
|
|
||
|
|
## button
|
||
|
|
|
||
|
|
|