Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
python_open_ai
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
haojie
python_open_ai
Commits
bec065dd
Commit
bec065dd
authored
Apr 14, 2023
by
lei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1
parent
ae8c6e36
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
5 additions
and
606 deletions
+5
-606
Helper.py
+0
-596
test.py
+5
-10
No files found.
Helper.py
View file @
bec065dd
import
re
import
time
import
json
import
redis
import
random
import
aiohttp
import
requests
from
web3
import
Web3
from
web3.eth
import
AsyncEth
import
datetime
import
itertools
import
eth_utils
import
numpy
as
np
from
lxml
import
etree
from
fake_useragent
import
UserAgent
from
aredis
import
StrictRedis
,
ConnectionPool
from
web3._utils.abi
import
get_abi_output_types
,
map_abi_data
from
web3._utils.normalizers
import
BASE_RETURN_NORMALIZERS
uni256Max
=
2
**
256
...
...
@@ -366,32 +357,6 @@ class Helper:
print
(
"Redis setex error"
,
e
)
@staticmethod
async
def
get_functions_
(
fn_abi
,
transaction
,
web_async
):
"""
web3 get_functions_
:param fn_abi:
:param transaction:
:param web_async:
:return:
"""
eth
=
AsyncEth
(
web_async
)
contract
=
await
eth
.
call
(
transaction
)
output_types
=
get_abi_output_types
(
fn_abi
)
output_data
=
web_async
.
codec
.
decode_abi
(
output_types
,
contract
)
_normalizers
=
itertools
.
chain
(
BASE_RETURN_NORMALIZERS
,
(),
)
normalized_data
=
map_abi_data
(
_normalizers
,
output_types
,
output_data
)
# print(normalized_data)
if
len
(
normalized_data
)
==
1
:
return
normalized_data
[
0
]
else
:
return
normalized_data
@staticmethod
async
def
get_token_decimals
(
token
,
web_async
):
"""
web3 decimals
...
...
@@ -547,450 +512,6 @@ class Helper:
return
function
@staticmethod
async
def
get_token_detail_web
(
token
,
chain
):
"""
get goPlus token detail
:param token:
:param chain:
:return:
"""
url
=
f
'https://api.gopluslabs.io/api/v1/token_security/{chain}?contract_addresses={token}'
async
with
aiohttp
.
ClientSession
()
as
session
:
proxy
=
Helper
.
aiohttp_proxy_pool
()
headers
=
Helper
.
getHeaders
()
res
=
await
session
.
get
(
url
,
headers
=
headers
,
proxy
=
proxy
,
timeout
=
10
)
res
=
await
res
.
text
()
da
=
json
.
loads
(
res
)
return
da
[
'result'
][
token
.
lower
()]
if
token
.
lower
()
in
da
[
'result'
]
else
{}
@staticmethod
async
def
get_sell_radio
(
token
,
sell_num
,
token_d
,
address
,
web_async
):
"""
get sell radio
:param token:
:param sell_num:
:param token_d:
:param address:
:param web_async:
:return:
"""
if
address
is
not
None
:
balance
=
await
Helper
.
get_token_balance
(
token
,
address
,
web_async
)
balance
=
balance
/
(
10
**
token_d
)
sell_radio
=
sell_num
/
(
sell_num
+
balance
)
return
{
'radio'
:
sell_radio
,
'balance'
:
balance
,
}
else
:
return
{
'radio'
:
None
,
'balance'
:
None
,
}
@staticmethod
async
def
balancer_sell_radio
(
token
,
token_d
,
tx_hash
,
token_a
,
sell_num
,
web_async
):
"""
balancer sell info
:param token:
:param token_d:
:param tx_hash:
:param token_a:
:param sell_num:
:param web_async:
:return:
"""
tran_str
=
Helper
.
tran_str
()
pool
=
"0x000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8"
receipt
=
await
web_async
.
eth
.
get_transaction_receipt
(
tx_hash
)
logs
=
receipt
[
'logs'
]
address
=
None
for
log
in
logs
:
if
log
[
'address'
]
==
token
and
log
[
'topics'
][
0
]
.
hex
()
==
tran_str
and
log
[
'topics'
][
2
]
.
hex
()
==
pool
and
eval
(
log
[
'data'
])
==
token_a
:
address
=
log
[
'topics'
][
1
]
.
hex
()
address
=
web_async
.
toChecksumAddress
(
Helper
.
hex2bsc
(
address
))
break
else
:
pass
sell_radio
,
balance
=
None
,
None
if
address
is
not
None
:
balance
=
await
Helper
.
get_token_balance
(
token
,
address
,
web_async
)
balance
=
balance
/
(
10
**
token_d
)
sell_radio
=
sell_num
/
(
sell_num
+
balance
)
return
{
'address'
:
address
,
'radio'
:
sell_radio
,
'balance'
:
balance
}
@staticmethod
async
def
Beethoven_sell_radio
(
token
,
token_d
,
tx_hash
,
token_a
,
sell_num
,
web_async
):
"""
beethoven sell info
:param token:
:param token_d:
:param tx_hash:
:param token_a:
:param sell_num:
:param web_async:
:return:
"""
tran_str
=
Helper
.
tran_str
()
pool
=
"0x00000000000000000000000020dd72ed959b6147912c2e529f0a0c651c33c9ce"
receipt
=
await
web_async
.
eth
.
get_transaction_receipt
(
tx_hash
)
logs
=
receipt
[
'logs'
]
address
=
None
for
log
in
logs
:
if
log
[
'address'
]
==
token
and
log
[
'topics'
][
0
]
.
hex
()
==
tran_str
and
log
[
'topics'
][
2
]
.
hex
()
==
pool
and
eval
(
log
[
'data'
])
==
token_a
:
address
=
log
[
'topics'
][
1
]
.
hex
()
address
=
web_async
.
toChecksumAddress
(
Helper
.
hex2bsc
(
address
))
break
else
:
pass
sell_radio
,
balance
=
None
,
None
if
address
is
not
None
:
balance
=
await
Helper
.
get_token_balance
(
token
,
address
,
web_async
)
balance
=
balance
/
(
10
**
token_d
)
sell_radio
=
sell_num
/
(
sell_num
+
balance
)
return
{
'address'
:
address
,
'radio'
:
sell_radio
,
'balance'
:
balance
}
@staticmethod
async
def
get_new_holder
(
token
,
token_d
,
address
,
buy_num
,
web_async
):
"""
get new holder info
:param token:
:param token_d:
:param address:
:param buy_num:
:param web_async:
:return:
"""
address
=
web_async
.
toChecksumAddress
(
address
)
balance
=
await
Helper
.
get_token_balance
(
token
,
address
,
web_async
)
balance
=
balance
/
(
10
**
token_d
)
if
balance
<=
buy_num
:
new
=
1
else
:
new
=
0
return
{
'balance'
:
balance
,
'new'
:
new
}
@staticmethod
async
def
balancer_new_holder
(
token
,
tx_hash
,
token_a
,
web_async
):
"""
balancer new holder info
:param token:
:param tx_hash:
:param token_a:
:param web_async:
:return:
"""
tran_str
=
Helper
.
tran_str
()
pool
=
"0x000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8"
receipt
=
await
web_async
.
eth
.
get_transaction_receipt
(
tx_hash
)
logs
=
receipt
[
'logs'
]
address
=
None
for
log
in
logs
:
if
log
[
'address'
]
==
token
and
log
[
'topics'
][
0
]
.
hex
()
==
tran_str
and
log
[
'topics'
][
1
]
.
hex
()
==
pool
and
eval
(
log
[
'data'
])
==
token_a
:
address
=
log
[
'topics'
][
2
]
.
hex
()
address
=
web_async
.
toChecksumAddress
(
Helper
.
hex2bsc
(
address
))
break
else
:
pass
# print('address', address)
new
,
balance
=
0
,
0
if
address
is
not
None
:
balance
=
await
Helper
.
get_token_balance
(
token
,
address
,
web_async
)
if
balance
==
token_a
:
new
=
1
return
{
'balance'
:
balance
,
'address'
:
address
,
'new'
:
new
}
@staticmethod
async
def
Beethoven_new_holder
(
token
,
tx_hash
,
token_a
,
web_async
):
"""
beethoven new holder info
:param token:
:param tx_hash:
:param token_a:
:param web_async:
:return:
"""
tran_str
=
Helper
.
tran_str
()
pool
=
"0x00000000000000000000000020dd72ed959b6147912c2e529f0a0c651c33c9ce"
receipt
=
await
web_async
.
eth
.
get_transaction_receipt
(
tx_hash
)
logs
=
receipt
[
'logs'
]
address
=
None
for
log
in
logs
:
if
log
[
'address'
]
==
token
and
log
[
'topics'
][
0
]
.
hex
()
==
tran_str
and
log
[
'topics'
][
1
]
.
hex
()
==
pool
and
eval
(
log
[
'data'
])
==
token_a
:
address
=
log
[
'topics'
][
2
]
.
hex
()
address
=
web_async
.
toChecksumAddress
(
Helper
.
hex2bsc
(
address
))
break
else
:
pass
# print('address', address)
new
,
balance
=
0
,
0
if
address
is
not
None
:
balance
=
await
Helper
.
get_token_balance
(
token
,
address
,
web_async
)
if
balance
==
token_a
:
new
=
1
return
{
'balance'
:
balance
,
'address'
:
address
,
'new'
:
new
}
@staticmethod
async
def
sell_address
(
logs
,
token
,
pool
,
amount
,
web_async
):
"""
get sell address
:param logs:
:param token:
:param pool:
:param amount:
:param web_async:
:return:
"""
tran_str
=
Helper
.
tran_str
()
address
=
None
for
log
in
logs
:
if
log
[
'address'
]
==
token
and
log
[
'topics'
][
0
]
.
hex
()
==
tran_str
and
log
[
'topics'
][
2
]
.
hex
()
==
pool
and
eval
(
log
[
'data'
])
==
amount
:
address
=
log
[
'topics'
][
1
]
.
hex
()
address
=
web_async
.
toChecksumAddress
(
Helper
.
hex2bsc
(
address
))
break
else
:
pass
if
address
is
None
:
for
log
in
logs
:
if
log
[
'address'
]
==
token
and
log
[
'topics'
][
0
]
.
hex
()
==
tran_str
and
log
[
'topics'
][
2
]
.
hex
()
==
pool
:
address
=
log
[
'topics'
][
1
]
.
hex
()
address
=
web_async
.
toChecksumAddress
(
Helper
.
hex2bsc
(
address
))
break
else
:
pass
return
address
@staticmethod
def
hex2bsc
(
address
):
"""
change hex-address
:param address:
:return:
"""
address
=
'0x'
+
address
[
26
:]
return
address
@staticmethod
def
normalize_32_byte_hex_address
(
address
):
"""
change type toCheckAddress
:param address:
:return:
"""
as_bytes
=
eth_utils
.
to_bytes
(
hexstr
=
address
)
return
eth_utils
.
to_normalized_address
(
as_bytes
[
-
20
:])
@staticmethod
def
checksumAddress
(
address
,
web_async
):
"""
web3 checkAddress
:param address:
:param web_async:
:return:
"""
address
=
Helper
.
normalize_32_byte_hex_address
(
address
)
return
web_async
.
toChecksumAddress
(
address
)
@staticmethod
async
def
wBalances
(
amount
,
p_token
,
p_token_symbol
,
pDecimals
,
wToken
,
Router
,
redisKey
,
wDecimals
,
web_async
):
"""
get wrap pool balance
:param amount
:param p_token
:param p_token_symbol
:param pDecimals
:param wToken
:param Router
:param redisKey
:param wDecimals
:param web_async
"""
redis_con
=
StrictRedis
(
connection_pool
=
RedisConnectionPoolSingleton
())
rate
=
await
redis_con
.
get
(
f
'{redisKey}:rate:'
+
p_token_symbol
+
'-W'
)
opType
=
[
'opt'
,
'can'
]
if
rate
is
None
:
if
redisKey
in
opType
:
rate
=
await
Helper
.
get_amounts_out_op
(
p_token
,
wToken
,
web_async
,
Router
,
pDecimals
)
else
:
rate
=
await
Helper
.
get_amounts_out
(
p_token
,
wToken
,
web_async
,
Router
,
pDecimals
)
rate
=
rate
[
1
]
/
(
10
**
wDecimals
)
await
redis_con
.
setex
(
f
'{redisKey}:rate:'
+
p_token_symbol
+
'-W'
,
60
,
rate
)
else
:
rate
=
json
.
loads
(
rate
)
w_balances
=
amount
*
rate
return
w_balances
@staticmethod
def
trans_address
(
address
):
"""
change address-hex
:param address:
:return:
"""
address
=
address
[
2
:]
while
len
(
address
)
<
64
:
address
=
'0'
+
address
address
=
'0x'
+
address
return
address
.
lower
()
@staticmethod
async
def
get_pool_swap
(
pair
,
web_async
):
"""
get pool swap type
:param pair:
:param web_async:
:return:
"""
status
=
0
pool_swap
=
''
info
=
await
Helper
.
query_hash
(
"taos:search:saved"
,
pair
)
if
info
is
not
None
:
info
=
json
.
loads
(
info
)
if
"swap"
in
info
:
pool_swap
=
info
[
'swap'
]
status
=
1
if
status
==
0
:
try
:
pool_swap
=
await
Helper
.
get_token_name
(
pair
,
web_async
)
except
:
pool_swap
=
'Error Contract'
return
{
"swap"
:
pool_swap
,
"status"
:
status
}
@staticmethod
async
def
pair_balance
(
p_token
,
p_token_d
,
pair_address
,
redisKey
,
swapType
,
p_amount
,
web_async
):
"""
get pair balance
:param p_token
:param p_token_d
:param pair_address
:param redisKey
:param swapType
:param p_amount
:param web_async
"""
status
=
0
balance
=
await
Helper
.
query_hash
(
f
"{redisKey}:balance"
,
pair_address
)
if
balance
is
None
:
status
=
1
else
:
balance
=
json
.
loads
(
balance
)
ts_before
=
Helper
.
get_time_stamp
(
balance
[
'time'
])
ts
=
Helper
.
get_time_stamp
(
Helper
.
get_time
())
if
ts
-
ts_before
>
300
:
status
=
1
else
:
if
swapType
==
"sell"
:
balance
[
'p_balance'
]
-=
p_amount
else
:
balance
[
'p_balance'
]
+=
p_amount
if
balance
[
'p_balance'
]
<
0
:
status
=
1
if
status
==
1
:
p_token_balance
=
await
Helper
.
get_token_balance
(
p_token
,
pair_address
,
web_async
)
balance
=
{
'time'
:
Helper
.
get_time
(),
'p_balance'
:
(
p_token_balance
/
(
10
**
p_token_d
))
}
await
Helper
.
save_hash_data
(
f
"{redisKey}:balance"
,
pair_address
,
json
.
dumps
(
balance
))
return
balance
@staticmethod
async
def
public2usd
(
pToken
,
pSymbol
,
usd
,
redisKey
,
Router
,
uDecimals
,
pDecimals
,
web_async
):
"""
get public token - usd rate
:param pToken
:param pSymbol
:param usd
:param redisKey
:param Router
:param uDecimals
:param pDecimals
:param web_async
"""
busd_bsc
=
"0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"
# BUSD (bsc)
weth_bsc
=
"0x2170Ed0880ac9A755fd29B2688956BD959F933F8"
# ETH (bsc)
wbtc_bsc
=
"0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"
# BTCB (bsc)
router_bsc
=
"0x10ED43C718714eb63d5aA57B78B54704E256024E"
# pancakeSwapV2Router
redis_con
=
StrictRedis
(
connection_pool
=
RedisConnectionPoolSingleton
())
rate
=
await
redis_con
.
get
(
f
'{redisKey}:rate:'
+
pSymbol
+
'-U'
)
opType
=
[
'opt'
,
'can'
]
chainErrorRouter
=
[
'cro'
,
'aur'
,
'gno'
,
'opt'
,
'cel'
,
'met'
,
'ast'
]
chainErrorToken
=
[
'WETH'
,
'WBTC'
]
if
rate
is
None
:
if
pSymbol
==
'WETH'
and
redisKey
in
chainErrorRouter
:
bsc_rate
=
await
redis_con
.
get
(
'bsc:rate:WETH-U'
)
if
bsc_rate
is
None
:
rate
=
await
Helper
.
get_amounts_out
(
weth_bsc
,
busd_bsc
,
Helper
.
getWeb3Bsc
(),
router_bsc
,
18
)
uDecimals
=
18
rate
=
rate
[
1
]
/
(
10
**
uDecimals
)
await
redis_con
.
setex
(
'bsc:rate:WETH-U'
,
60
,
rate
)
else
:
rate
=
json
.
loads
(
bsc_rate
)
return
rate
elif
pSymbol
==
'WBTC'
and
redisKey
in
chainErrorRouter
:
bsc_rate
=
await
redis_con
.
get
(
'bsc:rate:WBTC-U'
)
if
bsc_rate
is
None
:
rate
=
await
Helper
.
get_amounts_out
(
wbtc_bsc
,
busd_bsc
,
Helper
.
getWeb3Bsc
(),
router_bsc
,
18
)
uDecimals
=
18
rate
=
rate
[
1
]
/
(
10
**
uDecimals
)
await
redis_con
.
setex
(
'bsc:rate:WBTC-U'
,
60
,
rate
)
else
:
rate
=
json
.
loads
(
bsc_rate
)
return
rate
elif
redisKey
in
opType
and
pSymbol
not
in
chainErrorToken
:
rate
=
await
Helper
.
get_amounts_out_op
(
pToken
,
usd
,
web_async
,
Router
,
pDecimals
)
else
:
rate
=
await
Helper
.
get_amounts_out
(
pToken
,
usd
,
web_async
,
Router
,
pDecimals
)
rate
=
rate
[
1
]
/
(
10
**
uDecimals
)
await
redis_con
.
setex
(
f
'{redisKey}:rate:'
+
pSymbol
+
'-U'
,
60
,
rate
)
else
:
rate
=
json
.
loads
(
rate
)
return
rate
@staticmethod
async
def
redis_data
(
data
,
info
,
ts_
,
redisKey
,
public_token
,
chainId
,
stable
,
search_table
,
web_async
):
"""
taos save insert task list
...
...
@@ -1104,68 +625,6 @@ class Helper:
return
amountIn
,
amountOut
@staticmethod
async
def
get_usd_price_V2
(
p_token
,
p_token_d
,
p_token_symbol
,
price
,
usd_token
,
uToken
,
redisKey
,
Router
,
uDecimals
,
web_async
):
"""
get usd price
:param p_token
:param p_token_d
:param p_token_symbol
:param price
:param usd_token
:param web_async
:param uToken
:param redisKey
:param Router
:param uDecimals
"""
if
p_token
in
usd_token
:
usd_price
=
price
else
:
rate
=
await
Helper
.
public2usd
(
p_token
,
p_token_symbol
,
uToken
,
redisKey
,
Router
,
uDecimals
,
p_token_d
,
web_async
)
usd_price
=
rate
*
price
return
usd_price
@staticmethod
async
def
get_token_detail
(
p_token
,
p_token_d
,
p_token_symbol
,
pool_address
,
usd_token
,
wToken
,
wDecimals
,
uToken
,
uDecimals
,
redisKey
,
Router
,
swapType
,
p_amount
,
web_async
):
"""
get token info
:param p_token
:param p_token_d
:param p_token_symbol
:param pool_address
:param usd_token
:param wToken
:param wDecimals
:param uToken
:param uDecimals
:param redisKey
:param Router
:param swapType
:param p_amount
:param web_async
"""
balance
=
await
Helper
.
pair_balance
(
p_token
,
p_token_d
,
pool_address
,
redisKey
,
swapType
,
p_amount
,
web_async
)
p_balance
=
balance
[
'p_balance'
]
u_balance
=
await
Helper
.
get_usd_price_V2
(
p_token
,
p_token_d
,
p_token_symbol
,
p_balance
,
usd_token
,
uToken
,
redisKey
,
Router
,
uDecimals
,
web_async
)
if
p_token
==
wToken
:
w_balance
=
p_balance
else
:
w_balance
=
await
Helper
.
wBalances
(
p_balance
,
p_token
,
p_token_symbol
,
p_token_d
,
wToken
,
Router
,
redisKey
,
wDecimals
,
web_async
)
detail
=
{
'pair_balance'
:
p_balance
,
'usd_balance'
:
u_balance
,
'wbnb_balance'
:
w_balance
}
return
detail
@staticmethod
async
def
redisSaveList
(
pool
,
dataProcess
,
redisKey
,
public_token
,
chainId
,
stable
,
search_table
,
web_async
):
"""
redis task list
...
...
@@ -1439,61 +898,6 @@ class Helper:
return
troops
@staticmethod
async
def
getHolderNum
(
chain
,
token
):
"""
get holder nums
:param chain:
:param token:
:return:
"""
if
chain
==
56
:
url
=
f
"https://bscscan.com/token/generic-tokenholders2?m=normal&a={token}&s=8000000000000&sid=&p=1"
else
:
url
=
f
"https://cn.etherscan.com/token/generic-tokenholders2?m=normal&a={token}&s=888888888000000000&sid=&p=1"
holder_num
=
0
for
i
in
range
(
5
):
try
:
proxy
=
Helper
.
aiohttp_proxy_pool
()
res
=
await
Helper
.
request_page
(
url
,
proxy
)
html
=
etree
.
HTML
(
res
)
holder_list
=
html
.
xpath
(
'//*[@class="mb-2 mb-md-0"]/text()'
)[
0
]
.
strip
()
holder_num
=
re
.
findall
(
r"\d+,?\d*"
,
holder_list
)[
0
]
# 代币持仓人数
holder_num
=
int
(
holder_num
.
replace
(
','
,
''
))
break
except
Exception
as
e
:
print
(
"get holder nums error!"
,
e
)
return
holder_num
@staticmethod
def
getWeb3Bsc
():
"""
async bsc web3
:return:
"""
bsc
=
"https://rpc.ankr.com/bsc"
# proxy = Helper.aiohttp_proxy_pool()
# request_kwargs={"proxy": proxy}
web_async
=
Web3
(
Web3
.
AsyncHTTPProvider
(
bsc
),
modules
=
{
'eth'
:
(
AsyncEth
,)},
middlewares
=
[])
return
web_async
@staticmethod
def
getWeb3Eth
():
"""
async eth web3
:return:
"""
eth
=
"https://rpc.ankr.com/eth"
proxy
=
Helper
.
aiohttp_proxy_pool
()
web_async
=
Web3
(
Web3
.
AsyncHTTPProvider
(
eth
,
request_kwargs
=
{
"proxy"
:
proxy
}),
modules
=
{
'eth'
:
(
AsyncEth
,)},
middlewares
=
[])
return
web_async
@staticmethod
def
bscPoolType
(
token
):
"""
bsc public token
...
...
test.py
View file @
bec065dd
...
...
@@ -70,24 +70,19 @@ async def main():
page
=
cur_pages
[
0
]
await
page
.
goto
(
'https://discord.com/channels/@me'
)
await
login
(
page
)
time
.
sleep
(
20
)
# 测试文字
test_title
=
'你好你好你好222'
# 插入文本
input_path
=
'//*[@id="app-mount"]/div[2]/div[1]/div[1]/div/div[2]/div/div/div/div/div[2]/div/main/form/div/div[2]/div/div[2]/div/div/div/span[2]/span[2]/span/span/span'
element
=
await
FindElement
(
page
,
input_path
)
# var evt = new InputEvent('input', {
# inputType: 'insertText',
# data: st,
# dataTransfer: null,
# isComposing: false
# });
# dom.dispatchEvent(evt);
if
element
:
await
page
.
evaluate
(
'''(element,test_title) => {
element.innerHTML = test_title
var dom = document.querySelector('body')
console.log(dom)
dom.value = test_title
const ke = new KeyboardEvent('keydown', {
bubbles: true, cancelable: true, keyCode: 49
});
document.body.dispatchEvent(ke);
}'''
,
element
,
test_title
)
logger
.
info
(
'成功'
)
# 回车
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment