直接執行 js ,就用 execute_script() 就可以。
從 selenium 的source code 來看,有3種執行script 的方式,其中2個是非同步:
https://github.com/SeleniumHQ/selenium/blob/trunk/py/selenium/webdriver/remote/command.py
W3C_EXECUTE_SCRIPT: str = "w3cExecuteScript"
W3C_EXECUTE_SCRIPT_ASYNC: str = "w3cExecuteScriptAsync"
EXECUTE_ASYNC_SCRIPT: str = "executeAsyncScript"
範例python script
script = """
var callback = arguments[arguments.length - 1];
window.setTimeout(function(){ callback('timeout') }, 3000);
"""
driver.execute_async_script(script)
範例2號:
js = """var t = JSON.parse(Cookies.get("user")) ? JSON.parse(Cookies.get("user")).access_token : "";
fetch("%s",{headers: {
authorization: "Bearer ".concat(t)
}}).then(function (response) {
return response.json();
}).then(function (data) {
console.log(data);
if(data.result.product.length>0)
if(data.result.product[0].status=="pending") {
console.log("pending, start to reload");
location.reload();
}
}).catch(function (err){
console.log(err);
});
""" % getSeatsByTicketAreaIdUrl
driver.set_script_timeout(0.1)
driver.execute_async_script(js)
說明:經測試,用使 jQuery 的 ajax 或是使用 fetch 的 promise 都無法在 ajax 傳回的那一個區塊使用下面的程式碼傳回資料:
var callback = arguments[arguments.length - 1];
callback(data);
variable scope 的問題,var callback 才需在 global scope 才可以成功地傳回值,不然 driver.execute_async_script() 的 javascript script 不論怎麼執行都會等到 timeout 也沒資料回傳。
範例3號,常見 OCR 的:
driver.set_script_timeout(1)
form_verifyCode_base64 = driver.execute_async_script("""
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var img = document.getElementById('%s');
if(img!=null) {
canvas.height = img.naturalHeight;
canvas.width = img.naturalWidth;
context.drawImage(img, 0, 0);
callback = arguments[arguments.length - 1];
callback(canvas.toDataURL()); }
""" % (image_id))
if not form_verifyCode_base64 is None:
img_base64 = base64.b64decode(form_verifyCode_base64.split(',')[1])