Jun.

記事は繁体字中国語で書かれています。

AI BLOG
2026-09-18AI 日誌

把测试中的交易结果摆进玻璃柜,也把读不懂新网页的爬虫治好

把测试中的交易结果摆进玻璃柜,也把读不懂新网页的爬虫治好 封面
封面由跨專案自動彙整流程生成。

這幾天做了兩件不太相關的事:一件是讓一直在背景抓購物網站資訊的機器人,認得出它之前看不懂的幾種網頁長相;另一件是把私下測試中的自動交易結果,做成一個公開頁面放到個人網站上,方便給人看作品。順手也在聯絡頁加了一個讓訪客直接約時間的按鈕。

爬蟲沒看過的版面,會安靜地抓不到東西

有一個專案是代購轉貼機器人,負責每天去日本幾個購物網站抓最新商品資訊,方便轉貼到社群平台。這幾天發現它在幾個網站上開了天窗——有的分類頁跟搜尋結果頁抓不到商品,有的商品尺寸規格讀不出來。

問題出在這些網站的頁面長相跟原本設定的不一樣。有的網站分類頁換了新的網址寫法,但舊網址其實還留著;搜尋結果頁要看頁面標題裡的關鍵字才認得出哪些是要的商品;商品尺寸資訊有些網站寫在沒有標籤的一般說明文字裡,寫法五花八門。這些情況都得一個一個補規則才認得出來。

如果請AI做一個每天要自動執行、去別人網站抓資料的工作,得先假設那個網站不會只有一種長相。規則寫死在一種版面上,遇到另一種版面時它不會主動喊救命,只會安靜地抓空。平常留一份維護清單,才看得出是哪個網站、哪種頁面壞掉了。

note技術細節:三個爬蟲補丁

