當想像力跨越邊界
用 AI 實現未來生活

生活本不該被無意義的「重複與摩擦」消磨。在這個實驗室裡,我專注於重構繁瑣的日常痛點,透過 Vibe Coding,將每一個看似不切實際的想像,具現為最乾淨、流暢的自動化工作流。

About the Lab

我曾是輸出大量創意的行銷人,而在這裡我是大膽嘗試的科學家!過去,天馬行空的想像常被技術限制了疆界,而現在我從生活中捕捉靈感、設定目標,將繁瑣的難題一步步細細拆解,再透過 AI 的分析與協作,將想像具現落地。

探索我的實驗成果!
Projects

LinkedIn 徵才貼文雷達

每天定時自動搜尋 LinkedIn 上符合特定關鍵字的個人徵才動態,並寫入至 Google 試算表中,節省人工爬文時間,掌握高價值的工作機會

問題

許多優質企業未公開招募職缺只出現在 LinkedIn 個人貼文中,常因演算法與人脈限制而錯過,而要靠人工搜尋,又得花費好多時間......

解法

透過定時排程啟動網頁自動化工具(Playwright),自動登入 LinkedIn 搜尋關鍵字並向下瀏覽,過濾重複內容後,將最新貼文直接寫入 Google 試算表。

流程
排程喚醒
確認網路就緒
搜尋並捲動載入
錨點擷取貼文
去重寫入試算表
專案亮點
  • 智慧喚醒偵測:自動啟動時會先確認網路連線,避免因開機瞬間沒網而直接中斷報錯
  • 防改版定位(data-testid):採用「網站身分標籤」鎖定資料,大幅降低因網頁改版而失效的機率
  • 斷網自動備份:寫入試算表失敗時會自動重試;若完全斷網,則先將資料存至電腦本機,確保資料不遺失
Python Playwright launchd 排程 Google Sheets API 容錯設計

抗改版的擷取錨點(scrape.py)

// LinkedIn 的 CSS class 每次改版都是隨機雜湊值,不能拿來當 selector
// 改用不會變動的錨點:data-testid,以及祖先中的 /in/ 或 /company/ 連結
const items = document.querySelectorAll(
  '[data-testid="expandable-text-box"]'
);
// 往上找最近的、包含個人檔案連結的祖先元素當作貼文容器

喚醒後的網路就緒檢查(scrape.py)

def wait_for_network(host="www.linkedin.com", port=443, max_wait=90):
    deadline = time.time() + max_wait
    while time.time() < deadline:
        try:
            with socket.create_connection((host, port), timeout=5):
                return True
        except OSError:
            time.sleep(5)
    return False

AI 履歷客製化系統

自動搜尋 LinkedIn 上符合條件的潛在職缺,透過 AI 比對個人履歷,進行職缺匹配程度評分,最後產出針對該職缺的客製化履歷內容。

問題

過往求職需要手動在 LinkedIn 裡慢慢撈適合自己職缺、比對 JD 後再手動修改每一份履歷,這種仰賴人工的流程,大幅影響了求職效率。

解法

自動檢索 LinkedIn 符合關鍵字的公開職缺,交由 AI 比對個人經歷進行匹配度評分,並針對高分職缺一鍵生成與匯出客製化履歷。

流程
排程抓取職缺
AI 評估適配度
生成客製化內容
中英夾雜校正
套版到可編輯網頁
列印/匯出 PDF
專案亮點
  • 智慧分組搜尋與篩選:自動將複雜的關鍵字拆解分組查詢,避開 LinkedIn 的 Boolean 搜尋限制,兼顧搜尋的精準度與完整性
  • Token 成本控制最佳化:將 JD 比對、語言與字數校正整合為單次 API 呼叫,在大幅降低 Token 消耗的同時,也顯著縮減了生成時間
  • 動態引用專案案例:內建 15 個額外客戶案例庫,AI 會根據目標職缺動態挑選最相關的實績融入履歷中
  • 上下文脈絡化校正:偵測到中英夾雜或語意不順時,命令 AI 重寫整句而非生硬的逐字刪減,確保語句流暢不破碎
Python Streamlit Gemini API Google Sheets API 適配度評分 網頁化編輯介面

自我校正迴圈(app.py)

# 偵測到殘留英文就請模型重寫該句,而非用正則刪字
for _ in range(MAX_FIX_ATTEMPTS):
    offending = find_offending_words(result_text)
    if not offending:
        break
    fix_prompt = build_fix_prompt(result_text, offending)
    result_text = client.models.generate_content(
        model=GEMINI_MODEL, contents=fix_prompt, config=gen_config,
    ).text
    result_text = apply_dictionary(result_text)

批次同步的重試策略(sync_sheet.py)

def _generate_with_retry(client, contents, config):
    for attempt in range(MAX_RETRIES):
        try:
            return client.models.generate_content(
                model=GEMINI_MODEL, contents=contents, config=config
            )
        except Exception as e:
            # 429/額度用盡重試無效,只重試 503 等暫時性錯誤
            is_transient = any(m in str(e) for m in TRANSIENT_MARKERS)
            if not is_transient or attempt == MAX_RETRIES - 1:
                raise
            delay = RETRY_BASE_DELAY * (2 ** attempt)
            time.sleep(delay)
Skills
AI/LLM 整合
Gemini API Prompt Engineering 結構化輸出JSON 生成內容自我校正
應用開發
Python Streamlit Google Sheets API OAuth 授權流程
開發方式
Claude Code 系統架構設計 模組化重構
Contact
Portfolio
Website
LinkedIn
ms-skye-peng