win11系统下使用iedriver开发带有activex控件的网站的自动化脚本

win11系统下使用iedriver开发带有activex控件的网站的自动化脚本

前情提要

本文技术要点:win11、ie、iedriver、python、selenium4.14.0、activex控件

前情提要部分没啥用,大家需要了解编写脚本的技巧的自行在本页ctrl+F搜索你想知道的相关关键词

最近有个小项目的工作流上,需要用到一个自动化脚本来填写表单,大体是这样:

用户在A系统上下单之后,要讲数据录入到系统B中,系统A和系统B属于不同公司,且数据不互通,并且将数据录入的过程中,还需要各种拍照、使用NFC或者高拍仪等工具读取身份证件等过程。

在接受这个项目的过程中,我遇到了以下几个比较棘手的点:

  1. B系统的录入系统是基于ie开发的,并且用到了activex控件,所以必须使用ie内核的浏览器
  2. 表单录入的过程中,需要从系统A中查询用户的信息,信息多且数据长度较长,比较容易出错
  3. 表单录入的过程中,需要从一个有40多页、每页5格,且数据随机分散在这40页的表格中找到一个数据,数据可以与实际不符,也就是可以乱选,但不允许大量的用户选择到重复数据,人工填写很难保证随机性
  4. ie浏览器设置cookie的问题:driver.add_cookie()函数可能会不起作用,我换了各种版本的driver和selenium版本,甚至使用了win7系统都无法正常将cookie添加进去
  5. 验证码接入问题:这个其实不属于本文章范畴之内,我们使用了开源的短信转发系统,将验证码推送到飞书机器人或者自建的接口,用于接收验证码
  6. send_keys()的效率问题,在ie中,send_keys()可能会很慢很慢,使用pyperclip可能依然很慢,如果你遇到了和我一样的情况,建议使用edge,调试的效率不知提升一点点

win11/win10下使用iedriver驱动Edge的ie内核模式

使用下面这段代码,我们可以得到一个使用iedriver驱动的Edge的ie内核模式的浏览器

1
2
3
4
5
6
ie_options = webdriver.IeOptions()
ie_options.attach_to_edge_chrome = True
ie_options.ignore_protected_mode_settings=True
ie_options.edge_executable_path = "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"

driver = webdriver.Ie(options=ie_options)

ie_options.attach_to_edge_chromeie_options.edge_executable_path这两句话是用来保证我们能够一直使用edge来操控ie的,不然的话在脚本运行的期间,可能某些页面会跳转到ie11的界面,导致一些网页没法正常显示

activex控件启用不成功问题

你可能需要进入interne选项的安全面板,选择一个区域,然后点击自定义级别,将所有的activex控件相关的项目变更为“启用”状态

python3使用sqlalchemy的依赖问题以及密码中含有@等特殊字符的问题

这里我实现了一个自定义类,用来暴露给main.py文件调用,方便调试代码与协同开发、降低耦合度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from urllib.parse import quote_plus as urlquote

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

class Query:
def __init__(self, host, user, password, database):
'''初始化数据库连接
host: 数据库地址
user: 数据库用户名
password: 数据库密码
database: 数据库名
'''
self.engine = create_engine(f'mysql://{user}:{urlquote(password)}@{host}/{database}?charset=utf8mb4')
self.Base = declarative_base()
self.Base.metadata.create_all(self.engine)
self.Session = sessionmaker(bind=self.engine)
self.session = self.Session()
def __del__(self):
self.session.close()
def __getSession(self):
return self.session
def getOrdersByPhone(self, phone: str):
"""通过手机号查询订单"""
return self.session.query(Order).filter(
Order.phone == phone,
Order.status == 1
).all()
def getOrdersByStudentId(self, studentId: str):
"""通过学号查询订单"""
return self.session.query(Order).filter(
Order.student_id == studentId,
Order.status == 1
).all()
def getOrdersByIdCard(self, idCard: str):
"""通过身份证号查询订单"""
return self.session.query(Order).filter(
Order.id_card == idCard,
Order.status == 1
).all()

首先声明一下,这里使用sqlalchemy是因为作者太菜不会写sql语句。

依赖问题

这里我遇到了几个问题,在python3,如果出现no moudle named mysqldb之类的报错,需要pip install mysql-client这个库

特殊字符问题

需要将

1
create_engine('mysql://{user}:{password}@{host}/{database}?charset=utf8mb4')

替换为

1
create_engine(f'mysql://{user}:{urlquote(password)}@{host}/{database}?charset=utf8mb4')

当然你需要在这之前

1
from urllib.parse import quote_plus as urlquote

在ie中driver.add_cookie()很有可能没法正确设置cookie,如果你也遇到这样的问题,不妨尝试使用driver.execute_script()以下是一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from selenium import webdriver

# 启动IE浏览器
driver = webdriver.Ie()

# 打开网页
# driver.get("https://example.com")


# 定义要设置的cookie
cookie = {
'name': 'SESSION_ID',
'value': 'content',
'path': '/your/path', # 这个path是用来指定该cookie值适用的路径
'domain': 'example.com'
}

# 将cookie添加到页面中
driver.execute_script("document.cookie = '{}={}; path={}; domain={}'".format(
cookie['name'], cookie['value'], cookie['path'], cookie['domain']))

# 刷新页面,让cookie生效
driver.refresh()

print(driver.get_cookies())

input('Press ENTER to close the automated browser')
# 关闭浏览器
driver.quit()


win11系统下使用iedriver开发带有activex控件的网站的自动化脚本
https://www.lry666.cn/posts/27ea/
作者
LRY666
发布于
2024年3月12日
许可协议