Commit 0d4d5cb6 by lei

1

parent 849e6738
# 默认忽略的文件
/shelf/
/workspace.xml
Img_Ai
\ No newline at end of file
......@@ -2,7 +2,11 @@
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.8" jdkType="Python SDK" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</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 @@
<project version="4">
<component name="ProjectModuleManager">
<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>
</component>
</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
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 requests
import pyperclip
import time
from loguru import logger
......@@ -14,10 +6,13 @@ from bit_api import *
import asyncio
from Helper import RedisCon
import json
from multiprocessing import Process
import random
import pyppeteer
from multiprocessing import Process, Lock
import uuid
import os
from Vmlogin import VmLogin
# 获取当前时间
......@@ -28,11 +23,17 @@ def get_current_time():
class ToWork:
def __init__(self, browser_item, lock):
self.browser_token = 'd8ee6138f2b7ae5e064061e5c29d611a'
self.init_prompt = '/imagine'
self.browser_item = browser_item
self.browser_id = browser_item['id']
self.lock = lock
self.key = 'laravel_database_midjourney_prompt'
self.header = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': ''
}
# 获取浏览器窗口
async def browser(self, browser_id):
......@@ -49,13 +50,21 @@ class ToWork:
def random_sleep(self, 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):
pyperclip.copy(value)
# 粘贴
def driver_paste(self, dricer, value):
ActionChains(dricer).send_keys(Keys.CONTROL, value).perform()
# 粘贴--键盘输入
async def driver_paste(self, page, value):
for i in value:
await page.keyboard.press(i)
# 元素出现的循环次数
async def CheckElement(self, page, path, num=10, check_type='only'):
......@@ -68,7 +77,7 @@ class ToWork:
return element
else:
# 列表
element = self.sleepElementListShow(page, path)
element = await self.sleepElementListShow(page, path)
if element:
# 随机等待
self.random_sleep(1, 2)
......@@ -85,49 +94,152 @@ class ToWork:
return element
return False
except Exception as e:
logger.info(e)
return False
# 找元素,只找一次,不等待
def FindElement(self, custom_el, find_type, value):
async def FindElement(self, custom_el, path, el_type=''):
try:
el = custom_el.find_element(find_type, value)
return el
el = (await custom_el.xpath(path))
# 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:
return False
# 获取元素列表
def sleepElementListShow(self, dricer, type, value):
async def sleepElementListShow(self, page, path):
try:
element = dricer.find_elements(type, value)
if element:
element = (await page.xpath(path))
if len(element):
return element
return False
except Exception as e:
logger.info(e)
return False
# 元素点击-xpath点击
def ElementClick(self, dricer, value, name=''):
try:
task = dricer.find_element(type, value)
if task:
# 随机等待
self.random_sleep(1, 2)
# js 点击
dricer.execute_script("arguments[0].click()", task)
# task.click()
async def ElementClick(self, page, path, name=''):
status = False
for i in range(1, 10):
try:
ele = (await page.xpath(path))[0]
await page.waitFor(self.click_time_rand(1, 2))
await ele.click()
await asyncio.sleep(self.click_time_rand(1, 2))
logger.info(f'{name}-元素存在,开始点击')
return True
logger.info(f'{name}-元素不存在')
return False
status = True
break
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:
logger.info(f'{name}-元素不存在')
logger.error(e)
return False
# 循环输入指令
def enter_prompt(self, dricer, tasks):
if True:
async def img_callback(self, task, href):
# 先要上传图片
# 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()
while True:
......@@ -137,104 +249,151 @@ class ToWork:
if current_time - start_time >= 60:
# end
break
# 开始判断
element = '//ol[@data-list-id="chat-messages"]/li'
# 消息列表
message_list = self.CheckElement(dricer, 'xpath', element, 20, 'list')
if message_list:
logger.info('消息列表存在')
# 找到所有子元素
for e in message_list:
logger.info(e.get_attribute('id'))
# 找到文本并匹配
path = '//div[contains(@data-list-item-id, "chat-messages___chat-messages")]'
label_element = self.FindElement(e, By.XPATH, path)
if label_element:
logger.info(label_element.get_attribute('data-list-item-id'))
cur_type = 1 # 获取最后一个
if cur_type == 1:
logger.info('进入')
# 判断文字中是否存在进度条
text_path = '//div[contains(@id, "message-content-")]'
text_el = await self.FindElement(page, text_path, 'last')
if text_el:
title = await page.evaluate('(element) => element.textContent', text_el)
logger.info(title)
if '%' not in title and '(Waiting to start)' not in title and '正在发送命令' not in title:
logger.info('任务完成')
# 最后一个链接
img_path = '//*[contains(@id, "message-accessories-")]/div[1]/div/div/div/div/div/a'
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:
logger.info('未找到文本')
logger.info('等待300秒')
time.sleep(300)
return
logger.info('任务进行中')
else:
logger.info('文本元素不存在')
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是一个列表
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):
# 测试
# 当前浏览器需要执行的任务
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 False:
task = RedisCon.get_task(self.key)
# 当前浏览器需要执行的任务
cur_tasks = []
if task:
task = json.loads(task)
task['prompt'] = task['prompt'].replace(',', ',')
# 将任务添加到列表
cur_tasks.append(task)
if len(cur_tasks):
return cur_tasks
return []
if len(cur_tasks):
return cur_tasks
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):
try:
logger.info(f'浏览器id-{browser_item["num"]},开始执行')
res = openBrowser(browser_item)
driverPath = res['data']['driver']
debuggerAddress = res['data']['http']
ws = res['data']['ws']
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", debuggerAddress)
browser = await pyppeteer.connect({
"browserWSEndpoint": ws
})
page = await browser.newPage()
logger.info('打开窗口')
await page.goto('https://discord.com/channels/@me')
return page
vm = VmLogin(self.browser_token)
proxy = vm.start_chrome(browser_item['id'])
if not proxy:
logger.info('无法打开浏览器')
else:
url = f'http://127.0.0.1:{proxy}/json/version'
logger.info(url)
browser = await pyppeteer.connect({
"browserWSEndpoint": requests.get(url).json()['webSocketDebuggerUrl'],
'args': [
'--window-size=1536,824',
'--start-maximized',
# '--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:
logger.error(e)
return False
......@@ -245,6 +404,7 @@ class ToWork:
# 先获取任务
tasks = self.get_current_tasks()
if len(tasks):
logger.info(f'{self.browser_item["num"]},打开窗口')
# 打开窗口
page = await self.open_browser(self.browser_item)
if not page:
......@@ -256,11 +416,8 @@ class ToWork:
status = await self.run_task(self.browser_item, tasks, page)
if status == False:
logger.info('请检查自动化')
else:
time.sleep(3)
logger.info('不存在任务,等待3秒')
break
time.sleep(3)
logger.info('不存在任务,等待3秒')
async def run_task(self, browser_item, tasks, page):
try:
......@@ -276,19 +433,19 @@ class ToWork:
logger.info('登录成功')
# 等待服务器元素出现
server_el = '//div[contains(@aria-label, "测试服务器")]'
element = self.CheckElement(page, server_el, 20)
element = await self.CheckElement(page, server_el, 20)
if element:
# 点击指定服务器
status = self.ElementClick(page, server_el, '测试服务器')
status = await self.ElementClick(page, server_el, '测试服务器')
if status:
# 等待聊天窗口出现
input_el = '//*[@role="textbox"]'
element = self.CheckElement(page, 'xpath', input_el)
element = await self.CheckElement(page, input_el)
if element:
logger.info('聊天窗口存在')
# 输入指令
self.enter_prompt(page, tasks)
logger.info('元素未找到,任务暂停')
await self.enter_prompt(page, tasks)
return True
return False
except Exception as e:
logger.error(e)
......@@ -298,16 +455,24 @@ class ToWork:
def process_start(browser_item, lock):
loop = asyncio.get_event_loop()
keyword = ToWork(browser_item, lock)
# 生产
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__':
# 测试-两个任务
browser_list = [
{
# 7
'num': 7,
'id': '1115ce586624431a8b7bcba8b1e82035'
# 1
'num': 1,
'id': '2A61BF52-6997-4290-AF3D-7FD7F8FC9CA6'
},
# {
# # 9
......
......@@ -16,13 +16,13 @@ def createOrUpdateBrowser(browser_item): # 创建或者更新窗口
# 9 db474b6936a24a7a949377a6d90b4dcb
'id': browser_item['id'], # 有值时为修改,无值是添加
# 'groupId': '2c996b378054663b01805a69f0344410', # 群组ID,绑定群组时传入,如果登录的是子账号,则必须赋值,否则会自动分配到主账户下面去
'platform': 'https://discord.com', # 账号平台
'platformIcon': 'discord', # 取账号平台的 hostname 或者设置为other
'url': '', # 打开的url,多个用,分开
# 'platform': 'https://discord.com', # 账号平台
# 'platformIcon': 'discord', # 取账号平台的 hostname 或者设置为other
# 'url': '', # 打开的url,多个用,分开
'name': 'Discord', # 窗口名称
'remark': '登录discord', # 备注
'userName': '', # 用户账号
'password': '', # 用户密码
# 'userName': '', # 用户账号
# 'password': '', # 用户密码
'cookie': '', # Cookie,符合标准的序列化字符串,具体可参考文档
# IP库,默认ip-api,选项 ip-api | ip123in | luminati,luminati为Luminati专用
'ipCheckService': 'ip-api',
......
......@@ -146,9 +146,9 @@ class ToWork:
# 选择指令
prompt_el = '//*[@id="autocomplete-0"]'
# 等待选择指令元素出现
element = self.CheckElement(dricer, 'xpath', prompt_el, 5)
element = self.CheckElement(dricer, prompt_el, 5)
if element:
status = self.ElementClick(dricer, 'xpath', prompt_el, '选择指令')
status = self.ElementClick(dricer, prompt_el, '选择指令')
if status:
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):
if __name__ == '__main__':
key = 'laravel_database_gpt_text_prompt'
logger.info('开始执行')
while False:
while True:
tasks = list()
# 获取任务数量
task_num = RedisCon.get_task_num(key)
......@@ -115,11 +115,11 @@ if __name__ == '__main__':
tasks.append(get_gpt_message(task))
loop.run_until_complete((asyncio.wait(tasks, timeout=30)))
else:
logger.info('等待100秒')
time.sleep(100)
logger.info('等待3秒')
time.sleep(3)
continue
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_img': None, 'user_id': 1, 'prompt_num': 5,
'callback': 'http://test.phpgpt.com/api/users/gpt/callback', 'task_id': 1}
get_gpt_message(test_task)
# 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_img': None, 'user_id': 1, 'prompt_num': 5,
# 'callback': 'http://test.phpgpt.com/api/users/gpt/callback', 'task_id': 1}
# 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