toei-anim 補上分類頁 /shop/c/cXX/ 與舊網址 category.aspx 的解析規則(送 dtype=Category、dcode=XX)。 movic 補上搜尋結果頁 /shop/goods/search.aspx,抓 關鍵字比對、p=N 翻頁,上限 30 頁。 animate 的 fetchDetail 補回傳 specs,extractSpecs 處理沒有標籤的尺寸寫法(如 H180mm×W90mm×D3mm、Φ56mm 等)。 對應維護看板編號 B-22、B-23。</p></div></details><h2>內部資料要公開,先做一份唯讀的複本</h2> <p>我私下有一個自動交易系統,用假錢做紙上交易實驗,用來驗證交易策略。為了讓個人作品集網站看起來更有說服力,這幾天把這個實驗的走勢圖、績效、持股結果做成一個公開頁面放上網站。</p> <p>公開頁面不會直接連到那個正在運作的交易系統。交易系統會定期做一份唯讀的複本資料,公開網站只讀這份複本來顯示畫面。這就像把展品放進博物館的玻璃櫃給遊客看,遊客看得到,但碰不到,也動不了櫃子裡的真品。另外還寫了一支檢查程式,專門抓公開頁面上有沒有不小心漏出內部才用的代號或字眼。</p> <pre class="mermaid">flowchart LR A[正在運作的交易系統] --> B[定期做一份唯讀複本] B --> C[公開網站只讀複本來顯示]</pre> <p>如果要把內部系統的資料公開給外人看,不要讓公開頁面直接連到正在運作的系統,中間隔一層唯讀的複本。這樣公開頁面出問題也不會影響到正在跑的系統,內部還在調整中的資料也不會不小心曝光。</p> <details class="callout"><summary><span class="callout-kind">note</span><span>技術細節:唯讀匯出與驗證腳本</span></summary><div class="callout-body"><p>020 的 run_export.py 與 qtrader/paper/public_export.py 以 mode=ro 開啟帳本,匯出 018 用的 content/data/paper-trading/snapshot.json,數字全部來自既有的 sleeve_perf、track_orders、order_stats 等函式。 018 新增 /data/paper-trading 三語頁面(SSG),含走勢圖、績效、持股、AI 提案、機率評分、風控等區塊。 scripts/verify-paper-trading.ts 檢查 schema、禁用詞、內部用語與組名字典是否一致,納入 npm run verify。</p></div></details><h2>留言板旁邊多開一條直接約時間的路</h2> <p>個人作品集網站的聯絡頁,本來只能留言等我回信。這幾天加了一個預約會議的按鈕,訪客可以直接選時間,不用來回等信,按下去開新分頁導去我自己用的預約連結,版面維持原本的樣子沒有大動。</p> <p>如果網站的目的是要讓別人聯繫你,留言等回信跟直接約時間這兩條路都留著比較好。有人喜歡先留言問清楚,有人只想直接訂個時間,兩種人都要接得住。</p> <h2>接下來</h2> <ul> <li>模擬交易儀表板目前還在本機測試,還沒真正對外上線。</li> <li>代購轉貼機器人這幾個網站的補丁是被動發現才修的,還要留意有沒有其他網站也因為改版而抓不到資料。</li> </ul> <hr> <p><small>本篇由跨專案自動彙整產生,素材為 2026-09-17 之後 3 個專案的提交紀錄與 0 則知識投遞。</small></p> </div><p class="mt-[34px]"><a class="inline-flex items-center gap-2 font-archivo text-xs font-semibold uppercase tracking-[0.14em] text-faint transition-colors hover:text-accent" href="/ja/blog"><span aria-hidden="true">←</span>AI BLOG に戻る</a></p></article></main><!--$--><!--/$--></div><!--$!--><template data-dgst="BAILOUT_TO_CLIENT_SIDE_RENDERING"></template><!--/$--><script src="/_next/static/immutable/chunks/36k8in9a291ok.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[39756,[\"/_next/static/immutable/chunks/2corl6wyj4669.js\"],\"default\"]\n3:I[37457,[\"/_next/static/immutable/chunks/2corl6wyj4669.js\"],\"default\"]\n4:I[87771,[\"/_next/static/immutable/chunks/4151u7kuqmfgu.js\"],\"default\"]\n12:I[68027,[],\"default\",1]\n:HL[\"/_next/static/immutable/chunks/2dzl5-zjgfkx2.css\",\"style\"]\n:HL[\"/_next/static/immutable/chunks/3v6ud-foik3iy.css\",\"style\"]\n:HL[\"/_next/static/immutable/chunks/194cbpe8w10vy.css\",\"style\"]\n:HL[\"/_next/static/immutable/chunks/2kigoiybn2yy1.css\",\"style\"]\n:HL[\"/_next/static/immutable/media/2a65768255d6b625-s.p.2r-cuu_7locvx.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/immutable/media/70e3db2de7f94926-s.p.43n2qzmbjskyp.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/immutable/media/75affa71d1e2f6a7-s.p.13rul5q9jl2r0.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/immutable/media/ad9c66e761fed85a-s.p.1qiholmd5_dkj.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/immutable/media/fb4edce8a3cbfef3-s.p.16g943u0dmysf.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n10:X\n0:{\"P\":null,\"c\":[\"\",\"ja\",\"blog\",\"ai-log-2026-09-18\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[[\"locale\",\"ja\",\"d\",[\"about\",\"api\",\"blog\",\"contact\",\"data\",\"llms.txt\",\"tools\",\"works\"]],{\"children\":[\"blog\",{\"children\":[[\"slug\",\"ai-log-2026-09-18\",\"d\",[]],{\"children\":[\"__PAGE__\",{},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4624],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/immutable/chunks/2dzl5-zjgfkx2.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"html\",null,{\"lang\":\"zh-Hant-TW\",\"className\":\"archivo_8cb556d3-module__Jr5Dbq__variable playfair_display_4cdddb53-module__RUst5q__variable noto_sans_tc_2a171203-module__E2bm4G__variable h-full antialiased\",\"children\":[\"$\",\"body\",null,{\"className\":\"min-h-full flex flex-col\",\"children\":[[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"{\\\"@context\\\":\\\"https://schema.org\\\",\\\"@graph\\\":[{\\\"@type\\\":\\\"Person\\\",\\\"@id\\\":\\\"https://junlin0083.com/#person\\\",\\\"name\\\":\\\"Jun Lin\\\",\\\"url\\\":\\\"https://junlin0083.com/\\\",\\\"image\\\":\\\"https://junlin0083.com/img/profile.jpg\\\",\\\"email\\\":\\\"mailto:jun.lin0083@gmail.com\\\",\\\"description\\\":\\\"軟體產業 | 專案管理 · 企劃 · 營運策略 · AI數位化轉型\\\",\\\"sameAs\\\":[\\\"https://medium.com/@abc12345678910\\\",\\\"https://www.linkedin.com/in/jun-lin-297520225/\\\",\\\"https://x.com/aburamatyatya\\\"],\\\"mainEntityOfPage\\\":{\\\"@id\\\":\\\"https://junlin0083.com/#website\\\"}},{\\\"@type\\\":\\\"WebSite\\\",\\\"@id\\\":\\\"https://junlin0083.com/#website\\\",\\\"url\\\":\\\"https://junlin0083.com/\\\",\\\"name\\\":\\\"Jun Lin\\\",\\\"inLanguage\\\":[\\\"zh-Hant-TW\\\",\\\"en\\\",\\\"ja\\\"],\\\"publisher\\\":{\\\"@id\\\":\\\"https://junlin0083.com/#person\\\"}}]}\"}}],[\"$\",\"$L4\",null,{\"locale\":\"zh-TW\",\"logo\":\"Jun.\",\"socials\":[{\"label\":\"Medium\",\"url\":\"https://medium.com/@abc12345678910\"},{\"label\":\"LinkedIn\",\"url\":\"https://www.linkedin.com/in/jun-lin-297520225/\"},{\"label\":\"X\",\"url\":\"https://x.com/aburamatyatya\"}],\"copyright\":\"Copyright ©2026 Jun Lin.\\nAll rights reserved.\",\"labels\":{\"openMenu\":\"開啟選單\",\"closeMenu\":\"關閉選單\"}}],[\"$\",\"div\",null,{\"className\":\"flex min-h-screen flex-col pt-16 lg:pl-[285px] lg:pt-0\",\"children\":[\"$\",\"main\",null,{\"className\":\"flex-1 px-6 py-12 sm:px-10 lg:px-[88px] lg:pb-[88px] lg:pt-[76px]\",\"children\":[[\"$\",\"p\",null,{\"className\":\"mb-4 font-playfair text-[19px] font-medium italic text-muted\",\"children\":\"404\"}],[\"$\",\"h1\",null,{\"className\":\"font-archivo text-[48px] font-black uppercase leading-[0.94] tracking-[-0.03em] sm:text-[64px] lg:text-[76px]\",\"children\":\"Not Found\"}],[\"$\",\"div\",null,{\"className\":\"mt-10 max-w-[560px] lg:mt-[52px]\",\"children\":[[\"$\",\"section\",\"zh-TW\",{\"lang\":\"zh-Hant-TW\",\"className\":\"border-t border-hairline py-[26px] \",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-[19px] font-medium\",\"children\":\"找不到這個頁面\"}],[\"$\",\"p\",null,{\"className\":\"mt-2 text-[15px] leading-[1.95] text-[#4a4a4a]\",\"children\":\"這個網址不存在,或內容已經移走了。\"}],[\"$\",\"a\",null,{\"href\":\"/\",\"hrefLang\":\"zh-Hant-TW\",\"className\":\"mt-4 inline-flex items-center gap-[10px] border-b border-text pb-[6px] transition-colors hover:border-accent hover:text-accent\",\"children\":[[\"$\",\"span\",null,{\"className\":\"text-[15px] font-medium\",\"children\":\"回到首頁\"}],[\"$\",\"span\",null,{\"aria-hidden\":true,\"children\":\"→\"}]]}]]}],[\"$\",\"section\",\"en\",{\"lang\":\"en\",\"className\":\"border-t border-hairline py-[26px] \",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-[19px] font-medium\",\"children\":\"Page not found\"}],[\"$\",\"p\",null,{\"className\":\"mt-2 text-[15px] leading-[1.95] text-[#4a4a4a]\",\"children\":\"This URL does not exist, or the content has been moved.\"}],[\"$\",\"a\",null,{\"href\":\"/en\",\"hrefLang\":\"en\",\"className\":\"mt-4 inline-flex items-center gap-[10px] border-b border-text pb-[6px] transition-colors hover:border-accent hover:text-accent\",\"children\":[[\"$\",\"span\",null,{\"className\":\"text-[15px] font-medium\",\"children\":\"Back to home\"}],[\"$\",\"span\",null,{\"aria-hidden\":true,\"children\":\"→\"}]]}]]}],[\"$\",\"section\",\"ja\",{\"lang\":\"ja\",\"className\":\"border-t border-hairline py-[26px] border-b border-hairline\",\"children\":[\"$L5\",\"$L6\",\"$L7\"]}]]}]]}]}],\"$L8\",\"$L9\"]}]}],[\"$La\",\"$Lb\"]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"$Lc\",{\"children\":[\"$Ld\",{\"children\":[\"$Le\",{\"children\":[\"$Lf\",{},null,false,null]},null,false,\"$10\"]},null,false,\"$10\"]},null,false,null]},null,false,null],\"$L11\",false]],\"m\":\"$undefined\",\"G\":[\"$12\",[\"$L13\"]],\"S\":true,\"h\":null,\"r\":\"$undefined\",\"s\":\"$undefined\",\"a\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"ZbbnE-vwuUoJwgFFaKc_V\"}\n14:I[2355,[\"/_next/static/immutable/chunks/4151u7kuqmfgu.js\"],\"Analytics\"]\n15:I[79520,[\"/_next/static/immutable/chunks/4151u7kuqmfgu.js\"],\"\"]\n18:I[97367,[\"/_next/static/immutable/chunks/2corl6wyj4669.js\"],\"OutletBoundary\"]\n19:\"$Sreact.suspense\"\n1b:I[97367,[\"/_next/static/immutable/chunks/2corl6wyj4669.js\"],\"ViewportBoundary\"]\n1d:I[97367,[\"/_next/static/immutable/chunks/2corl6wyj4669.js\"],\"MetadataBoundary\"]\n5:[\"$\",\"h2\",null,{\"className\":\"text-[19px] font-medium\",\"children\":\"ページが見つかりません\"}]\n6:[\"$\",\"p\",null,{\"className\":\"mt-2 text-[15px] leading-[1.95] text-[#4a4a4a]\",\"children\":\"この URL は存在しないか、コンテンツが移動しました。\"}]\n7:[\"$\",\"a\",null,{\"href\":\"/ja\",\"hrefLang\":\"ja\",\"className\":\"mt-4 inline-flex items-center gap-[10px] border-b border-text pb-[6px] transition-colors hover:border-accent hover:text-accent\",\"children\":[[\"$\",\"span\",null,{\"className\":\"text-[15px] font-medium\",\"children\":\"ホームに戻る\"}],[\"$\",\"span\",null,{\"aria-hidden\":true,\"children\":\"→\"}]]}]\n8:[\"$\",\"$L14\",null,{}]\n9:[[\"$\",\"$L15\",null,{\"src\":\"https://www.googletagmanager.com/gtag/js?id=G-CXWRTBV7ZD\",\"strategy\":\"afterInteractive\"}],[\"$\",\"$L15\",null,{\"id\":\"ga4-init\",\"strategy\":\"afterInteractive\",\"children\":\"window.dataLayer = window.dataLayer || [];\\nfunction gtag(){dataLayer.push(arguments);}\\ngtag('js', new Date());\\ngtag('config', 'G-CXWRTBV7ZD');\"}]]\na:[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/immutable/chunks/194cbpe8w10vy.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\nb:[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/immutable/chunks/2kigoiybn2yy1.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\nc:[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/immutable/chunks/3v6ud-foik3iy.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/immutable/chunks/194cbpe8w10vy.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"2\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/immutable/chunks/2kigoiybn2yy1.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/immutable/chunks/4151u7kuqmfgu.js\",\"async\":true,\"nonce\":\"$undefined\"}]],\"$L16\"]}]\nd:[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]\ne:[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]\nf:[\"$\",\"$1\",\"c\",{\"children\":[\"$L17\",[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/immutable/chunks/3zbglfeikyhj3.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L18\",null,{\"children\":[\"$\",\"$19\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@1a\"}]}]]}]\n11:[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L1b\",null,{\"children\":\"$L1c\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L1d\",null,{\"children\":[\"$\",\"$19\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L1e\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}]\n13:[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/immutable/chunks/2dzl5-zjgfkx2.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\n1f:I[22016,[\"/_next/static/immutable/chunks/4151u7kuqmfgu.js\",\"/_next/static/immutable/chunks/3zbglfeikyhj3.js\"],\"\"]\n20:I[5500,[\"/_next/static/immutable/chunks/4151u7kuqmfgu.js\",\"/_next/static/immutable/chunks/3zbglfeikyhj3.js\"],\"Image\"]\n10:C\n16:[\"$\",\"html\",null,{\"lang\":\"ja\",\"className\":\"archivo_8cb556d3-module__Jr5Dbq__variable playfair_display_4cdddb53-module__RUst5q__variable noto_sans_tc_2a171203-module__E2bm4G__variable noto_sans_jp_43a8d00c-module__snZIpq__variable h-full antialiased\",\"children\":[\"$\",\"body\",null,{\"className\":\"min-h-full flex flex-col\",\"children\":[[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"{\\\"@context\\\":\\\"https://schema.org\\\",\\\"@graph\\\":[{\\\"@type\\\":\\\"Person\\\",\\\"@id\\\":\\\"https://junlin0083.com/#person\\\",\\\"name\\\":\\\"Jun Lin\\\",\\\"url\\\":\\\"https://junlin0083.com/\\\",\\\"image\\\":\\\"https://junlin0083.com/img/profile.jpg\\\",\\\"email\\\":\\\"mailto:jun.lin0083@gmail.com\\\",\\\"description\\\":\\\"ソフトウェア業界 | プロジェクトマネジメント · 企画 · 運営戦略 · AI による DX\\\",\\\"sameAs\\\":[\\\"https://medium.com/@abc12345678910\\\",\\\"https://www.linkedin.com/in/jun-lin-297520225/\\\",\\\"https://x.com/aburamatyatya\\\"],\\\"mainEntityOfPage\\\":{\\\"@id\\\":\\\"https://junlin0083.com/#website\\\"}},{\\\"@type\\\":\\\"WebSite\\\",\\\"@id\\\":\\\"https://junlin0083.com/#website\\\",\\\"url\\\":\\\"https://junlin0083.com/\\\",\\\"name\\\":\\\"Jun Lin\\\",\\\"inLanguage\\\":[\\\"zh-Hant-TW\\\",\\\"en\\\",\\\"ja\\\"],\\\"publisher\\\":{\\\"@id\\\":\\\"https://junlin0083.com/#person\\\"}}]}\"}}],[\"$\",\"$L4\",null,{\"locale\":\"ja\",\"logo\":\"Jun.\",\"socials\":\"$0:f:0:1:0:props:children:1:props:notFound:0:props:children:props:children:1:props:socials\",\"copyright\":\"Copyright ©2026 Jun Lin.\\nAll rights reserved.\",\"labels\":{\"openMenu\":\"メニューを開く\",\"closeMenu\":\"メニューを閉じる\"}}],[\"$\",\"div\",null,{\"className\":\"flex min-h-screen flex-col pt-16 lg:pl-[285px] lg:pt-0\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}],[\"$\",\"$L14\",null,{}],[[\"$\",\"$L15\",null,{\"src\":\"https://www.googletagmanager.com/gtag/js?id=G-CXWRTBV7ZD\",\"strategy\":\"afterInteractive\"}],[\"$\",\"$L15\",null,{\"id\":\"ga4-init\",\"strategy\":\"afterInteractive\",\"children\":\"window.dataLayer = window.dataLayer || [];\\nfunction gtag(){dataLayer.push(arguments);}\\ngtag('js', new Date());\\ngtag('config', 'G-CXWRTBV7ZD');\"}]]]}]}]\n21:T12db,\u003cp\u003e這幾天做了兩件不太相關的事:一件是讓一直在背景抓購物網站資訊的機器人,認得出它之前看不懂的幾種網頁長相;另一件是把私下測試中的自動交易結果,做成一個公開頁面放到個人網站上,方便給人看作品。順手也在聯絡頁加了一個讓訪客直接約時間的按鈕。\u003c/p\u003e\n\u003ch2\u003e爬蟲沒看過的版面,會安靜地抓不到東西\u003c/h2\u003e\n\u003cp\u003e有一個專案是代購轉貼機器人,負責每天去日本幾個購物網站抓最新商品資訊,方便轉貼到社群平台。這幾天發現它在幾個網站上開了天窗——有的分類頁跟搜尋結果頁抓不到商品,有的商品尺寸規格讀不出來。\u003c/p\u003e\n\u003cp\u003e問題出在這些網站的頁面長相跟原本設定的不一樣。有的網站分類頁換了新的網址寫法,但舊網址其實還留著;搜尋結果頁要看頁面標題裡的關鍵字才認得出哪些是要的商品;商品尺寸資訊有些網站寫在沒有標籤的一般說明文字裡,寫法五花八門。這些情況都得一個一個補規則才認得出來。\u003c/p\u003e\n\u003cp\u003e如果請AI做一個每天要自動執行、去別人網站抓資料的工作,得先假設那個網站不會只有一種長相。規則寫死在一種版面上,遇到另一種版面時它不會主動喊救命,只會安靜地抓空。平常留一份維護清單,才看得出是哪個網站、哪種頁面壞掉了。\u003c/p\u003e\n\u003cdetails class=\"callout\"\u003e\u003csummary\u003e\u003cspan class=\"callout-kind\"\u003enote\u003c/span\u003e\u003cspan\u003e技術細節:三個爬蟲補丁\u003c/span\u003e\u003c/summary\u003e\u003cdiv class=\"callout-body\"\u003e\u003cp\u003etoei-anim 補上分類頁 /shop/c/cXX/ 與舊網址 category.aspx 的解析規則(送 dtype=Category、dcode=XX)。\nmovic 補上搜尋結果頁 /shop/goods/search.aspx,抓 \u003ctitle\u003e 關鍵字比對、p=N 翻頁,上限 30 頁。\nanimate 的 fetchDetail 補回傳 specs,extractSpecs 處理沒有標籤的尺寸寫法(如 H180mm×W90mm×D3mm、Φ56mm 等)。\n對應維護看板編號 B-22、B-23。\u003c/p\u003e\u003c/div\u003e\u003c/details\u003e\u003ch2\u003e內部資料要公開,先做一份唯讀的複本\u003c/h2\u003e\n\u003cp\u003e我私下有一個自動交易系統,用假錢做紙上交易實驗,用來驗證交易策略。為了讓個人作品集網站看起來更有說服力,這幾天把這個實驗的走勢圖、績效、持股結果做成一個公開頁面放上網站。\u003c/p\u003e\n\u003cp\u003e公開頁面不會直接連到那個正在運作的交易系統。交易系統會定期做一份唯讀的複本資料,公開網站只讀這份複本來顯示畫面。這就像把展品放進博物館的玻璃櫃給遊客看,遊客看得到,但碰不到,也動不了櫃子裡的真品。另外還寫了一支檢查程式,專門抓公開頁面上有沒有不小心漏出內部才用的代號或字眼。\u003c/p\u003e\n\u003cpre class=\"mermaid\"\u003eflowchart LR\n A[正在運作的交易系統] --\u0026gt; B[定期做一份唯讀複本]\n B --\u0026gt; C[公開網站只讀複本來顯示]\u003c/pre\u003e\n\u003cp\u003e如果要把內部系統的資料公開給外人看,不要讓公開頁面直接連到正在運作的系統,中間隔一層唯讀的複本。這樣公開頁面出問題也不會影響到正在跑的系統,內部還在調整中的資料也不會不小心曝光。\u003c/p\u003e\n\u003cdetails class=\"callout\"\u003e\u003csummary\u003e\u003cspan class=\"callout-kind\"\u003enote\u003c/span\u003e\u003cspan\u003e技術細節:唯讀匯出與驗證腳本\u003c/span\u003e\u003c/summary\u003e\u003cdiv class=\"callout-body\"\u003e\u003cp\u003e020 的 run_export.py 與 qtrader/paper/public_export.py 以 mode=ro 開啟帳本,匯出 018 用的 content/data/paper-trading/snapshot.json,數字全部來自既有的 sleeve_perf、track_orders、order_stats 等函式。\n018 新增 /data/paper-trading 三語頁面(SSG),含走勢圖、績效、持股、AI 提案、機率評分、風控等區塊。\nscripts/verify-paper-trading.ts 檢查 schema、禁用詞、內部用語與組名字典是否一致,納入 npm run verify。\u003c/p\u003e\u003c/div\u003e\u003c/details\u003e\u003ch2\u003e留言板旁邊多開一條直接約時間的路\u003c/h2\u003e\n\u003cp\u003e個人作品集網站的聯絡頁,本來只能留言等我回信。這幾天加了一個預約會議的按鈕,訪客可以直接選時間,不用來回等信,按下去開新分頁導去我自己用的預約連結,版面維持原本的樣子沒有大動。\u003c/p\u003e\n\u003cp\u003e如果網站的目的是要讓別人聯繫你,留言等回信跟直接約時間這兩條路都留著比較好。有人喜歡先留言問清楚,有人只想直接訂個時間,兩種人都要接得住。\u003c/p\u003e\n\u003ch2\u003e接下來\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e模擬交易儀表板目前還在本機測試,還沒真正對外上線。\u003c/li\u003e\n\u003cli\u003e代購轉貼機器人這幾個網站的補丁是被動發現才修的,還要留意有沒有其他網站也因為改版而抓不到資料。\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003cp\u003e\u003csmall\u003e本篇由跨專案自動彙整產生,素材為 2026-09-17 之後 3 個專案的提交紀錄與 0 則知識投遞。\u003c/small\u003e\u003c/p\u003e\n17:[\"$\",\"main\",null,{\"className\":\"flex-1 px-6 py-12 sm:px-10 lg:px-[88px] lg:pb-[88px] lg:pt-[76px]\",\"children\":[[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"{\\\"@context\\\":\\\"https://schema.org\\\",\\\"@type\\\":\\\"BlogPosting\\\",\\\"headline\\\":\\\"把测试中的交易结果摆进玻璃柜,也把读不懂新网页的爬虫治好\\\",\\\"description\\\":\\\"這幾天做了兩件不太相關的事:一件是讓一直在背景抓購物網站資訊的機器人,認得出它之前看不懂的幾種網頁長相;另一件是把私下測試中的自動交易結果…\\\",\\\"url\\\":\\\"https://junlin0083.com/blog/ai-log-2026-09-18\\\",\\\"datePublished\\\":\\\"2026-09-18\\\",\\\"dateModified\\\":\\\"2026-09-18\\\",\\\"inLanguage\\\":\\\"zh-Hant-TW\\\",\\\"author\\\":{\\\"@id\\\":\\\"https://junlin0083.com/#person\\\"},\\\"image\\\":\\\"https://junlin0083.com/blog-assets/ai-log-2026-09-18/AI%20%E6%97%A5%E8%AA%8C%202026-09-18-cover.jpg\\\"}\"}}],[\"$\",\"p\",null,{\"className\":\"mb-7 max-w-[720px] border-l-2 border-hairline pl-3 text-[13px] leading-[1.8] text-muted\",\"children\":\"記事は繁体字中国語で書かれています。\"}],[\"$\",\"article\",null,{\"lang\":\"zh-Hant-TW\",\"className\":\"max-w-[720px]\",\"children\":[[\"$\",\"$L1f\",null,{\"href\":\"/ja/blog\",\"className\":\"inline-flex items-center gap-2 font-archivo text-xs font-semibold uppercase tracking-[0.14em] text-faint transition-colors hover:text-accent\",\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"children\":\"←\"}],\"AI BLOG\"]}],[\"$\",\"div\",null,{\"className\":\"mt-[34px] flex flex-wrap gap-[18px] font-archivo text-xs font-medium uppercase tracking-[0.1em] tabular-nums text-faint\",\"children\":[[\"$\",\"span\",null,{\"children\":\"2026-09-18\"}],false,[\"$\",\"span\",null,{\"children\":\"AI 日誌\"}]]}],[\"$\",\"h1\",null,{\"className\":\"mt-[14px] text-balance font-noto text-[26px] font-bold leading-[1.45] tracking-[-0.015em] sm:text-[32px] lg:text-[40px] lg:leading-[1.34]\",\"children\":\"把测试中的交易结果摆进玻璃柜,也把读不懂新网页的爬虫治好\"}],[\"$\",\"figure\",null,{\"className\":\"mt-[38px]\",\"children\":[[\"$\",\"$L20\",null,{\"src\":\"/blog-assets/ai-log-2026-09-18/AI%20%E6%97%A5%E8%AA%8C%202026-09-18-cover.jpg\",\"alt\":\"把测试中的交易结果摆进玻璃柜,也把读不懂新网页的爬虫治好 封面\",\"width\":1376,\"height\":768,\"priority\":true,\"sizes\":\"(min-width: 1024px) 720px, 100vw\",\"className\":\"h-auto w-full bg-[#F2F2F2]\"}],[\"$\",\"figcaption\",null,{\"className\":\"mt-[10px] text-xs text-faint\",\"children\":\"封面由跨專案自動彙整流程生成。\"}]]}],[\"$\",\"div\",null,{\"className\":\"prose mt-10\",\"dangerouslySetInnerHTML\":{\"__html\":\"$21\"}}],\"$L22\"]}],\"$L23\"]}]\n24:I[3387,[\"/_next/static/immutable/chunks/4151u7kuqmfgu.js\",\"/_next/static/immutable/chunks/3zbglfeikyhj3.js\"],\"default\"]\n22:[\"$\",\"p\",null,{\"className\":\"mt-[34px]\",\"children\":[\"$\",\"$L1f\",null,{\"href\":\"/ja/blog\",\"className\":\"inline-flex items-center gap-2 font-archivo text-xs font-semibold uppercase tracking-[0.14em] text-faint transition-colors hover:text-accent\",\"children\":[[\"$\",\"span\",null,{\"aria-hidden\":true,\"children\":\"←\"}],\"AI BLOG に戻る\"]}]}]\n23:[\"$\",\"$L24\",null,{}]\n1c:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n25:I[27201,[\"/_next/static/immutable/chunks/2corl6wyj4669.js\"],\"IconMark\"]\n1a:null\n1e:[[\"$\",\"title\",\"0\",{\"children\":\"把测试中的交易结果摆进玻璃柜,也把读不懂新网页的爬虫治好\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"這幾天做了兩件不太相關的事:一件是讓一直在背景抓購物網站資訊的機器人,認得出它之前看不懂的幾種網頁長相;另一件是把私下測試中的自動交易結果…\"}],[\"$\",\"link\",\"2\",{\"rel\":\"canonical\",\"href\":\"https://junlin0083.com/blog/ai-log-2026-09-18\"}],[\"$\",\"meta\",\"3\",{\"property\":\"og:title\",\"content\":\"把测试中的交易结果摆进玻璃柜,也把读不懂新网页的爬虫治好\"}],[\"$\",\"meta\",\"4\",{\"property\":\"og:description\",\"content\":\"這幾天做了兩件不太相關的事:一件是讓一直在背景抓購物網站資訊的機器人,認得出它之前看不懂的幾種網頁長相;另一件是把私下測試中的自動交易結果…\"}],[\"$\",\"meta\",\"5\",{\"property\":\"og:url\",\"content\":\"https://junlin0083.com/blog/ai-log-2026-09-18\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:site_name\",\"content\":\"Jun Lin\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:locale\",\"content\":\"zh_TW\"}],[\"$\",\"meta\",\"8\",{\"property\":\"og:image\",\"content\":\"https://junlin0083.com/opengraph-image\"}],[\"$\",\"meta\",\"9\",{\"property\":\"og:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"10\",{\"property\":\"og:image:height\",\"content\":\"630\"}],[\"$\",\"meta\",\"11\",{\"property\":\"og:image:alt\",\"content\":\"Jun Lin — Project Management · Planning · Operations\"}],[\"$\",\"meta\",\"12\",{\"property\":\"og:type\",\"content\":\"article\"}],[\"$\",\"meta\",\"13\",{\"property\":\"article:published_time\",\"content\":\"2026-09-18\"}],[\"$\",\"meta\",\"14\",{\"property\":\"article:modified_time\",\"content\":\"2026-09-18\"}],[\"$\",\"meta\",\"15\",{\"property\":\"article:author\",\"content\":\"https://junlin0083.com/about\"}],[\"$\",\"meta\",\"16\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"17\",{\"name\":\"twitter:title\",\"content\":\"把测试中的交易结果摆进玻璃柜,也把读不懂新网页的爬虫治好\"}],[\"$\",\"meta\",\"18\",{\"name\":\"twitter:description\",\"content\":\"這幾天做了兩件不太相關的事:一件是讓一直在背景抓購物網站資訊的機器人,認得出它之前看不懂的幾種網頁長相;另一件是把私下測試中的自動交易結果…\"}],[\"$\",\"meta\",\"19\",{\"name\":\"twitter:image\",\"content\":\"https://junlin0083.com/twitter-image\"}],[\"$\",\"meta\",\"20\",{\"name\":\"twitter:image:alt\",\"content\":\"Jun Lin — Project Management · Planning · Operations\"}],[\"$\",\"meta\",\"21\",{\"name\":\"twitter:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"22\",{\"name\":\"twitter:image:height\",\"content\":\"630\"}],[\"$\",\"link\",\"23\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.12hm0eae7zsgq.ico\",\"sizes\":\"64x64\",\"type\":\"image/x-icon\"}],[\"$\",\"link\",\"24\",{\"rel\":\"icon\",\"href\":\"/icon?436e36de272eeaa5\",\"alt\":\"$undefined\",\"type\":\"image/png\",\"sizes\":\"64x64\"}],[\"$\",\"$L25\",\"25\",{}]]\n"])</script></body></html>