# -*- coding: utf-8 -*-
"""百家号 UE setContent（JS外置版）"""
import sys, socket, json, time, os
sys.stdout.reconfigure(encoding='utf-8')

HOST = "localhost"; PORT = 28800
PAGE_ID = "70039F329097C14448996F189E3A42A1"

TITLE = '水稻"长寿基因"刷屏背后：农业科技崛起，这类专业成升学就业新风口'

BODY_HTML = (
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">近日，中国科学家克隆水稻多年生关键基因EBT1的成果登上国际权威期刊《科学》封面，让"收水稻像采果子"的愿景成为可能，这一农业科技突破不仅刷屏全网，更让农学、生物科学等相关专业再次进入大众视野。</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">图源：中国科学院分子植物科学卓越创新中心</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">科研突破背后：农业科技成国家战略刚需</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">此次中科院韩斌院士、王佳伟研究员团队历时8年找到水稻"长寿基因"EBT1，首次阐明水稻从多年生到一年生驯化的分子机制，让多年生水稻的培育进程大幅提速。网友纷纷评论："原来种地也能这么高科技""中国农业科研太牛了"，而在点赞背后，更值得关注的是国家对农业科技的持续加码——从种业振兴到粮食安全，从生物育种产业化到智慧农业发展，农业科技早已不是"面朝黄土背朝天"的传统印象，而是融合了基因工程、分子生物学、大数据的高精尖领域。</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">云南大学胡凤益团队的多年生水稻PR23曾入选《科学》年度十大科学突破，此次EBT1基因的发现又实现新突破，印证了一个事实：农业科技领域的人才缺口正在持续扩大，为中考、高考、考研的学业规划，以及考公、国央企就业提供了明确的赛道方向。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">分阶段学业规划：踩准农业科技的升学节奏</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">农业科技的发展，对不同学习阶段的学生提出了差异化的能力要求，从选科到选专业，从深造到就业，每一步都有明确的规划重点。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">中考阶段：选科筑牢基础，培养学科兴趣</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">初中阶段需重点夯实生物、化学、数学三大基础学科，同时可通过农业科普纪录片、校园种植实验、农业科研院所开放日等方式，培养对农业科技的兴趣。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">高考阶段：选专业瞄准三大方向，抓住风口赛道</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">生物科学类、农学类、生物育种科学三大专业方向成为风口，且均为国家战略紧缺专业。</p>'
    '<p style="margin:12px 0 12px 24px">• <b>生物科学类</b>：聚焦基因、分子生物学等基础研究，是克隆EBT1这类基因的核心专业；</p>'
    '<p style="margin:12px 0 12px 24px">• <b>农学类</b>：涵盖作物学、园艺学等，直接对接水稻育种、农作物改良等应用领域；</p>'
    '<p style="margin:12px 0 12px 24px">• <b>生物育种科学</b>：国家种业振兴核心专业，2026年科研院所校招年薪22万起，中农发等央企扩招35%。</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">报考小贴士：中国农业大学、南京农业大学、华中农业大学等农科强校，以及中科院下属院校，拥有顶尖的农业科研平台；生物科学类专业属于"高学历依赖型"，建议提前做好读研读博规划。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">考研阶段：聚焦细分领域，贴合行业需求</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">作物遗传育种、分子植物学、农业生物技术、生物信息学是四大热门方向。想走科研路线可选作物遗传育种、分子植物学，博士毕业年薪可达20-40万元；想走应用路线可选农业生物技术、生物信息学。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">就业方向：考公、国央企成主流，赛道稳、竞争小</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">农业科技相关专业的就业，彻底打破了"冷门、低薪"的偏见，尤其是考公、进国央企成为主流选择，赛道稳定、竞争比三不限岗位低一半。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">方向一：体制内考公/事业单位，专业对口岗多</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">农业农村局、乡村振兴局、海关（动植物检疫）、农技推广中心等单位，每年都会发布大量对口岗位。专业对口、竞争小，硕士上岸可直接定级。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">方向二：国央企/涉农国企，福利拉满不内卷</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">中粮、中农发、中储粮、各省农投、种业国企等国央企是首选。一位农学硕士分享：9点到岗、17:30下班，周末双休，六险二金，不用996，生活与工作平衡度高。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">方向三：科研院所/头部农企，高薪适配科研型人才</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">中国农科院、各省农科院等科研院所，以及隆平高科、新希望等头部农企，对农业科技高端人才需求旺盛。随着EBT1基因研究向禾本科植物拓展，玉米、小麦等农作物的多年生改良也将成为新方向。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">写在最后：选择农业科技，就是选择国家未来</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">从水稻"长寿基因"的发现，到多年生水稻的培育，中国农业科技的一步突破，都离不开一代代科研工作者的深耕。如今的农业科技，早已是融合了基因工程、大数据、人工智能的高精尖领域，是国家战略刚需，更是升学就业的"潜力赛道"。</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">对于中考、高考的学生来说，选择农业科技相关专业，是抓住国家政策红利的明智之举；对于考研、考公的考生来说，农业科技赛道竞争小、稳定性高，是实现职业价值的优质选择。</p>'
    '<p style="font-weight:bold;font-size:20px;margin:24px 0 12px;line-height:1.6">延伸阅读</p>'
    '<p style="margin:12px 0 8px 24px">1. 《科学》封面文章：《A small regulatory RNA controls vegetative growth in rice》</p>'
    '<p style="margin:8px 0 8px 24px">2. 新华网：《中国科学家首次发现水稻多年生"长寿基因" 有望实现一次栽培年年收获》</p>'
    '<p style="margin:8px 0 8px 24px">3. 2026年国家公务员考试职位表：农业农村系统招录公告</p>'
    '<p style="margin:14px 0;text-indent:2em;line-height:1.8">本文参考资料：澎湃新闻、新华网、2026年河南公务员考试职位表</p>'
)

