perf: localhost→127.0.0.1 fix IPv6 2s delay; simphtml radio/checkbox/svg/dropdown fixes; poll interval 0.5→0.2s

This commit is contained in:
Liang Jiaqing
2026-03-13 20:13:19 +08:00
parent 081aa12657
commit 908c1a52ed
4 changed files with 19 additions and 9 deletions

View File

@@ -34,7 +34,7 @@ class Session:
class TMWebDriver: class TMWebDriver:
def __init__(self, host: str = 'localhost', port: int = 18765): def __init__(self, host: str = '127.0.0.1', port: int = 18765):
self.host, self.port = host, port self.host, self.port = host, port
self.sessions, self.results, self.acks = {}, {}, {} self.sessions, self.results, self.acks = {}, {}, {}
self.default_session_id = None self.default_session_id = None
@@ -202,7 +202,7 @@ class TMWebDriver:
hasjump = acked = False hasjump = acked = False
while exec_id not in self.results: while exec_id not in self.results:
time.sleep(0.5) time.sleep(0.2)
if not acked and exec_id in self.acks: if not acked and exec_id in self.acks:
acked = True; start_time = time.time() acked = True; start_time = time.time()
if tp == 'ws': if tp == 'ws':
@@ -266,4 +266,4 @@ class TMWebDriver:
return self.execute_js(f'GM_openInTab("{url}");') return self.execute_js(f'GM_openInTab("{url}");')
if __name__ == "__main__": if __name__ == "__main__":
driver = TMWebDriver(host='localhost', port=18765) driver = TMWebDriver(host='127.0.0.1', port=18765)

View File

