顯示具有 download 標籤的文章。 顯示所有文章
顯示具有 download 標籤的文章。 顯示所有文章

2024年8月23日 星期五

Python 開發筆記 - 不透過 Google API Key 下載公開 Google Sheets 資料,將每個 Sheet 匯出 csv 格式

有個工作任務要做 Google Sheets 資料比對,最簡單的方式就把他們匯出後用 git diff 來比對即可,想試著用 AI 產生一隻 python 小工具,只要輸入 Google Sheets URL 或是 Google Sheets URL 內關鍵的辨識 ID (在此稱作 spreadsheet id),就能夠下載該 Google Spreadsheet 內所有 sheet 資料

然後,要下載指定 sheet 必須得知每個 sheet gid ,這個問 ChatGPT-4o 或 Claude.ai 老半天還是沒法解,包過上傳 html static code,最後自己還是跳下來收尾人工刻一下,原理:

  • 先設法下載到 HTML Code
  • 透過 docs-sheet-tab-caption 抓出 Sheet Name
  • 透過 var bootstrapData = {...}; 得知內有 Sheet Name 與 Gid 的資料
  • 再用 [0,0,\"gid\",[ 格式,找到 gid
連續動作:

% python3 main.py 

usage: main.py [-h] (--google-spreadsheet-url GOOGLE_SPREADSHEET_URL | --google-spreadsheet-id GOOGLE_SPREADSHEET_ID) [--output OUTPUT]

main.py: error: one of the arguments --google-spreadsheet-url --google-spreadsheet-id is required


% python3 main.py --google-spreadsheet-id 'XXXXXXXXXXXXXXXXXXXXXXX'

[INFO] Downloaded sheet: sheet01 to sheets_csv/sheet01.csv

[INFO] Downloaded sheet: sheet02 to sheets_csv/sheet02.csv

[INFO] Downloaded sheet: sheet03 to sheets_csv/sheet03.csv

[INFO] Downloaded sheet: sheet04 to sheets_csv/sheet04.csv

[INFO] Downloaded sheet: sheet05 to sheets_csv/sheet05.csv


程式碼:

```
% cat main.py 
import argparse
import re
import requests
import json
import os

def extract_spreadsheet_id(url):
    match = re.search(r'/d/([a-zA-Z0-9-_]+)', url)
    return match.group(1) if match else None

def get_spreadsheet_info(spreadsheet_id):
    url = f"https://docs.google.com/spreadsheets/d/{spreadsheet_id}/edit"
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    }
    
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        html_content = response.text
        
        # Extract sheet names
        sheet_names = re.findall(r'docs-sheet-tab-caption[^>]+>([^<]+)</div>', html_content)
        #print(f"Found sheet names: {sheet_names}")

        # Extract mergedConfig
        config_match = re.search(r'var bootstrapData\s*=\s*({.*?});', html_content, re.DOTALL)
        if config_match:
            config_str = config_match.group(1)
            sheet_info = {}
            try:
                for index, sheet_name in enumerate(sheet_names):
                    #print(f"Processing sheet: {sheet_name}, index: {index}")
                    beginPattern = f'[{index},0,\\"'
                    endPattern = f'\\",['
                    beginIndex = config_str.find(beginPattern)
                    endIndex = config_str.find(endPattern, beginIndex)
                    gidValue = config_str[beginIndex + len(beginPattern):endIndex]
                    sheet_info[sheet_name] = gidValue
                return sheet_info
            except Exception as e:
                print(f"[INFO] Error extracting sheet information: {e}")
                return None
        else:
            print("[INFO] Could not find bootstrapData in the HTML content")
            return None
    except requests.RequestException as e:
        print(f"[INFO] Error fetching the spreadsheet: {e}")
        return None

def download_sheet_as_csv(spreadsheet_id, sheet_name, gid, output_folder):
    csv_url = f"https://docs.google.com/spreadsheets/d/{spreadsheet_id}/export?format=csv&gid={gid}"
    csv_response = requests.get(csv_url)
    
    if csv_response.status_code == 200:
        output_path = os.path.join(output_folder, f"{sheet_name}.csv")
        with open(output_path, 'wb') as f:
            f.write(csv_response.content)
        print(f"[INFO] Downloaded sheet: {sheet_name} to {output_path}")
    else:
        print(f"[INFO] Failed to download sheet: {sheet_name}. Status code: {csv_response.status_code}")

def main():
    parser = argparse.ArgumentParser(description="Extract Google Spreadsheet information")
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument("--google-spreadsheet-url", help="Google Spreadsheet URL")
    group.add_argument("--google-spreadsheet-id", help="Google Spreadsheet ID")
    parser.add_argument('--output', type=str, default='sheets_csv', help='The directory to save the CSV files')
    args = parser.parse_args()

    if args.google_spreadsheet_url:
        spreadsheet_id = extract_spreadsheet_id(args.google_spreadsheet_url)
    else:
        spreadsheet_id = args.google_spreadsheet_id

    if not spreadsheet_id:
        print("[INFO] Invalid Google Spreadsheet URL or ID")
        return

    sheet_info = get_spreadsheet_info(spreadsheet_id)
    if sheet_info:
        for name, gid in sheet_info.items():
            download_sheet_as_csv(spreadsheet_id, name, gid, args.output)
    else:
        print("[INFO] Failed to extract sheet information")

if __name__ == "__main__":
    main()
```

2024年7月15日 星期一

macOS - android fileTransfer 下載位置 AndroidFileTransfer.dmg


圖:2024-07-15 https://www.android.com/filetransfer/


以前都用 Google 找 Android fileTransfer 來下載,現在有點詭異,不知為何連到 https://www.android.com/filetransfer/ 時,首頁看不到下載位置。這大概是 2024 年春天以後發生的事。

只好亂翻一下得到 google.com 下載位置,像是用 web.archive.org 定位一下:
有興趣可以在這邊回顧,看來是 2024-05-21 起就不見了:




2020年2月27日 星期四

kobo desktop 下載 , kobo app download @ macOS / Windows

昨晚跟在 FB 工作的學弟通個電話,聊了一陣子,被推坑看了一本 2017 年再版的書。找了一陣子,實體書都賣光了,只剩 KOBO 有電子書在賣,恰好當年 Kobo 在台灣推廣時,一直說第一次購書可以折 100 元,當時 NETFLIX 給力很夯,只是我最後買了實體書 XD 因此,那一百元折價一直沒用,就這樣很快地刷卡。

接著下一刻就囧了,大家都說可以用電腦看,找了很久台灣官網上沒有下載連結,輾轉得知改用美版網站就有了!
  • https://www.kobo.com/us/en/p/desktop 下方有 Download Now
    • https://kbdownload1-a.akamaihd.net/desktop/kobodesktop/kobosetup.dmg
    • https://kbdownload1-a.akamaihd.net/desktop/kobodesktop/kobosetup.exe
最近共用了 Kindle 看書、豆瓣閱讀 Mobile app 跟 Web 觀看付費書籍,接下來試試 Kobo 囉

2019年4月4日 星期四

[macOS] 製作 macOS High sierra USB 安裝碟 @ macOS 10.13.6

build macOS USB install 10.13

手上這台 Macbook Pro 已經無法安裝 macOS 10.14 了,正準備更換 SSD ,因此想先準備 USB 安裝碟時,發現竟然無法製作 Orz 透過官網教學文才找到 macOS 10.13 下載位置  ( https://itunes.apple.com/tw/app/macos-high-sierra/id1246284741?ls=1&mt=12 ) ,發現僅 15MB 的大小,執行指令時會看到以下錯誤訊息:

$ time sudo /Applications/Install\ macOS\ High\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/8GUSB/
/Applications/Install macOS High Sierra.app does not appear to be a valid OS installer application.


最後研究一下,原來要靠安裝流程,讓系統根目錄 macOS Install Data 會產生必要的資料,接著安裝過程下載完必須的軟體時,會停在要重開機的路上,這時就可以關閉安裝,並把必要的資料取出來使用。

$ tree /macOS\ Install\ Data/ ; sudo du -hd1 /macOS\ Install\ Data/
/macOS\ Install\ Data/
├── AppleDiagnostics.chunklist
├── AppleDiagnostics.dmg
├── BaseSystem.chunklist
├── BaseSystem.dmg
├── InstallESDDmg.pkg
├── InstallInfo.plist
├── Locked\ Files
└── index.sproduct

1 directory, 7 files
 20K /macOS Install Data//Locked Files
4.9G /macOS Install Data/


接著可透過"顯示套件"的方式,在 Install macOS High Sierra.app 內的 Contents 中,建立 SharedSupport 目錄,並把 macOS Install Data 複製進去:

$ tree /Applications/Install\ macOS\ High\ Sierra.app/Contents/SharedSupport
/Applications/Install\ macOS\ High\ Sierra.app/Contents/SharedSupport
├── AppleDiagnostics.chunklist
├── AppleDiagnostics.dmg
├── BaseSystem.chunklist
├── BaseSystem.dmg
├── InstallESDDmg.pkg
├── InstallInfo.plist
└── index.sproduct

0 directories, 7 files


就可以製作 USB 安裝碟:

$ time sudo /Applications/Install\ macOS\ High\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/8GUSB/
Password:
Ready to start.
To continue we need to erase the volume at /Volumes/8GUSB/.
If you wish to continue type (Y) then press return: Y


Updated @ 2019/04/06:

雖說可以順利製作出開機碟,但發現該 USB 無法完成 10.13.6 作業系統的安裝。推論是系統安裝流程已被修改的關係,應當是系統安裝時,會要求要安裝的系統碟的根目錄上,配有 "/macOS Install Data/" 資料,才能重開機後完成安裝流程。

以上並未驗證 :P 因為這次重安裝是為了把筆電換上新的 SSD ,因此單純先把原本的系統碟透過外接方式重啟,並跑正常的系統安裝流程,安置在新的 SSD ,而安裝過程就完全不靠 USB 開機碟。

或許把 SharedSupport 複製一份到新 SSD 的 "/macOS Install Data/" 有可能就可以搞定?!

2015年10月3日 星期六

iOS 開發筆記 - 下載舊版 Simulator,如 iOS 8 Simulator

Download iOS Simulator

記得很久以前,我還有把 Xcode 3,4 系列燒成光碟,為的就是舊版 simulator,後來不知不覺就都不需要,甚至把玩 app 都直接用最新版 iOS siumulator 跟 sdk 了。不過這次 iOS 9 跟 iOS 8 有一些 layout 問題,所以還是找一下舊版 simulator 吧!

Xcode -> Preferences -> Downloads 或是 iOS Simulator -> Hardware -> Device -> Manage Devices -> 左下角 + -> iOS Version -> Download more simulators 。

此外,有人說在 OS X EI Capitan 已不支援 iOS 7 Simulator 了 :P 所以在此版本的作業系統下載不到。

另外一提,安裝 Simulator 需要用高級權限 Orz 不然會有以下訊息:

Cloud not download and install iOS 8.x Simulator.

高級權限的方式:

sudo /Applications/Xcode.app/Contents/MacOS/Xcode