通过 Python \text{Python} Python 仿真一个 FireFox or Chrome \text{FireFox or Chrome} FireFox or Chrome 浏览器,然后通过 send_keys \text{send\_keys} send_keys 发送数据到 input \text{input} input 文本框,当数据字节数比较小时,完全不会发现任何异常,但是当发送长文本时,会出现卡顿或者阻塞的现象,导致数据的实时性下降了很多。
查看 send_keys \text{send\_keys} send_keys 源码:
def
send_keys
(
self
,
*
keys_to_send
)
:
"""
Sends keys to current focused element.
:Args:
- keys_to_send: The keys to send. Modifier keys constants can be found in the
'Keys' class.
"""
typing
=
keys_to_typing
(
keys_to_send
)
if
self
.
_driver
.
w3c
:
for
key
in
typing
:
self
.
key_down
(
key
)
self
.
key_up
(
key
)
else
:
self
.
_actions
.
append
(
lambda
:
self
.
_driver
.
execute
(
Command
.
SEND_KEYS_TO_ACTIVE_ELEMENT
,
{
'value'
:
typing
}
)
)
return
self
def
keys_to_typing
(
value
)
:
"""Processes the values that will be typed in the element."""
typing
=
[
]
for
val
in
value
:
if
isinstance
(
val
,
Keys
)
:
typing
.
append
(
val
)
elif
isinstance
(
val
,
int
)
:
val
=
str
(
val
)
for
i
in
range
(
len
(
val
)
)
:
typing
.
append
(
val
[
i
]
)
else
:
for
i
in
range
(
len
(
val
)
)
:
typing
.
append
(
val
[
i
]
)
return
typing
可以发现 keys_to_typing \text{keys\_to\_typing} keys_to_typing 函数将 value \text{value} value 逐个拆分成字符放到列表中,然后再做其他处理,并不是特别理解他为什么要这样去做(没有进一步去探索原因),但是可以肯定的是,当数据量大的时候,这会大大的提高 send_keys \text{send\_keys} send_keys 的时间,继而造成卡顿的状况。
解决方案是内嵌 js \text{js} js 进行赋值:
js
=
"element = document.getElementById('text');"
\
"element.value = 'xxx';"
driver
.
execute_script
(
js
)
这样便可以避免拆分字符所造成的卡顿问题,但是同样带来了一个新的问题——无法使用 selenimu.webdriver.common.keys \text{selenimu.webdriver.common.keys} selenimu.webdriver.common.keys 来触发事件。因为如上发送文本后并不会触发任何事件(例如 change \text{change} change 事件),而我们往往会用到这些事件来结束一次输入刷新数据,所以需要找到对应的触发方案。
解决这个问题的方法是使用 fireEvents or dispatchEvent \text{fireEvents or dispatchEvent} fireEvents or dispatchEvent ,前者是在较老或者低级的浏览器中可以使用,后者在 FireFox or Chrome \text{FireFox or Chrome} FireFox or Chrome 中使用。由于我使用的是 FireFox \text{FireFox} FireFox ,所以如下:
js
=
"element = document.getElementById('text');"
\
"element.value = 'xxx';"
\
"event = document.createEvent('HTMLEvents');"
\
"event.initEvent('change', true, true);"
\
"element.dispatchEvent(event);"
driver
.
execute_script
(
js
)
完美解决发送长文本卡顿的问题,不过如果需要发送很多次数据的时候,上述 js \text{js} js 代码中有些部分没必要执行多次,但是由于是内嵌在 Python \text{Python} Python 中,所以么得法子……或者说,我不知道怎么优化,没有学过 js \text{js} js 也是第一次尝试嵌到 Python \text{Python} Python 中。
另外,有网友称也可以通过将数据复制到粘贴板然后直接粘贴到输入框,未测试。