@@ -11,7 +11,7 @@
// @grant GM_xmlhttpRequest // @grant GM_xmlhttpRequest
// @grant GM_openInTab // @grant GM_openInTab
// @grant unsafeWindow // @grant unsafeWindow
// @connect localhost // @connect 127.0.0.1
// @run-at document-start // @run-at document-start
// ==/UserScript== // ==/UserScript==
@@ -26,13 +26,13 @@
return; return;
} }
const wsUrl = 'ws://localhost:18765'; const wsUrl = 'ws://127.0.0.1:18765';
const httpUrl = 'http://localhost:18766/'; const httpUrl = 'http://127.0.0.1:18766/';
function isWebSocketServerAlive(callback) { function isWebSocketServerAlive(callback) {
GM_xmlhttpRequest({ GM_xmlhttpRequest({
method: 'GET', method: 'GET',
url: 'http://localhost:18765/', url: 'http://127.0.0.1:18765/',
onload: () => callback(true), onload: () => callback(true),
onerror: () => callback(false) onerror: () => callback(false)
}); });

View File

@@ -104,4 +104,7 @@ web_scan失败时按序排查
①TM没装→遍历本机所有Chromium浏览器(Chrome/Edge/Brave…)用户数据目录下Extensions/各子目录manifest.json搜"tampermonkey" ①TM没装→遍历本机所有Chromium浏览器(Chrome/Edge/Brave…)用户数据目录下Extensions/各子目录manifest.json搜"tampermonkey"
没找到→走web_setup_sop找到→记住装在哪个浏览器 没找到→走web_setup_sop找到→记住装在哪个浏览器
②浏览器没开?→检查①对应的浏览器进程是否在跑(tasklist/ps)没有则启动并打开正常URL⚠about:blank等内部页不加载扩展 ②浏览器没开?→检查①对应的浏览器进程是否在跑(tasklist/ps)没有则启动并打开正常URL⚠about:blank等内部页不加载扩展
③WS后台挂了→socket.connect_ex(('localhost',18766))非0即dead→手动`from TMWebDriver import TMWebDriver; TMWebDriver()`起master ③WS后台挂了→socket.connect_ex(('127.0.0.1',18766))非0即dead→手动`from TMWebDriver import TMWebDriver; TMWebDriver()`起master
## 性能
- ⚠ URL必须用`127.0.0.1`不用`localhost`。Windows下localhost先尝试IPv6(::1)超时2s再回退IPv4每次HTTP请求多2s

View File

@@ -17,12 +17,14 @@ function createEnhancedDOMCopy() {
if (sourceNode.nodeType === 3) return sourceNode.cloneNode(false); if (sourceNode.nodeType === 3) return sourceNode.cloneNode(false);
const clone = sourceNode.cloneNode(false); const clone = sourceNode.cloneNode(false);
if ((sourceNode.tagName === 'INPUT' || sourceNode.tagName === 'TEXTAREA') && sourceNode.value) clone.setAttribute('value', sourceNode.value); if ((sourceNode.tagName === 'INPUT' || sourceNode.tagName === 'TEXTAREA') && sourceNode.value) clone.setAttribute('value', sourceNode.value);
if (sourceNode.tagName === 'INPUT' && (sourceNode.type === 'radio' || sourceNode.type === 'checkbox') && sourceNode.checked) clone.setAttribute('checked', '');
else if (sourceNode.tagName === 'SELECT' && sourceNode.value) clone.setAttribute('data-selected', sourceNode.value); else if (sourceNode.tagName === 'SELECT' && sourceNode.value) clone.setAttribute('data-selected', sourceNode.value);
try { if (sourceNode.matches && sourceNode.matches(':-webkit-autofill')) { clone.setAttribute('data-autofilled', 'true'); if (!sourceNode.value) clone.setAttribute('value', '⚠️受保护-读tmwebdriver_sop的autofill章节提取'); } } catch(e) {} try { if (sourceNode.matches && sourceNode.matches(':-webkit-autofill')) { clone.setAttribute('data-autofilled', 'true'); if (!sourceNode.value) clone.setAttribute('value', '⚠️受保护-读tmwebdriver_sop的autofill章节提取'); } } catch(e) {}
const isDropdown = sourceNode.classList?.contains('dropdown-menu') || const isDropdown = sourceNode.classList?.contains('dropdown-menu') ||
/dropdown|menu/i.test(sourceNode.className) || sourceNode.getAttribute('role') === 'menu'; /dropdown|menu/i.test(sourceNode.className) || sourceNode.getAttribute('role') === 'menu';
const isSmallDropdown = isDropdown && (sourceNode.querySelectorAll('a, button, [role="menuitem"], li').length <= 7 && sourceNode.textContent.length < 500); const _ddItems = isDropdown ? sourceNode.querySelectorAll('a, button, [role="menuitem"], li').length : 0;
const isSmallDropdown = _ddItems > 0 && _ddItems <= 7 && sourceNode.textContent.length < 500;
const childNodes = []; const childNodes = [];
for (const child of sourceNode.childNodes) { for (const child of sourceNode.childNodes) {
@@ -704,6 +706,7 @@ js_findMainContent = '''
def optimize_html_for_tokens(html): def optimize_html_for_tokens(html):
if type(html) is str: soup = BeautifulSoup(html, 'html.parser') if type(html) is str: soup = BeautifulSoup(html, 'html.parser')
else: soup = html else: soup = html
for svg in soup.find_all('svg'): svg.clear()
[tag.attrs.pop('style', None) for tag in soup.find_all(True)] [tag.attrs.pop('style', None) for tag in soup.find_all(True)]
for tag in soup.find_all(True): for tag in soup.find_all(True):
if tag.has_attr('src'): if tag.has_attr('src'):
@@ -788,6 +791,10 @@ def find_changed_elements(before_html, after_html):
for sig, els in after_sigs.items(): for sig, els in after_sigs.items():
if sig not in before_sigs: changed.extend(els) if sig not in before_sigs: changed.extend(els)
elif len(els) > len(before_sigs[sig]): changed.extend(els[:len(els) - len(before_sigs[sig])]) elif len(els) > len(before_sigs[sig]): changed.extend(els[:len(els) - len(before_sigs[sig])])
if len(changed) == 0 and str(before_soup) != str(after_soup):
before_els, after_els = before_soup.find_all(True), after_soup.find_all(True)
for i in range(min(len(before_els), len(after_els))):
if get_sig(before_els[i]) != get_sig(after_els[i]): changed.append(after_els[i])
# 变化边界: parent不在changed中的元素 # 变化边界: parent不在changed中的元素
cids = set(id(el) for el in changed) cids = set(id(el) for el in changed)
boundaries = [el for el in changed if el.parent is None or id(el.parent) not in cids] boundaries = [el for el in changed if el.parent is None or id(el.parent) not in cids]