Commit 0d4d5cb6 by lei

1

parent 849e6738
# 默认忽略的文件
/shelf/
/workspace.xml
Img_Ai
\ No newline at end of file
...@@ -2,7 +2,11 @@ ...@@ -2,7 +2,11 @@
<module type="PYTHON_MODULE" version="4"> <module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.8" jdkType="Python SDK" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module> </module>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N806" />
</list>
</option>
</inspection_tool>
</profile>
</component>
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<project version="4"> <project version="4">
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/.idea/python-demo.iml" filepath="$PROJECT_DIR$/.idea/python-demo.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/Img_Ai.iml" filepath="$PROJECT_DIR$/.idea/Img_Ai.iml" />
</modules> </modules>
</component> </component>
</project> </project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="NewModuleRootManager">
<orderEntry type="jdk" jdkName="Python 3.8" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="69cbe23c-d853-4b51-b873-06f85f1d3199" name="变更" comment="">
<change afterPath="$PROJECT_DIR$/Vmlogin.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/download_img.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.gitignore" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.name" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/Img_Ai.iml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/python-demo.iml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/vcs.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/ai_pyppeteer.py" beforeDir="false" afterPath="$PROJECT_DIR$/ai_pyppeteer.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/bit_api.py" beforeDir="false" afterPath="$PROJECT_DIR$/bit_api.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/bit_selenium.py" beforeDir="false" afterPath="$PROJECT_DIR$/bit_selenium.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gpt.py" beforeDir="false" afterPath="$PROJECT_DIR$/gpt.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FormatOnSaveOptions">
<option name="myRunOnSave" value="true" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectId" id="2NiGtA98nfjUjgQnO3PrkFMQZ1U" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;F:/python/Img_Ai&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;actions.on.save&quot;
}
}</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="F:\python\Img_Ai" />
</key>
</component>
<component name="RunManager" selected="Python.ai_pyppeteer">
<configuration name="Vmlogin" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="Img_Ai" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/Vmlogin.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration default="true" type="PythonConfigurationType" factoryName="Python">
<module name="Img_Ai" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="ai_pyppeteer" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="python-demo" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="C:\Users\lei\AppData\Local\Programs\Python\Python38\python.exe" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/ai_pyppeteer.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="bit_api" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="Img_Ai" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/bit_api.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="download_img" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="Img_Ai" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/download_img.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="gpt" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="python-demo" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="C:\Users\lei\AppData\Local\Programs\Python\Python38\python.exe" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/gpt.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration default="true" type="Tox" factoryName="Tox">
<module name="Img_Ai" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<method v="2" />
</configuration>
<configuration default="true" type="docs" factoryName="Docutils task">
<module name="Img_Ai" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="docutils_input_file" value="" />
<option name="docutils_output_file" value="" />
<option name="docutils_params" value="" />
<option name="docutils_task" value="" />
<option name="docutils_open_in_browser" value="false" />
<method v="2" />
</configuration>
<configuration default="true" type="docs" factoryName="Sphinx task">
<module name="Img_Ai" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="docutils_input_file" value="" />
<option name="docutils_output_file" value="" />
<option name="docutils_params" value="" />
<option name="docutils_task" value="" />
<option name="docutils_open_in_browser" value="false" />
<method v="2" />
</configuration>
<configuration default="true" type="tests" factoryName="Autodetect">
<module name="Img_Ai" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="_new_additionalArguments" value="&quot;&quot;" />
<option name="_new_target" value="&quot;&quot;" />
<option name="_new_targetType" value="&quot;PATH&quot;" />
<method v="2" />
</configuration>
<configuration default="true" type="tests" factoryName="Doctests">
<module name="Img_Ai" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="FOLDER_NAME" value="" />
<option name="TEST_TYPE" value="TEST_SCRIPT" />
<option name="PATTERN" value="" />
<option name="USE_PATTERN" value="false" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Python.ai_pyppeteer" />
<item itemvalue="Python.Vmlogin" />
<item itemvalue="Python.download_img" />
<item itemvalue="Python.gpt" />
<item itemvalue="Python.bit_api" />
</list>
</recent_temporary>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="应用程序级" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="默认任务">
<changelist id="69cbe23c-d853-4b51-b873-06f85f1d3199" name="变更" comment="" />
<created>1680139700437</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1680139700437</updated>
</task>
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
</component>
</project>
\ No newline at end of file
import json
import os
import shutil
import stat
from loguru import logger
import requests
class VmLogin:
def __init__(self, token):
self.token = token
def get_remotely_url(self, path):
"""
vmlogin 远程地址
:param path:
:return:
"""
return f"https://api.vmlogin.com/v1{path}"
def get_chrome_config(self, profile_id, start_url='', proxy=None):
"""
获取修改后的浏览器配置
:param profile_id: 配置ID
:param start_url: 打开地址
:return:ilo29@
"""
url = self.get_remotely_url(f'/profile/detail?token={self.token}&profileId={profile_id}')
json_text = self.request_get(url)
print(json.dumps(json_text))
json_text['proxyServer']['setProxyServer'] = True
json_text['startUrl'] = start_url
json_text['proxyServer']['port'] = proxy['port']
json_text['proxyServer']['host'] = proxy['host']
json_text['proxyServer']['username'] = proxy.get('username', '')
json_text['proxyServer']['password'] = proxy.get('password', '')
return json_text
def create_chrome_config(self, body, user_agent, name="关键词上首页"):
"""
创建浏览器配置
:param body:
:param user_agent:
:return:
"""
body['name'] = name
body['userAgent'] = user_agent
body['localCache']['deleteCache'] = True
body['localCache']['deleteCookie'] = True
body['localCache']['clearCache'] = True
body['localCache']['clearHistory'] = True
headers = {'Content-Type': 'application/json'}
url = self.get_remotely_url('/profile/create')
text = requests.post(url, headers=headers,
data=json.dumps({"token": self.token, "Body": body})).json()
return text['value']
def get_local_url(self, path):
"""
vmlogin 本地地址
:param path:
:return:
"""
return f"http://127.0.0.1:35000/api/v1{path}"
def start_chrome(self, profile_id):
"""
启动浏览器
:param profile_id: 配置ID
:return:
"""
url = self.get_local_url(f'/profile/start?profileId={profile_id}')
text = requests.get(url).json()
if text['status'] == 'ERROR':
return ''
return ('' + text['value']).replace("http://127.0.0.1:", "")
def request_get(self, url, params=None):
"""
发送请求
:param url: 请求地址
:param params: 请求参数
:return: 配置信息
"""
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62"
}
return requests.get(url, headers=headers, params=params).json()
def get_rand_ua(self):
"""
获取随机请求头
:return:
"""
url = self.get_local_url(f'/profile/randomProfile?token={self.token}&platform=Windows&browser=chrome')
json_text = self.request_get(url)
return json_text['userAgent']
def stop_chrome(self, profile_id):
"""
停止浏览器
:param profile_id:
:return:
"""
url = self.get_local_url(f'/profile/stop?profileId={profile_id}')
self.request_get(url)
def delete_config(self, profile_id, path="C:\\Users\\Administrator\\AppData\\Roaming\\VMLogin\\profile"):
"""
删除配置文件
:param profile_id: 配置ID
:return:
"""
url = self.get_remotely_url(f'/profile/remove?token={self.token}&profileId={profile_id}')
requests.get(url)
self.delete_file(path)
def delete_file(self, file_path):
"""
删除文件
:param file_path: 文件地址
:return:
"""
if os.path.exists(file_path):
for fileList in os.walk(file_path):
for name in fileList[2]:
os.chmod(os.path.join(fileList[0], name), stat.S_IWRITE)
os.remove(os.path.join(fileList[0], name))
shutil.rmtree(file_path)
return "delete ok"
else:
return "no filepath"
def import_cookie(self, profile_id: str, cookie: dict) -> dict:
"""
导入cookie
:param profile_id:
:param cookie:
:return:
"""
url = self.get_local_url('/profile/cookies/import/webext')
data = {
'profileId': profile_id,
'body': cookie,
}
return requests.post(url=url, data=data).json()
if __name__ == '__main__':
token = '6731ae7034426c1f861479eaeb964c61'
data = VmLogin(token).get_chrome_config('0B3D6BAF-E534-4CE5-A53B-75D405378E39')
print(data)
from selenium import webdriver import requests
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC
import pyperclip import pyperclip
import time import time
from loguru import logger from loguru import logger
...@@ -14,10 +6,13 @@ from bit_api import * ...@@ -14,10 +6,13 @@ from bit_api import *
import asyncio import asyncio
from Helper import RedisCon from Helper import RedisCon
import json import json
from multiprocessing import Process
import random import random
import pyppeteer import pyppeteer
from multiprocessing import Process, Lock from multiprocessing import Process, Lock
import uuid
import os
from Vmlogin import VmLogin
# 获取当前时间 # 获取当前时间
...@@ -28,11 +23,17 @@ def get_current_time(): ...@@ -28,11 +23,17 @@ def get_current_time():
class ToWork: class ToWork:
def __init__(self, browser_item, lock): def __init__(self, browser_item, lock):
self.browser_token = 'd8ee6138f2b7ae5e064061e5c29d611a'
self.init_prompt = '/imagine' self.init_prompt = '/imagine'
self.browser_item = browser_item self.browser_item = browser_item
self.browser_id = browser_item['id'] self.browser_id = browser_item['id']
self.lock = lock self.lock = lock
self.key = 'laravel_database_midjourney_prompt' self.key = 'laravel_database_midjourney_prompt'
self.header = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': ''
}
# 获取浏览器窗口 # 获取浏览器窗口
async def browser(self, browser_id): async def browser(self, browser_id):
...@@ -49,13 +50,21 @@ class ToWork: ...@@ -49,13 +50,21 @@ class ToWork:
def random_sleep(self, min, max): def random_sleep(self, min, max):
time.sleep(random.uniform(min, max)) time.sleep(random.uniform(min, max))
def click_time_rand(self, min_num, max_num):
"""
点击随机时间
:return:
"""
return random.randint(min_num, max_num)
# 粘贴板插入数据 # 粘贴板插入数据
def driver_copy(self, driver, value): def driver_copy(self, driver, value):
pyperclip.copy(value) pyperclip.copy(value)
# 粘贴 # 粘贴--键盘输入
def driver_paste(self, dricer, value): async def driver_paste(self, page, value):
ActionChains(dricer).send_keys(Keys.CONTROL, value).perform() for i in value:
await page.keyboard.press(i)
# 元素出现的循环次数 # 元素出现的循环次数
async def CheckElement(self, page, path, num=10, check_type='only'): async def CheckElement(self, page, path, num=10, check_type='only'):
...@@ -68,7 +77,7 @@ class ToWork: ...@@ -68,7 +77,7 @@ class ToWork:
return element return element
else: else:
# 列表 # 列表
element = self.sleepElementListShow(page, path) element = await self.sleepElementListShow(page, path)
if element: if element:
# 随机等待 # 随机等待
self.random_sleep(1, 2) self.random_sleep(1, 2)
...@@ -85,49 +94,152 @@ class ToWork: ...@@ -85,49 +94,152 @@ class ToWork:
return element return element
return False return False
except Exception as e: except Exception as e:
logger.info(e)
return False return False
# 找元素,只找一次,不等待 # 找元素,只找一次,不等待
def FindElement(self, custom_el, find_type, value): async def FindElement(self, custom_el, path, el_type=''):
try: try:
el = custom_el.find_element(find_type, value) el = (await custom_el.xpath(path))
return el # logger.info(len(el))
# for i in el:
# title = await page.evaluate('(element) => element.textContent', i)
# logger.info(title)
if el_type == 'last':
return el[len(el) - 1]
else:
return el[0]
except Exception as e: except Exception as e:
return False return False
# 获取元素列表 # 获取元素列表
def sleepElementListShow(self, dricer, type, value): async def sleepElementListShow(self, page, path):
try: try:
element = dricer.find_elements(type, value) element = (await page.xpath(path))
if element: if len(element):
return element return element
return False return False
except Exception as e: except Exception as e:
logger.info(e)
return False return False
# 元素点击-xpath点击 # 元素点击-xpath点击
def ElementClick(self, dricer, value, name=''): async def ElementClick(self, page, path, name=''):
try: status = False
task = dricer.find_element(type, value) for i in range(1, 10):
if task: try:
# 随机等待 ele = (await page.xpath(path))[0]
self.random_sleep(1, 2) await page.waitFor(self.click_time_rand(1, 2))
# js 点击 await ele.click()
dricer.execute_script("arguments[0].click()", task) await asyncio.sleep(self.click_time_rand(1, 2))
# task.click()
logger.info(f'{name}-元素存在,开始点击') logger.info(f'{name}-元素存在,开始点击')
return True status = True
logger.info(f'{name}-元素不存在') break
return False except Exception as e:
logger.info(e)
logger.info(f'{name}-元素不存在')
status = False
await asyncio.sleep(1)
return status
# 获取上传策略
async def get_policy(self, url):
for i in range(5):
try:
proxies = {
'http': '192.168.100.139:2009'
}
res = requests.get(url)
data = json.loads(res.text)['data']
return data
except Exception as e:
logger.error('上传策略请求错误')
logger.error(e)
async def download_img(self, url, cur_uuid):
"""
下载图片
:param url:
:return:
"""
get_file = requests.get(url=url, headers=self.header, stream=True, allow_redirects=False, timeout=10)
file_name = cur_uuid
if not os.path.exists('./download'):
os.makedirs('./download')
path = f'./download/{file_name}'
with open(path, "wb") as Pypdf:
for chunk in get_file.iter_content(chunk_size=1024): # 1024 bytes
if chunk:
Pypdf.write(chunk)
return path
async def image_to_byte(self, imagepath):
'''
图片转二进制
'''
with open(imagepath, "rb") as f:
byte_data = f.read()
return byte_data
async def al_upload(self, policy, path, cur_uuid):
# 阿里云上传
url = 'https://' + policy['host']
file = await self.image_to_byte(path)
logger.info('图片已经转为二进制')
params = {
'key': policy['dir'] + cur_uuid,
'policy': policy['policy'],
'OSSAccessKeyId': policy['accessid'],
'success_action_status': '200',
'callback': policy['callback'],
'signature': policy['signature'],
'file': file,
}
header = {
'Content-Type': 'multipart/form-data;charset=utf-8'
}
logger.info('阿里云上传')
res = requests.post(url, data=params, headers=header, proxies={
'http': '192.168.100.139:2009'
})
logger.info(res)
# 上传后的链接为
upload_img = policy['domain'] + policy['dir'] + cur_uuid
logger.info(upload_img)
async def upload_img(self, task, href):
try:
cur_uuid = uuid.uuid4()
cur_uuid = str(cur_uuid) + '.png'
# 先获取上传策略
policy = await self.get_policy(task['policy'])
# 下载discord的图片
# path = await self.download_img(href, cur_uuid)
path = './download/0f24e1f6-4ba2-42d7-bdf4-852653f30fe4.png'
logger.info(path)
# 开始上传
await self.al_upload(policy, path, cur_uuid)
except Exception as e: except Exception as e:
logger.info(f'{name}-元素不存在')
logger.error(e) logger.error(e)
return False
# 循环输入指令 async def img_callback(self, task, href):
def enter_prompt(self, dricer, tasks): # 先要上传图片
if True: # cur_href = await self.upload_img(task, href)
url = task['callback']
try:
params = {
'result_img': href,
'user_id': task['user_id'],
'task_id': task['task_id'],
}
res = requests.post(url, data=params)
except Exception as e:
logger.error(e)
# 检测图片生成进度
async def check_img_load_process(self, page, task):
logger.info('开始检测任务状态')
# 先写单个任务的,获取最后一张图片
while True:
# 获取开始时间 # 获取开始时间
start_time = get_current_time() start_time = get_current_time()
while True: while True:
...@@ -137,104 +249,151 @@ class ToWork: ...@@ -137,104 +249,151 @@ class ToWork:
if current_time - start_time >= 60: if current_time - start_time >= 60:
# end # end
break break
# 开始判断 cur_type = 1 # 获取最后一个
element = '//ol[@data-list-id="chat-messages"]/li' if cur_type == 1:
# 消息列表 logger.info('进入')
message_list = self.CheckElement(dricer, 'xpath', element, 20, 'list') # 判断文字中是否存在进度条
if message_list: text_path = '//div[contains(@id, "message-content-")]'
logger.info('消息列表存在') text_el = await self.FindElement(page, text_path, 'last')
# 找到所有子元素 if text_el:
for e in message_list: title = await page.evaluate('(element) => element.textContent', text_el)
logger.info(e.get_attribute('id')) logger.info(title)
# 找到文本并匹配 if '%' not in title and '(Waiting to start)' not in title and '正在发送命令' not in title:
path = '//div[contains(@data-list-item-id, "chat-messages___chat-messages")]' logger.info('任务完成')
label_element = self.FindElement(e, By.XPATH, path) # 最后一个链接
if label_element: img_path = '//*[contains(@id, "message-accessories-")]/div[1]/div/div/div/div/div/a'
logger.info(label_element.get_attribute('data-list-item-id')) img_el = await self.CheckElement(page, img_path, 20)
if img_el:
href = await page.evaluate('img_el => img_el.href', img_el)
if href:
logger.info(href)
# 回调
await self.img_callback(task, href)
return
else: else:
logger.info('未找到文本') logger.info('任务进行中')
logger.info('等待300秒') else:
time.sleep(300) logger.info('文本元素不存在')
return else:
# 开始判断
element = '//ol[@data-list-id="chat-messages"]/li'
# 消息列表
message_list = await self.CheckElement(page, element, 20, 'list')
if message_list:
logger.info('消息列表存在')
# 找到所有子元素
for e in message_list:
# 找到文本并匹配
path = '//div[contains(@id, "message-content-")]/strong'
label_element = await self.FindElement(e, path)
if label_element:
title = await page.evaluate('(element) => element.textContent', label_element)
logger.info(title)
else:
logger.info('未找到文本')
await asyncio.sleep(2)
# 循环输入指令
async def enter_prompt(self, page, tasks):
# task是一个列表 # task是一个列表
for task in tasks: for task in tasks:
# 输入初始指令
logger.info('输入初始指令')
self.driver_paste(dricer, self.init_prompt)
# 选择指令
prompt_el = '//*[@id="autocomplete-0"]'
# 等待选择指令元素出现
element = self.CheckElement(dricer, 'xpath', prompt_el, 5)
if element:
status = self.ElementClick(dricer, 'xpath', prompt_el, '选择指令')
if status:
change_prompt = task['prompt']
# 图片链接
prompt_img = task['prompt_img']
if task['type'] == 1 and prompt_img and len(json.loads(prompt_img)):
prompt_img = json.loads(prompt_img)
st = ''
for item in prompt_img:
# 加入图片-链接
st += ' ' + item
change_prompt = st + ' ' + change_prompt
self.driver_paste(dricer, change_prompt)
# 回车
ActionChains(dricer).send_keys(Keys.ENTER).perform()
time.sleep(2)
# 输入完成,循环获取生成成功后的链接
# 获取开始时间
start_time = get_current_time()
while True:
# 再次获取当前时间
current_time = get_current_time()
# 最多等待一分钟
if current_time - start_time >= 60:
# end
break
# 开始判断 # 开始判断
message_list = '//*[@data-list-id="chat-messages"]' element = '//ol[@data-list-id="chat-messages"]/li'
# 消息列表
message_list = await self.CheckElement(page, element, 20, 'list')
if message_list:
# 输入初始指令
logger.info('输入初始指令')
await self.driver_paste(page, self.init_prompt)
# 选择指令
prompt_el = '//*[@id="autocomplete-0"]'
# 等待选择指令元素出现
element = await self.CheckElement(page, prompt_el, 20)
if element:
status = await self.ElementClick(page, prompt_el, '选择指令')
if status:
change_prompt = task['prompt']
# 图片链接
prompt_img = task['prompt_img']
if task['type'] == 1 and prompt_img and len(json.loads(prompt_img)):
prompt_img = json.loads(prompt_img)
st = ''
for item in prompt_img:
# 加入图片-链接
st += ' ' + item
change_prompt = st + ' ' + change_prompt
await self.driver_paste(page, change_prompt)
# 回车
await page.keyboard.press('Enter')
await asyncio.sleep(2)
# 输入完成,循环获取生成成功后的链接
await self.check_img_load_process(page, tasks[0])
# 获取任务列表 # 获取任务列表
def get_current_tasks(self): def get_current_tasks(self):
if False:
# 测试 task = RedisCon.get_task(self.key)
# 当前浏览器需要执行的任务 # 当前浏览器需要执行的任务
cur_tasks = [] cur_tasks = []
for j in range(2):
# task = RedisCon.get_task(key)
task = {
'prompt': "a very cute boys, 16 years old, fly a kite,in beautifulstreet,full body,3d art, c4d, octane render, ray tracting,clay material,popmart blind box,Pixar trend, animationlighting, depth of field, ultra detailed --q 5",
'user_id': 1,
'task_id': 1,
'prompt_img': [],
'result_img': "",
'type': 2,
'callback': 'http://test.phpgpt.com/api/users/prompt/callback',
}
if task: if task:
task = json.loads(task)
task['prompt'] = task['prompt'].replace(',', ',')
# 将任务添加到列表 # 将任务添加到列表
cur_tasks.append(task) cur_tasks.append(task)
if len(cur_tasks): if len(cur_tasks):
return cur_tasks return cur_tasks
return [] return []
else:
# 测试
# 当前浏览器需要执行的任务
cur_tasks = []
for j in range(1):
# task = RedisCon.get_task(key)
task = {
'prompt': "a very cute boys, 16 years old, fly a kite,in beautifulstreet,full body,3d art, c4d, octane render, ray tracting,clay material,popmart blind box,Pixar trend, animationlighting, depth of field, ultra detailed --q 5",
'user_id': 1,
'task_id': 1,
'prompt_img': [],
'result_img': "",
'type': 2,
'callback': 'http://test.phpgpt.com/api/users/prompt/callback',
'policy': 'http://test.phpgpt.com/api/users/config/policy2'
}
task['prompt'] = task['prompt'].replace(',', ',')
if task:
# 将任务添加到列表
cur_tasks.append(task)
if len(cur_tasks):
return cur_tasks
return []
async def open_browser(self, browser_item): async def open_browser(self, browser_item):
try: try:
logger.info(f'浏览器id-{browser_item["num"]},开始执行') logger.info(f'浏览器id-{browser_item["num"]},开始执行')
res = openBrowser(browser_item) vm = VmLogin(self.browser_token)
driverPath = res['data']['driver'] proxy = vm.start_chrome(browser_item['id'])
debuggerAddress = res['data']['http'] if not proxy:
ws = res['data']['ws'] logger.info('无法打开浏览器')
chrome_options = Options() else:
chrome_options.add_experimental_option("debuggerAddress", debuggerAddress) url = f'http://127.0.0.1:{proxy}/json/version'
browser = await pyppeteer.connect({ logger.info(url)
"browserWSEndpoint": ws browser = await pyppeteer.connect({
}) "browserWSEndpoint": requests.get(url).json()['webSocketDebuggerUrl'],
page = await browser.newPage() 'args': [
logger.info('打开窗口') '--window-size=1536,824',
await page.goto('https://discord.com/channels/@me') '--start-maximized',
return page # '--blink-settings=imagesEnabled=false',
'--n-images',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
]
})
page = await browser.newPage()
logger.info('打开窗口')
await page.goto('https://discord.com/channels/@me')
return page
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
return False return False
...@@ -245,6 +404,7 @@ class ToWork: ...@@ -245,6 +404,7 @@ class ToWork:
# 先获取任务 # 先获取任务
tasks = self.get_current_tasks() tasks = self.get_current_tasks()
if len(tasks): if len(tasks):
logger.info(f'{self.browser_item["num"]},打开窗口')
# 打开窗口 # 打开窗口
page = await self.open_browser(self.browser_item) page = await self.open_browser(self.browser_item)
if not page: if not page:
...@@ -256,11 +416,8 @@ class ToWork: ...@@ -256,11 +416,8 @@ class ToWork:
status = await self.run_task(self.browser_item, tasks, page) status = await self.run_task(self.browser_item, tasks, page)
if status == False: if status == False:
logger.info('请检查自动化') logger.info('请检查自动化')
time.sleep(3)
else: logger.info('不存在任务,等待3秒')
time.sleep(3)
logger.info('不存在任务,等待3秒')
break
async def run_task(self, browser_item, tasks, page): async def run_task(self, browser_item, tasks, page):
try: try:
...@@ -276,19 +433,19 @@ class ToWork: ...@@ -276,19 +433,19 @@ class ToWork:
logger.info('登录成功') logger.info('登录成功')
# 等待服务器元素出现 # 等待服务器元素出现
server_el = '//div[contains(@aria-label, "测试服务器")]' server_el = '//div[contains(@aria-label, "测试服务器")]'
element = self.CheckElement(page, server_el, 20) element = await self.CheckElement(page, server_el, 20)
if element: if element:
# 点击指定服务器 # 点击指定服务器
status = self.ElementClick(page, server_el, '测试服务器') status = await self.ElementClick(page, server_el, '测试服务器')
if status: if status:
# 等待聊天窗口出现 # 等待聊天窗口出现
input_el = '//*[@role="textbox"]' input_el = '//*[@role="textbox"]'
element = self.CheckElement(page, 'xpath', input_el) element = await self.CheckElement(page, input_el)
if element: if element:
logger.info('聊天窗口存在') logger.info('聊天窗口存在')
# 输入指令 # 输入指令
self.enter_prompt(page, tasks) await self.enter_prompt(page, tasks)
logger.info('元素未找到,任务暂停') return True
return False return False
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
...@@ -298,16 +455,24 @@ class ToWork: ...@@ -298,16 +455,24 @@ class ToWork:
def process_start(browser_item, lock): def process_start(browser_item, lock):
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
keyword = ToWork(browser_item, lock) keyword = ToWork(browser_item, lock)
# 生产
loop.run_until_complete(keyword.on_start()) loop.run_until_complete(keyword.on_start())
# 测试
# task = {
# 'policy': 'http://test.phpgpt.com/api/users/config/policy2'
# }
# href = 'https://cdn.discordapp.com/attachments/1090583268467945475/1093734564188409946/suifeng_a_very_cute_boys_16_years_old_fly_a_kitein_beautifulstr_cd2d65d6-ea40-432b-9941-c796504b6082.png'
# loop.run_until_complete(keyword.upload_img(task, href))
if __name__ == '__main__': if __name__ == '__main__':
# 测试-两个任务 # 测试-两个任务
browser_list = [ browser_list = [
{ {
# 7 # 1
'num': 7, 'num': 1,
'id': '1115ce586624431a8b7bcba8b1e82035' 'id': '2A61BF52-6997-4290-AF3D-7FD7F8FC9CA6'
}, },
# { # {
# # 9 # # 9
......
...@@ -16,13 +16,13 @@ def createOrUpdateBrowser(browser_item): # 创建或者更新窗口 ...@@ -16,13 +16,13 @@ def createOrUpdateBrowser(browser_item): # 创建或者更新窗口
# 9 db474b6936a24a7a949377a6d90b4dcb # 9 db474b6936a24a7a949377a6d90b4dcb
'id': browser_item['id'], # 有值时为修改,无值是添加 'id': browser_item['id'], # 有值时为修改,无值是添加
# 'groupId': '2c996b378054663b01805a69f0344410', # 群组ID,绑定群组时传入,如果登录的是子账号,则必须赋值,否则会自动分配到主账户下面去 # 'groupId': '2c996b378054663b01805a69f0344410', # 群组ID,绑定群组时传入,如果登录的是子账号,则必须赋值,否则会自动分配到主账户下面去
'platform': 'https://discord.com', # 账号平台 # 'platform': 'https://discord.com', # 账号平台
'platformIcon': 'discord', # 取账号平台的 hostname 或者设置为other # 'platformIcon': 'discord', # 取账号平台的 hostname 或者设置为other
'url': '', # 打开的url,多个用,分开 # 'url': '', # 打开的url,多个用,分开
'name': 'Discord', # 窗口名称 'name': 'Discord', # 窗口名称
'remark': '登录discord', # 备注 'remark': '登录discord', # 备注
'userName': '', # 用户账号 # 'userName': '', # 用户账号
'password': '', # 用户密码 # 'password': '', # 用户密码
'cookie': '', # Cookie,符合标准的序列化字符串,具体可参考文档 'cookie': '', # Cookie,符合标准的序列化字符串,具体可参考文档
# IP库,默认ip-api,选项 ip-api | ip123in | luminati,luminati为Luminati专用 # IP库,默认ip-api,选项 ip-api | ip123in | luminati,luminati为Luminati专用
'ipCheckService': 'ip-api', 'ipCheckService': 'ip-api',
......
...@@ -146,9 +146,9 @@ class ToWork: ...@@ -146,9 +146,9 @@ class ToWork:
# 选择指令 # 选择指令
prompt_el = '//*[@id="autocomplete-0"]' prompt_el = '//*[@id="autocomplete-0"]'
# 等待选择指令元素出现 # 等待选择指令元素出现
element = self.CheckElement(dricer, 'xpath', prompt_el, 5) element = self.CheckElement(dricer, prompt_el, 5)
if element: if element:
status = self.ElementClick(dricer, 'xpath', prompt_el, '选择指令') status = self.ElementClick(dricer, prompt_el, '选择指令')
if status: if status:
change_prompt = task['prompt'] change_prompt = task['prompt']
# 图片链接 # 图片链接
......
import uuid
from multiprocessing import Process, Lock
import asyncio
from loguru import logger
from Helper import RedisCon
import requests
import os
import oss2
class DownLoad:
def __init__(self, lock, task):
self.key = ''
self.lock = lock
self.task = task
self.header = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': ''
}
async def download_img(self, url, cur_uuid):
"""
下载图片
:param url:
:return:
"""
for i in range(3):
try:
get_file = requests.get(url=url, headers=self.header, stream=True, allow_redirects=False, timeout=10)
file_name = cur_uuid
if not os.path.exists('./download'):
os.makedirs('./download')
path = f'./download/{file_name}'
with open(path, "wb") as Pypdf:
for chunk in get_file.iter_content(chunk_size=1024): # 1024 bytes
if chunk:
Pypdf.write(chunk)
return path
except Exception as e:
logger.error(e)
async def upload_ali_oss(self, path, cur_uuid):
access_key_id = os.getenv('key', 'cener')
access_key_secret = os.getenv('OSS_TEST_ACCESS_KEY_SECRET', 'xxxxxxxxxxxxxxx')
bucket_name = os.getenv('OSS_TEST_BUCKET', 'xxxx-test')
endpoint = os.getenv('OSS_TEST_ENDPOINT', 'oss-cn-shenzhen.aliyuncs.com')
base_file_url = 'xxxxx-test.oss-cn-shenzhen.aliyuncs.com'
bucket_folder = 'test/' # bucket_folder = 'test/'
# 开始
async def on_start(self):
logger.info('开始执行')
cur_uuid = uuid.uuid4()
cur_uuid = str(cur_uuid) + '.png'
# 下载图片
path = await self.download_img(self.task['result_img'], cur_uuid)
if path:
logger.info('图片下载成功')
# 图片下载成功--准备上传阿里云
await self.upload_ali_oss(path, cur_uuid)
else:
# 图片下载失败-直接回调-失败状态
print('111')
def process_start(lock, task):
loop = asyncio.get_event_loop()
keyword = DownLoad(lock, task)
# 生产
loop.run_until_complete(keyword.on_start())
if __name__ == '__main__':
# 获取任务并实例化
key = 'laravel_database_discord_img_download'
try:
tasks = list()
task_num = RedisCon.get_task_num(key)
logger.info(f'{task_num}个任务')
nums = 10
process = 0
if task_num and task_num > 0:
if task_num < nums:
process = task_num
else:
process = nums
lock = Lock()
l = []
for i in range(process):
task = RedisCon.get_task(key)
p = Process(target=process_start, args=(lock, task))
p.start()
l.append(p) # 将进程加入列表中,这样 5 个子进程就会全部执行
for p in l:
p.join() # 当5 个子进程全部执行完,才会执行主进程
except Exception as e:
logger.error(e)
...@@ -93,7 +93,7 @@ def get_gpt_message(task): ...@@ -93,7 +93,7 @@ def get_gpt_message(task):
if __name__ == '__main__': if __name__ == '__main__':
key = 'laravel_database_gpt_text_prompt' key = 'laravel_database_gpt_text_prompt'
logger.info('开始执行') logger.info('开始执行')
while False: while True:
tasks = list() tasks = list()
# 获取任务数量 # 获取任务数量
task_num = RedisCon.get_task_num(key) task_num = RedisCon.get_task_num(key)
...@@ -115,11 +115,11 @@ if __name__ == '__main__': ...@@ -115,11 +115,11 @@ if __name__ == '__main__':
tasks.append(get_gpt_message(task)) tasks.append(get_gpt_message(task))
loop.run_until_complete((asyncio.wait(tasks, timeout=30))) loop.run_until_complete((asyncio.wait(tasks, timeout=30)))
else: else:
logger.info('等待100秒') logger.info('等待3秒')
time.sleep(100) time.sleep(3)
continue continue
test_task = {'type': 2, # test_task = {'type': 2,
'prompt': 'a very cute boys, 16 years old, fly a kite,in beautifulstreet,full body,3d art, c4d, octane render, ray tracting,clay material,popmart blind box,Pixar trend, animationlighting, depth of field, ultra detailed', # 'prompt': 'a very cute boys, 16 years old, fly a kite,in beautifulstreet,full body,3d art, c4d, octane render, ray tracting,clay material,popmart blind box,Pixar trend, animationlighting, depth of field, ultra detailed',
'prompt_img': None, 'user_id': 1, 'prompt_num': 5, # 'prompt_img': None, 'user_id': 1, 'prompt_num': 5,
'callback': 'http://test.phpgpt.com/api/users/gpt/callback', 'task_id': 1} # 'callback': 'http://test.phpgpt.com/api/users/gpt/callback', 'task_id': 1}
get_gpt_message(test_task) # get_gpt_message(test_task)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment