# -*- coding: utf-8 -*-
"""百家号填文章（修复正文 UE API）"""
import sys, socket, json, time, base64, os, glob, random
from base64 import b64encode
sys.stdout.reconfigure(encoding='utf-8')

HOST = "localhost"; PORT = 28800
PAGE_ID = "05A421A861953C0FFB3712503B85EE82"

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

def get_latest_image():
    d = r'D:\wxpic'
    exts = ['*.jpg','*.jpeg','*.png','*.gif','*.bmp','*.webp']
    imgs = []
    for e in exts: imgs.extend(glob.glob(os.path.join(d, e)))
    return max(imgs, key=os.path.getmtime) if imgs else None

IMG = get_latest_image()
print("[INFO] 图片:", IMG)

def fmt_p(style, text):
    if style == 'normal': return '<p style="margin:16px 0">　　' + text + '</p>'
    elif style == 'heading': return '<p style="font-weight:bold;font-size:18px;margin:20px 0 10px">' + text + '</p>'
    return ''

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(200):
        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.06)

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

# Step 1: 填标题
print("\n[Step 1] 填标题...")
# 点击标题区域
for t in ['mousePressed','mouseReleased']:
    _mid += 1; send(s, json.dumps({'id':_mid,'method':'Input.dispatchMouseEvent','params':{'type':t,'x':753,'y':207,'button':'left','clickCount':1}})); recv(s); time.sleep(0.05)
time.sleep(0.5)
# Ctrl+A 再输入新标题
key(s, 'Control', 'a'); time.sleep(0.2)
key(s, 'Delete'); time.sleep(0.2)
print("  输入:", TITLE[:20], "...")
for ch in TITLE: key(s, ch, ch)
time.sleep(0.5)
r = 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("  标题:", r)

# Step 2: 通过 UE API 清空并插入正文（不用 innerHTML）
print("\n[Step 2] 清空+填正文...")
# 组合所有正文为单个 HTML 字符串
all_body = ''
for style, text in PARAGRAPHS:
    html = fmt_p(style, text)
    if html.strip(): all_body += html

# 转义单引号
safe_body = all_body.replace("'", "\\'")

# 用 UE API 清空并填入新内容
r = cdp(s, (
    "var ifr=document.querySelectorAll('iframe');"
    "var result='';"
    "for(var i of ifr){"
    " try{"
    "  var w=i.contentWindow||i.contentDocument.defaultView;"
    "  if(w.UE_V2&&w.UE_V2.instants){"
    "   var ks=Object.keys(w.UE_V2.instants);"
    "   for(var k of ks){"
    "    var inst=w.UE_V2.instants[k];"
    "    if(inst&&inst.key&&inst.key.indexOf('content')>-1){"
    "     try{"
    "      inst.setContent('" + safe_body + "');"
    "      result='ok:'+inst.getContent().substring(0,50);"
    "     }catch(e){result='err:'+e.message}"
    "    }"
    "   }"
    "  }"
    " }catch(e){result='iframe_err:'+e.message}"
    "}"
    "result||'not_found'"
), timeout=30)
print("  UE 填充:", r[:100] if r else 'empty')

time.sleep(2, 3)

# Step 3: 状态验证
r = cdp(s, "var out=[];var els=document.querySelectorAll('*');for(var el of els){var t=(el.innerText||'').trim();if(t.match(/字数/)&&t.match(/\\d+/))out.push(t)}out.join(' | ')")
print("\n[字数统计]", r[:200] if r else 'empty')

# 检查正文是否真的进去了
r2 = cdp(s, (
    "var ifr=document.querySelectorAll('iframe');"
    "var content='';"
    "for(var i of ifr){try{var w=i.contentWindow||i.contentDocument.defaultView;"
    "if(w.UE_V2&&w.UE_V2.instants){"
    "var ks=Object.keys(w.UE_V2.instants);"
    "for(var k of ks){var inst=w.UE_V2.instants[k];"
    "if(inst&&inst.key&&inst.key.indexOf('content')>-1){"
    "content=inst.getContent().substring(0,100)}}}catch(e){}}"
    "}"
    "content||'empty'"
), timeout=15)
print("[正文片段]", r2[:100] if r2 else 'empty')

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