iT邦幫忙

2

【Python】

  • 分享至 

  • xImage

https://ithelp.ithome.com.tw/upload/images/20250310/20172214W5QMk8KUAE.png

求救各位python大神,找不到他的API,我用selenium爬取公開資訊訊觀測站,
使用webdriver按下【詳細資料】按鈕可以成功開的了視窗,
但讀不到新跳出來的視窗

這是我爬取的網站網址
https://mopsov.twse.com.tw/mops/web/ajax_t114sb07?parameters=0eb65210d5bdc34ea16e295ccdbad1094cba7de165dfcdf4e7902f9ef62c42f5e1d5d55f2907af83df59ae82756caca37dd8deda6d21048dd6757f91f6feed9efade4567702b1a82869a09fd73fc40584805cee69a5101ddc3bffc42dba6838e87d6b6c0db4e0cc4b38b25e81f8e9e6aaeb537f477d135aaa7cfe6b60d70cfc4

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup

# 啟動 WebDriver
driver = webdriver.Chrome()

try:
    # 打開目標網頁
    driver.get("https://mopsov.twse.com.tw/mops/web/ajax_t114sb07?parameters=0eb65210d5bdc34ea16e295ccdbad1094cba7de165dfcdf4e7902f9ef62c42f5e1d5d55f2907af83df59ae82756caca37dd8deda6d21048dd6757f91f6feed9efade4567702b1a82869a09fd73fc40584805cee69a5101ddc3bffc42dba6838e87d6b6c0db4e0cc4b38b25e81f8e9e6aaeb537f477d135aaa7cfe6b60d70cfc4")

    # 記錄原始視窗
    original_window = driver.current_window_handle

    # 等待並點擊按鈕
    button = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, '//*[@id="t114sb07_fm"]/p[2]/table[2]/tbody/tr[4]/td[9]/input'))
    )
    driver.execute_script("arguments[0].click();", button)

    # 由於第二頁是動態生成的 (URL 為 about:blank),所以等待特定元素出現
    WebDriverWait(driver, 30).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "#table01"))
    )

    # 透過 CSS Selector 找到第二頁的表格 (JS Path: document.querySelector("#table01"))
    table_element = driver.find_element(By.CSS_SELECTOR, "#table01")
    table_html = table_element.get_attribute("outerHTML")

    # 使用 BeautifulSoup 解析表格 HTML
    soup = BeautifulSoup(table_html, "html.parser")
    rows = soup.find_all("tr")
    table_data = []
    for row in rows:
        cols = row.find_all(["td", "th"])
        cols = [col.get_text(strip=True) for col in cols]
        table_data.append(cols)

    # 打印第二頁表格的內容
    for row in table_data:
        print("\t".join(row))

    # 存入檔案
    with open("table01_data.txt", "w", encoding="utf-8") as file:
        for row in table_data:
            file.write("\t".join(row) + "\n")

    print("數據已成功寫入 table01_data.txt")

finally:
    driver.quit()

ccutmis iT邦高手 2 級 ‧ 2025-03-10 12:47:34 檢舉
# 切到新跳出來的視窗example
driver.switch_to.window(driver.window_handles[1])
此方法電腦會一直沒有回應 謝謝您!!!

2 個回答

2
猴子
iT邦新手 3 級 ‧ 2025-03-10 18:59:48
最佳解答

code

可能有些小 bug 自己在改改就好

# pip install requests bs4

import json
from dataclasses import asdict, dataclass, field
from typing import List, Optional

import requests
from bs4 import BeautifulSoup

year = 112
co_id = 1101


@dataclass
class StockCompensation:
    """股票報酬資料"""

    shares: float  # 配發股數
    market_price: float  # 市場價格(元/股)
    amount_a: float  # 計算後的股票報酬總額


@dataclass
class CashCompensation:
    """現金報酬資料"""

    amount_b: float  # 現金報酬總額


@dataclass
class ManagerCompensation:
    """管理階層報酬總計"""

    stock: StockCompensation  # 股票報酬資訊
    cash: CashCompensation  # 現金報酬資訊
    total_amount: float  # 總報酬金額(股票 + 現金)
    percentage_of_net_income: float  # 佔公司淨利比例(%)


@dataclass
class Manager:
    """管理階層人員資訊"""

    title: str  # 職稱
    name: str  # 姓名


@dataclass
class CompanyCompensation:
    """公司管理階層報酬資訊"""

    company_code: str  # 公司代號
    company_name: str  # 公司名稱
    employee_compensation_year: int  # 員工薪酬所屬年度
    distribution_year: int  # 發放年度
    unit: str  # 單位(元/股)
    manager_compensation: ManagerCompensation  # 管理階層報酬總計
    managers: List[Manager] = field(default_factory=list)  # 管理階層成員列表