print("[INFO] 正文长度:", len(BODY_HTML))

# 把HTML通过CDP注入到页面，再调用setContent
body_json_str = json.dumps(BODY_HTML)

def ws():
    import urllib.parse
    u = "ws://%s:%s/devtools/page/%s" % (HOST, PORT, PAGE_ID)
    p = urllib.parse.urlparse(u)
    s = socket.create_connection((p.hostname, p.port or 80), timeout=15)
    req = ("GET %s HTTP/1.1\r\nHost: %s:%s\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n" % (p.path, p.hostname, p.port))
    s.send(req.encode())
    resp = b''
    while b'\r\n\r\n' not in resp: resp += s.recv(4096)
    return s

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

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

_mid = 0
def cdp(s, js, timeout=20):
    global _mid
    _mid += 1
    send(s, json.dumps({'id':_mid,'method':'Runtime.evaluate','params':{'expression':js,'returnByValue':True}}))
    s.settimeout(timeout)
    for _ in range(300):
        try:
            r = json.loads(recv(s))
            if r.get('id') == _mid:
                return r.get('result',{}).get('result',{}).get('value','')
        except: pass
    return ''

def key(s, k, txt=''):
    global _mid
    for t in ['keyDown','keyUp']:
        _mid += 1
        p = {'type':t,'key':k}
        if txt: p['text'] = txt
        send(s, json.dumps({'id':_mid,'method':'Input.dispatchKeyEvent','params':p}))
        recv(s)
    time.sleep(0.04)

def mouse_click(s, x, y):
    global _mid
    for t in ['mousePressed','mouseReleased']:
        _mid += 1
        send(s, json.dumps({'id':_mid,'method':'Input.dispatchMouseEvent','params':{'type':t,'x':x,'y':y,'button':'left','clickCount':1}}))
        recv(s)
        time.sleep(0.05)

s = ws()
print("[OK] Connected\n")

