# -*- coding: utf-8 -*-
import socket, json, urllib.request, urllib.parse

HOST = 'localhost'
PORT = 9223

# 获取页面
pages = json.loads(urllib.request.urlopen(f'http://{HOST}:{PORT}/json').read())
page_id = [p['id'] for p in pages if 'baijiahao.baidu.com' in p['url']][0]

# 连接
ws_url = f'ws://{HOST}:{PORT}/devtools/page/{page_id}'
parsed = urllib.parse.urlparse(ws_url)
sock = socket.create_connection((parsed.hostname, parsed.port or 80), timeout=15)
key = 'dGhlIHNhbXBsZSBub25jZQ=='
handshake = f'GET {parsed.path} HTTP/1.1\r\nHost:{parsed.hostname}:{parsed.port}\r\nUpgrade:websocket\r\nConnection:Upgrade\r\nSec-WebSocket-Key:{key}\r\nSec-WebSocket-Version:13\r\n\r\n'
sock.send(handshake.encode())
resp = b''
while b'\r\n\r\n' not in resp:
    resp += sock.recv(4096)

def send(s, d):
    data = json.dumps(d).encode('utf-8')
    n = len(data)
    mask = b'\x01\x02\x03\x04'
    if n <= 125:
        hdr = bytes([0x81, n|0x80]) + mask
    elif n <= 65535:
        hdr = bytes([0x81, 0xFE]) + n.to_bytes(2, 'big') + mask
    s.send(hdr + bytes(data[i] ^ mask[i%4] for i in range(n)))

def recv(s):
    h = s.recv(2)
    n = h[1] & 0x7f
    if n == 126:
        n = int.from_bytes(s.recv(2), 'big')
    elif n == 127:
        n = int.from_bytes(s.recv(8), 'big')
    return s.recv(n).decode('utf-8')

# 查找标题区域 - 找包含"标题"或"请输入标题"的元素
expr = """
(function(){
    var results = [];
    var all = document.querySelectorAll('*');
    for(var el of all){
        var text = el.innerText || '';
        var placeholder = el.getAttribute('placeholder') || '';
        if((text.includes('标题') && text.length < 50) || 
           (placeholder.includes('标题')) ||
           (el.className && el.className.toString().includes('title'))){
            results.push({
                tag: el.tagName,
                class: el.className ? el.className.toString().substring(0,60) : '',
                id: el.id,
                placeholder: placeholder,
                innerText: text.substring(0,40),
                contenteditable: el.contentEditable
            });
        }
    }
    return JSON.stringify(results.slice(0, 15));
})()
"""
send(sock, {'id':1,'method':'Runtime.evaluate','params':{'expression':expr}})
r = recv(sock)
print('可能的标题元素:')
print(json.loads(r)['result']['result']['value'])

# 查找所有 textarea（百家号可能用 textarea 做标题）
expr2 = """
(function(){
    var results = [];
    var textareas = document.querySelectorAll('textarea');
    for(var ta of textareas){
        results.push({
            class: ta.className ? ta.className.toString().substring(0,60) : '',
            placeholder: ta.placeholder || '',
            value: ta.value ? ta.value.substring(0,30) : '',
            rows: ta.rows,
            cols: ta.cols
        });
    }
    return JSON.stringify(results);
})()
"""
send(sock, {'id':2,'method':'Runtime.evaluate','params':{'expression':expr2}})
r2 = recv(sock)
print('\n所有 textarea:')
print(json.loads(r2)['result']['result']['value'])

# 查找页面最上方的可编辑元素
expr3 = """
(function(){
    var results = [];
    var editable = document.querySelectorAll('[contenteditable="true"]');
    for(var i=0; i<editable.length && i<5; i++){
        var el = editable[i];
        var rect = el.getBoundingClientRect();
        results.push({
            index: i,
            tag: el.tagName,
            class: el.className ? el.className.toString().substring(0,40) : '',
            top: rect.top,
            left: rect.left,
            innerText: el.innerText ? el.innerText.substring(0,30) : ''
        });
    }
    return JSON.stringify(results);
})()
"""
send(sock, {'id':3,'method':'Runtime.evaluate','params':{'expression':expr3}})
r3 = recv(sock)
print('\n所有 contenteditable 元素（按位置）:')
print(json.loads(r3)['result']['result']['value'])

sock.close()