def get_company_detailed(co_id: int, year: int) -> Optional[CompanyCompensation]:
    req = requests.post(
        "https://mopsov.twse.com.tw/mops/web/ajax_t114sb07",
        data={
            "encodeURIComponent": 1,
            "firstin": True,
            "id": "",
            "key": "",
            "TYPEK": "sii",
            "step": 32,
            "home_step": 0,
            "co_id": co_id,
            "year": year,
        },
    )

    soup = BeautifulSoup(req.text, "html.parser")
    form = soup.select_one("form")
    if form is None:
        return
    tables1 = form.select("table:nth-child(1)")
    table1 = tables1[0]  # 基本訊息
    table2 = tables1[1]  # 單位
    table3 = form.select("table:nth-child(2)")[0]  # 經理人酬勞分派情形
    table4 = tables1[2]  # 經理人職稱及姓名

    table1_tds = list(table1.select("td"))
    table4_tds = [x.text for x in table4.select("td") if x.text.strip()]
    year_data = table1_tds[2].select_one("td").contents  # type: ignore
    table3_tr_odd = [float(x.text.replace(",", "")) for x in table3.select("tr:nth-child(4) > td")]

    manager_compensation = ManagerCompensation(
        stock=StockCompensation(
            shares=table3_tr_odd[0],
            amount_a=table3_tr_odd[1],
            market_price=table3_tr_odd[2],
        ),  # 股票報酬資訊
        cash=CashCompensation(amount_b=table3_tr_odd[3]),  # 現金報酬資訊
        total_amount=table3_tr_odd[4],  # 總報酬金額(股票 + 現金)
        percentage_of_net_income=table3_tr_odd[5],  # 佔公司淨利比例(%)
    )

    manager_compensation: ManagerCompensation
    return CompanyCompensation(
        company_code=table1_tds[0].contents[2].text.strip(),
        company_name=table1_tds[1].contents[2].text.strip(),
        employee_compensation_year=int(year_data[1].text),
        distribution_year=int(year_data[4].text),
        unit=table2.text.strip(),
        manager_compensation=manager_compensation,
        managers=[Manager(title=title, name=name) for title, name in zip(table4_tds[::2], table4_tds[1::2])],
    )


if company := get_company_detailed(co_id, year):
    company_dict = asdict(company)
    print(json.dumps(company_dict, ensure_ascii=False, indent=2))

out:

{
  "company_code": "1101",
  "company_name": "台泥",
  "employee_compensation_year": 111,
  "distribution_year": 112,
  "unit": "單位:元/股",
  "manager_compensation": {
    "stock": {
      "shares": 0.0,
      "market_price": 0.0,
      "amount_a": 0.0
    },
    "cash": {
      "amount_b": 8376383.0
    },
    "total_amount": 8376383.0,
    "percentage_of_net_income": 0.1549
  },
  "managers": [
    {
      "title": "企業團總執行長",
      "name": "張安平"
    },
    {
      "title": "總經理",
      "name": "程耀輝"
    },
    {
      "title": "資深副總經理",
      "name": "黃健強"
    },
    {
      "title": "資深副總經理",
      "name": "呂克甫"
    },
    {
      "title": "副總經理",
      "name": "葛保羅"
    },
    {
      "title": "副總經理",
      "name": "王建全"
    },
    {
      "title": "副總經理",
      "name": "劉鳳萍"
    },
    {
      "title": "副總經理",
      "name": "葉毓君"
    },
    {
      "title": "財務長",
      "name": "于明仁"
    },
    {
      "title": "資深協理",
      "name": "蔡國嶼"
    },
    {
      "title": "資深協理",
      "name": "丘惠生"
    },
    {
      "title": "資深協理兼會計主管",
      "name": "葉國宏"
    },
    {
      "title": "資深協理",
      "name": "邱鈺文"
    },
    {
      "title": "協理",
      "name": "辜公怡"
    },
    {
      "title": "協理",
      "name": "余金龍"
    },
    {
      "title": "協理",
      "name": "藍岑藯"
    },
    {
      "title": "協理兼公司治理主管",
      "name": "賴家柔"
    },
    {
      "title": "協理",
      "name": "陳光熙"
    },
    {
      "title": "協理",
      "name": "魏家珮"
    },
    {
      "title": "協理",
      "name": "李國源"
    },
    {
      "title": "協理",
      "name": "蔣政道"
    },
    {
      "title": "協理",
      "name": "陳銀華"
    },
    {
      "title": "協理",
      "name": "陳怡中"
    },
    {
      "title": "資安長",
      "name": "張年旺"
    },
    {
      "title": "資深經理",
      "name": "陳進益"
    },
    {
      "title": "資深經理",
      "name": "吳雲德"
    },
    {
      "title": "資深經理",
      "name": "陳技竫"
    },
    {
      "title": "資深經理",
      "name": "梁詩聖"
    },
    {
      "title": "經理兼稽核主管",
      "name": "曹家華"
    },
    {
      "title": "資深副理",
      "name": "吳子揚"
    },
    {
      "title": "資深副理",
      "name": "張毓揚"
    },
    {
      "title": "總經理",
      "name": "李鐘培"
    },
    {
      "title": "資深協理",
      "name": "黃麟添"
    },
    {
      "title": "協理",
      "name": "洪維爵"
    },
    {
      "title": "協理",
      "name": "宋又新"
    },
    {
      "title": "資深經理",
      "name": "李明達"
    },
    {
      "title": "經理",
      "name": "劉志仁"
    }
  ]
}
0
zivzhong
iT邦研究生 3 級 ‧ 2025-03-10 13:36:49

目前是參考這篇沒錯 但還是無法 但謝謝您提醒!!

我要發表回答

立即登入回答