# Step 1: 注入 HTML 到页面变量
print("[Step 1] 注入正文 HTML...")
cdp(s, "window.__BODY__ = " + body_json_str)
r = cdp(s, "window.__BODY__ ? 'len='+window.__BODY__.length : 'null'")
print("  HTML 注入:", r[:60] if r else 'empty')

# Step 2: 调用 UE setContent
print("\n[Step 2] UE setContent...")
js_code = (
    "var html = window.__BODY__ || '';"
    "var ins = window.UE_V2 && window.UE_V2.instants;"
    "var result = 'no_instants';"
    "if (ins) {"
    "  var keys = Object.keys(ins);"
    "  for (var i = 0; i < keys.length; i++) {"
    "    var inst = ins[keys[i]];"
    "    if (inst && inst.key === 'ueditor') {"
    "      try {"
    "        inst.setContent(html);"
    "        result = 'ok:' + inst.getContent().length;"
    "      } catch(e) { result = 'err:' + e.message; }"
    "      break;"
    "    }"
    "  }"
    "  if (result === 'no_instants' || result.indexOf('no_ueditor') > -1) { result = 'no_ueditor:keys=' + keys.join(','); }"
    "}"
    "result"
)
r = cdp(s, js_code, timeout=30)
print("  UE填充:", r[:120] if r else 'empty')
time.sleep(1)

# Step 3: 填标题
print("\n[Step 3] 填标题...")
r = cdp(s, "var ps=document.querySelectorAll('p');var out=[];for(var p of ps){var t=(p.innerText||'').trim();if(t.length>0&&t.length<300&&!t.includes('插入')&&!t.includes('AI助手')&&!t.includes('热点')&&!t.includes('灵感')){var rect=p.getBoundingClientRect();out.push({x:Math.round(rect.left+rect.width/2),y:Math.round(rect.top+rect.height/2)})}}JSON.stringify(out)")
print("  位置:", r[:80] if r else 'empty')
if r and 'x' in r:
    info = json.loads(r)
    if info:
        x, y = info[0]['x'], info[0]['y']
        mouse_click(s, x, y)
        time.sleep(0.4)
        key(s, 'Control', 'a')
        time.sleep(0.15)
        key(s, 'Delete')
        time.sleep(0.2)
        print("  输入:", TITLE[:20], "...")
        for ch in TITLE:
            key(s, ch, ch)
        time.sleep(0.3)
        r2 = cdp(s, "var ps=document.querySelectorAll('p');var f='';for(var p of ps){var t=(p.innerText||'').trim();if(t.indexOf('长寿基因')>-1)f=t.substring(0,40)}f")
        print("  标题:", r2)

# Step 4: 存草稿
print("\n[Step 4] 存草稿...")
r = cdp(s, "var els=document.querySelectorAll('*');var out=[];for(var el of els){var t=(el.innerText||'').trim();if(t==='存草稿'){var rect=el.getBoundingClientRect();if(rect.width>0)out.push({x:Math.round(rect.left+rect.width/2),y:Math.round(rect.top+rect.height/2)})}}JSON.stringify(out)")
print("  按钮:", r[:80] if r else 'not found')
if r and 'x' in r:
    info = json.loads(r)
    if info:
        x, y = info[0]['x'], info[0]['y']
        print("  点击 (%d, %d)..." % (x, y))
        mouse_click(s, x, y)
        time.sleep(2)
        r2 = cdp(s, "var els=document.querySelectorAll('*');var f='';for(var el of els){var t=(el.innerText||'').trim();if(t.includes('已保存'))f=t}if(!f){var els2=document.querySelectorAll('*');for(var el of els2){var t2=(el.innerText||'').trim();if(t2.match(/字数/)&&t2.match(/\\d+/))f=t2}}f")
        print("  状态:", r2[:80] if r2 else 'empty')

print("\n✅ 完成，请在浏览器中确认后点击'发布'")
s.close()
