Board logo

標題: [原創] python上市櫃三大法人買賣超日報資料下載 [打印本頁]

作者: zyzzyva    時間: 2016-8-16 22:22     標題: python上市櫃三大法人買賣超日報資料下載

可用來下載上市櫃三大法人買賣超日報資料。與py檔同一路徑下的path.ini可設定csv存放位置,注意路徑要包括最後一個"\",如:C:\user\desktop\test\。
附上執行檔
  1. import requests
  2. import time
  3. import os

  4. mydate = time.strftime("%Y/%m/%d")
  5. year = str(int(mydate[0:4])-1911)
  6. mydate2 = mydate.replace(mydate[0:4],year)

  7. setting = os.getcwd() + "\\" + "path.ini"

  8. if os.path.exists(setting):
  9.     with open(setting, 'r') as r:
  10.         path = r.read()
  11.     if not os.path.exists(path):
  12.         os.makedirs(path)
  13. else:
  14.     path = ""

  15. headers = {"User-Agent":"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"}


  16. url1 = "http://www.twse.com.tw/ch/trading/fund/T86/T86.php"
  17. payload1 = {"download": "csv",
  18.             "qdate": mydate2,
  19.             "select2": "ALLBUT0999",
  20.             "sorting": "by_issue"}

  21. res1 = requests.post(url1, headers=headers, data=payload1, stream=True)

  22. fName1 = path + mydate.replace("/","") + ".csv"

  23. with open(fName1, 'wb') as f1:
  24.     for chunk in res1.iter_content(1024):
  25.         f1.write(chunk)


  26. url3 = "http://www.tpex.org.tw/web/stock/3insti/daily_trade/\
  27. 3itrade_hedge_download.php?l=zh-tw&se=EW&t=D&d=" + mydate2 + "&s=0,asc,0"

  28. res3 = requests.get(url3, headers=headers, stream=True)

  29. fName3 = path + "BIGD_" + mydate2.replace("/","") + ".csv"

  30. with open(fName3, 'wb') as f3:
  31.     for chunk in res3.iter_content(1024):
  32.         f3.write(chunk)


  33. url2 = "http://www.twse.com.tw/ch/trading/exchange/MI_INDEX/MI_INDEX.php"
  34. payload2 = {"download": "csv",
  35.             "qdate": mydate2,
  36.             "selectType": "ALLBUT0999"}

  37. res2 = requests.post(url2, headers=headers, data=payload2,stream=True)

  38. fName2= path + "A11" + mydate.replace("/","") + ".csv"

  39. with open(fName2, 'wb') as f2:
  40.     for chunk in res2.iter_content(1024):
  41.         f2.write(chunk)
  42.         

  43. url4 = "http://www.tpex.org.tw/web/stock/aftertrading/otc_quotes_no1430/\
  44. stk_wn1430_download.php?l=zh-tw&d=" + mydate2 + "&se=EW&s=0,asc,0"

  45. res4 = requests.post(url4, headers=headers, data=payload2,stream=True)

  46. fName4 = path + "SQUOTE_EW_" + mydate2.replace("/","") + ".csv"

  47. with open(fName4, 'wb') as f4:
  48.     for chunk in res4.iter_content(1024):
  49.         f4.write(chunk)
複製代碼

作者: VBALearner    時間: 2016-8-16 23:06

本帖最後由 VBALearner 於 2016-8-16 23:10 編輯

回復 1# zyzzyva

等一下!!!乾~~~這太猛了吧O___Q 居然過了一段時間...還有人再研究我的主題,有關如何下載的內容......只能說感動T___T
小弟我原本想再丟一個開發到一半的籌碼資料整理檔,內附選股表單功能與進場績效紀錄功能,和Z大共襄盛舉重啟這個主題並分享其所學,但礙於上傳限制(1MB),只好作罷,以文字交流之(嘆~)
Z大高手!!! 小弟我最近剛好也開始想學最近很火紅的Python,只不過還在摸索階段,畢竟市面上有關Py的書不多,不像VBA這種算是熱門又簡單的書籍...Z大真是勾起我對Pyhton程式的莫大興趣>w<!!! 可以請教您,幾個問題嗎? 第一,這個執行檔是全部都用Python寫的嗎?!! 您貼上來的程式碼是用Python寫的嗎? 還是Py與VBA兩者結合呢?!(看起來不像有參雜VBA語法...我幾乎看不懂xD,您於文初雖然有簡單說明,但小弟我還是甭琢磨了,先一旁玩沙去~) 。第二,您是如何學習Py的xD? 是自學、上課、還是有類似的論壇呢?  期望能站在Z大的肩膀上學習邁進OwO!!!
作者: zyzzyva    時間: 2016-8-16 23:49

回復 2# VBALearner
您過獎了。這個是python的code,如果沒有安裝python,可以下載執行檔,再在vba裡用shell的方式執行。
抓網路資料方面python還滿好用的,網路上資源很多,我也是為了抓資料東學一點西學一點,拿別人的東西修修改改。找時間再補上註解,應該會比較清楚。
作者: clianghot546    時間: 2016-8-18 15:49

版大
您的檔案下載後,執行getTwseOtc.exe後沒有反應,可以再說明清楚一點嗎?
謝謝
作者: c_c_lai    時間: 2016-8-18 16:01

回復 3# zyzzyva
檢查目錄內之檔案內容如圖示:
[attach]24968[/attach]
作者: clianghot546    時間: 2016-8-18 16:55

回復 5# c_c_lai

再重新下載解壓縮後可正常執行
TKS
研究PYTHON中~~
作者: zyzzyva    時間: 2016-8-18 17:23

回復 5# c_c_lai

應該是因為我沒有處理時間(下載的日期是直接取當日的日期),如果是資料還沒出來的時候執行下載就會出現問題。
請在傍晚的時間再試試看。
作者: c_c_lai    時間: 2016-8-18 17:42

回復 7# zyzzyva
剛剛我試了一下,OK 了。
請教一下我有下載 Python35 但是還需要怎樣的模組
條件下,才能完整執行你附上的 .py 檔呢?
Python 是有練習過,但無實務作業經驗,
還請多多指教!
作者: zyzzyva    時間: 2016-8-18 17:58

回復 1# zyzzyva
補上註解。
  1. #匯入模組(requests需另外安裝,也可使用urllib2)
  2. import requests
  3. import time
  4. import os

  5. #取得當前日期
  6. mydate = time.strftime("%Y/%m/%d")

  7. #將西元年轉為民國年
  8. year = str(int(mydate[0:4])-1911)

  9. #將民國年取代日期中之西元年
  10. mydate2 = mydate.replace(mydate[0:4],year)

  11. #os.getcwd()取得當前路徑
  12. setting = os.getcwd() + "\\" + "path.ini"

  13. #檢查path.ini是否存在,若有則將csv存檔之路徑讀入
  14. if os.path.exists(setting):
  15.     with open(setting, 'r') as r:
  16.         path = r.read()
  17.     #若csv存檔之資料夾不存在則建立資料夾
  18.     if not os.path.exists(path):
  19.         os.makedirs(path)

  20. #若path.ini不存在則將path設為空字串
  21. else:
  22.     path = ""

  23. #設定header
  24. headers = {"User-Agent":"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"}

  25. #設定url
  26. url1 = "http://www.twse.com.tw/ch/trading/fund/T86/T86.php"

  27. #設定post查詢之資料
  28. payload1 = {"download": "csv",
  29.             "qdate": mydate2,
  30.             "select2": "ALLBUT0999",
  31.             "sorting": "by_issue"}

  32. #發出request並將網站回覆之資料存入res1變數中
  33. res1 = requests.post(url1, headers=headers, data=payload1, stream=True)

  34. #設定csv檔案之路徑與檔名
  35. fName1 = path + mydate.replace("/","") + ".csv"

  36. #將res1的資料寫入csv中
  37. with open(fName1, 'wb') as f1:
  38.     for chunk in res1.iter_content(1024):
  39.         f1.write(chunk)
複製代碼

作者: zyzzyva    時間: 2016-8-18 22:20

回復 8# c_c_lai
只要安裝requests就可以了。
作者: c_c_lai    時間: 2016-8-19 07:11

回復 10# zyzzyva
謝謝你,
等我眼睛手術好後再來研究一番,
前些日子我對 Python 還蠻熱衷的,
尚請你多加指教!
作者: zyzzyva    時間: 2016-8-19 07:28

回復 11# c_c_lai
您太客氣了,有興趣可以一起研究。也預祝您手術順利,早日康復。
作者: VBALearner    時間: 2016-8-19 19:31

回復 9# zyzzyva

喔~謝謝您的教學,我日後會再進一步了解,另外請問一下,模組網址是
http://docs.python-requests.org/zh_CN/latest/user/quickstart.html
沒錯吧?
作者: zyzzyva    時間: 2016-8-19 22:04

回復 13# VBALearner
是的,那是requests模組的文件沒錯。
內建的urllib模組的功能也差不多,但是我覺得requests比較好用一點。
作者: hanson09    時間: 2016-8-27 21:30

我想請問一下, 樓主是用Python3.5 還是2.7寫的呢,我也剛接觸python,我用3.5,試了很多方式,都無法成轉執行檔

感謝,樓主提供這麼好的東西。非常感謝
作者: zyzzyva    時間: 2016-8-28 07:14

回復 15# hanson09 我的是3.4,3.5執行應該沒有問題(因為我沒有處理時間,所以要交易日的下午資料出來後執行,抓到的檔案才會完整。)你是執行過不了,還是抓不到完整檔案?有錯誤訊息嗎?
作者: hanson09    時間: 2016-8-28 13:43

樓主,我是想請問,你寫出來的 .py 檔,是如何轉成.exe的。

另外 ,我也想問個同樣的問題,樓主是看書自學python的,還是看網路文章

ps: 我在網路上也抓了不少,python 視訊教學,也希望能寫出支像樣的程式。
作者: zyzzyva    時間: 2016-8-28 21:07

回復 17# hanson09 我是用Cx_freeze,簡單的程式應該都可以,但如果程式中有用到某些套件,像tinker或lxml之類的,可能就會有問題。學python一開始是工作上需要(要抓一些籌碼資料),老闆拿了一本書給我,叫菲絲恩教你學會python,對基本語法有一些概念以後,就是看網路上的教學,要用到什麼就看什麼,看了一些覺得雖然有學到一點皮毛,不過還滿沒有系統的,所以也買了一些書,有的內容看得懂,有些一知半解,目前就是慢慢看,想說多看之後可能就會懂了。
作者: VBALearner    時間: 2016-8-30 13:23

回復 18# zyzzyva

喔~所以樓主是用pip install cx_Freeze模組把Python程式轉成執行檔,要不然其他沒有使用Python的人是不能使用樓主的程式。但是在要給他人使用時,也要連Python的一堆套件模組都要寄送出去,例如request模組,對吧(還是我觀念錯誤,小弟Py新手,請不吝指教?!) 另外想請教樓主,如果我想要改寫您的程式,可以把cx-Freeze已經轉好的執行檔再回溯回原本的py檔再改寫嗎? 還是有其他辦法可以從樓主的檔案夾裡開啟主程式碼的檔案來改寫? (我最近開始學Py,雖然比VBA還難許多倍,但感謝樓主的分享激發了我對Py的熱情,最近也去把樓主分享的那本菲絲恩教你學會Python看完了,雖然實在有夠基本無法有太大的應用層面,但也是個開始OwO!!!)
[attach]25100[/attach]
作者: zyzzyva    時間: 2016-8-30 23:23

本帖最後由 zyzzyva 於 2016-8-30 23:25 編輯

回復 19# VBALearner
cx_freeze在包的時候就會把有用到的套件包進去,所以其他人正常來說應該直接就可以使用了。python也有反組譯的工具,但我沒用過,所以詳細情況不太了解,如果要改寫應該直接用我po的code改比較方便。
要轉exe檔的時候,除了要轉的檔案(假設檔名為test.py),還要另外準備一個py檔(假設檔名為setup.py)放在同一個目錄下,內容大概是像這樣:
  1. from cx_Freeze import setup, Executable

  2. setup(name='程式的名字',
  3.       version='版本號',
  4.       description='簡單的描述',
  5.       option={"build.exe"},
  6.       executables=[Executable("test.py")])
複製代碼
然後在檔案所在目錄下開啟cmd,執行setup.py build,成功的話在同一個目錄下就會有一個build資料夾,裡頭就是我們要的東西。
其實我覺得python入門不會比vba困難耶,有vba的經驗,我想應該很快就會上手了。雖然我懂的也很有限,但有什麼問題歡迎提出來,大家可以一起研究。
作者: c_c_lai    時間: 2016-8-31 08:23

回復 12# zyzzyva
[attach]25101[/attach]
作者: lpk187    時間: 2016-8-31 09:03

本帖最後由 lpk187 於 2016-8-31 09:05 編輯

回復 21# c_c_lai

jupyter和IDLE執行有點不同,jupyter是一段一段執行的,
執行某段必須繼承上一次的執行,否則會錯誤
而執行的結果,則是在某段的下面,Shift Enter 是對的

    [attach]25103[/attach]
作者: lpk187    時間: 2016-8-31 09:08

推薦使用 Anaconda 的 Python 版本, 因為這個版本幫你把許多套件 (尤其是科學計算、資料分析相關的) 都裝好了。

    https://www.continuum.io/downloads
作者: zyzzyva    時間: 2016-8-31 11:17

回復 21# c_c_lai
應該是因為程式本身沒有print out任何東西,可以看一下路徑下有沒有抓到檔案,或是在程式最下面加個print("test")試試看。
作者: c_c_lai    時間: 2016-8-31 11:22

回復 23# lpk187
謝謝你!我下載試試!
作者: c_c_lai    時間: 2016-8-31 11:23

回復 24# zyzzyva
我再來多TRY幾次試試!多謝你了!
作者: clianghot546    時間: 2016-9-2 10:23

請問若要指定日期下載該怎麼寫
作者: zyzzyva    時間: 2016-9-2 11:09

回復 27# clianghot546
有安裝python的話, 直接把前面日期的部份註解掉,自己給定就可以了,假設是要抓8/31的資料,就是像這樣:
  1. ##mydate = time.strftime("%Y/%m/%d")
  2. ##year = str(int(mydate[0:4])-1911)
  3. ##mydate2 = mydate.replace(mydate[0:4],year)

  4. mydate = "2016/8/31"
  5. mydate2 = "105/8/31"
複製代碼
如果是要能讓使用者輸入,可以用input。(或是用sys模組的argv[]取得cmd下的參數)
作者: clianghot546    時間: 2016-9-2 11:19

回復 28# zyzzyva
謝謝回覆,剛接觸PYTHON,馬上來測試一下。
作者: c_c_lai    時間: 2016-9-3 10:29

回復 28# zyzzyva
Python 3.4 版的要在哪裡下載? 我是用 3.5
但有些東西卡卡的。
作者: zyzzyva    時間: 2016-9-3 11:39

回復 30# c_c_lai
https://www.python.org/downloads/
3.x版的應該都大同小異,您再試試。
作者: c_c_lai    時間: 2016-9-3 12:34

回復 31# zyzzyva
謝謝你,下載了 3.4.5 試試。
作者: VBALearner    時間: 2016-9-4 00:27

回復 20# zyzzyva

感謝您的回答~
我正一步一步開始學^^
作者: moco5360    時間: 2016-9-6 18:31

我之前看過 有人在推P語言
最近才來這個論壇
看到你們討論的很熱烈
害我也跑去下載了Python

我目前有一個做法想用 EXCEL下載  法人資料
但是看到大大貼出這個語言的下載
是否會比較簡單可行呢?
還是,其實差不多?

因為目前還沒有真實操作過[下載資料]跟[整理資料]跟[刪除重複資料]
不知道大大在這方面有沒有什麼建議,可以建議我
該怎樣執行比較流暢?
流程根具體大概是怎樣
希望有大大可以回答我
讓我有一個絲路....
作者: zyzzyva    時間: 2016-9-7 10:49

回復 34# moco5360
應該要看你的需求:看你要下載的是什麼樣的資料,做什麼樣的整理,(刪除重複資料不太懂,是指如果重複下載要把多的刪掉還是原來的資料就有重複?)
vba抓資料我不太熟,沒辦法做比較,不過python在下載資料來說,我自己用起來是覺得還滿順手的。
如果資料量不多,就用python把資料抓下來,再用excel處理,如果資料多的話,可能還是要放到資料庫裡比較好。
作者: c_c_lai    時間: 2016-9-7 12:01

回復 35# zyzzyva
其實學習任何程式語言均有一通病,
在學習過程中大家都了解各個語法的使用,
但要將它們兜在一起應用於實務面時,卻往往又是另一回事。
有些人因而怯步不前,甚至棄之離去。
觀察其原因多因無實用的範例教學引導,充分之資訊提供。
好比我學習 Excel VBA 一開始我只是憑藉著有其它程式語言背景
撰寫基礎,進而從各位大大的提問中一步一步地探討、應用的。
如果大大能提列一些實用範例、需要套件,應留意事項等,
幫助大家提升領域那也是功德一件啊!
作者: zyzzyva    時間: 2016-9-7 12:35

回復 36# c_c_lai
其實我也都只是做簡單的應用,一個簡單的例子(抓取期貨外資交易口數以做為交易策略的參考):
網址:http://www.taifex.com.tw/chinese/3/7_12_3.asp
假設目標是抓取圖中紅圈的數字:[attach]25166[/attach]
固定的起手式大概就像這樣(bs4要另外安裝,還有一個也很好用的是lxml):
  1. import requests
  2. from bs4 import BeautifulSoup

  3. url = 'http://www.taifex.com.tw/chinese/3/7_12_3.asp'

  4. res = requests.get(url)

  5. soup = BeautifulSoup(res.text)

  6. tbl = soup.select('.table_f td')

  7. print(tbl[33].text)
複製代碼
因為使用了requests和bs4,只要簡短的幾行程式碼就可以達到我們的需求。
作者: c_c_lai    時間: 2016-9-7 15:10

回復 37# zyzzyva
[attach]25169[/attach]
作者: lpk187    時間: 2016-9-7 18:11

回復 38# c_c_lai


    soup = BeautifulSoup(res.text,"html.parser")
作者: zyzzyva    時間: 2016-9-7 18:15

回復 38# c_c_lai
那個訊息不影響執行,如果不想看到警告訊息只要像L大說的指定parser就可以了。把soup那段改成
soup = BeautifulSoup(res.text, "html. parser")
作者: c_c_lai    時間: 2016-9-7 18:35

本帖最後由 c_c_lai 於 2016-9-7 18:47 編輯

回復 39# lpk187
回復 40# zyzzyva
謝謝你!
請問 3714 代表筆數嗎?
如果要顯示 Get 後的網頁內容那該如何表達?
[attach]25171[/attach]
作者: zyzzyva    時間: 2016-9-7 21:19

本帖最後由 zyzzyva 於 2016-9-7 21:21 編輯

回復 41# c_c_lai
3714是今天外資的期貨多空交易淨口數,就是圖裡紅圈的地方。一般我是會直接寫到csv檔裡,這樣ts或mc就可以直接讀取。
[attach]25172[/attach]
如果要顯示抓取回來的完整網頁,只需要
  1. import requests

  2. url = 'http://www.taifex.com.tw/chinese/3/7_12_3.asp'

  3. res = requests.get(url)

  4. print(res.text)
複製代碼
BeautifulSoup那邊只是在做html碼的剖析,方便我們找到要的資料。
作者: lpk187    時間: 2016-9-7 23:26

回復 41# c_c_lai

    表格可以用 pandas 去抓詳細的指令可參照 http://pandas.pydata.org/pandas- ... tml#io-excel-writer
  1. import pandas as pd
  2. import io
  3. url = 'http://www.taifex.com.tw/chinese/3/7_12_3.asp'
  4. dfs = pd.read_html(url, index_col=0)
  5. data=dfs[3][0:][1:]
  6. data.to_excel('test.xlsx')
複製代碼
不過抓回來的表格有點錯亂,我也是剛開始學,別介意!
大家互相研究!   :$
作者: lpk187    時間: 2016-9-8 00:05

回復 41# c_c_lai

html比較多問題, 當你有html5lib / LXML解析器的問題
你可以下載它
pip install html5lib
easy_install lxml
作者: c_c_lai    時間: 2016-9-8 06:59

本帖最後由 c_c_lai 於 2016-9-8 07:08 編輯

回復 43# lpk187
謝謝你!
這是不是指 Pandas 套件尚未安裝?
請問下載Pandas套件後, 要如何加入Pandas 套件?
感覺上比 Excel VBA 還複雜呦。
[attach]25175[/attach]
作者: c_c_lai    時間: 2016-9-8 07:07

回復 42# zyzzyva
謝謝你!
執行完後出來的是網頁原始碼,
如國我想要的是如你上圖的結果值,
那又該如何處理?
我是在想了解 Python 它是如何來完成?
[attach]25176[/attach]
作者: c_c_lai    時間: 2016-9-8 07:20

回復  c_c_lai

html比較多問題, 當你有html5lib / LXML解析器的問題
你可以下載它
pip install html ...
lpk187 發表於 2016-9-8 00:05

不好意思 html5lib / LXML 要如何才能下載到?
下載後我是在安裝的 Python 3.5 的環境下 執行 pip install ?
但是目前我不識在該DOS 環境下執行程式,而是透過 Anaconda 的
Jupyter 環境下執行程式下,那又應該要如何運作?
不好意思一口氣提出這麼多的疑問,因無人教導自學的,
所以尚請多多包涵。再次向你說聲謝謝囉!
作者: lpk187    時間: 2016-9-8 09:13

本帖最後由 lpk187 於 2016-9-8 09:16 編輯

回復 47# c_c_lai

安裝模塊最好在DOS中安裝 ,其實在安裝Python時大多已寫入環境變數,但是最好還是在其版本下的Scripts資料夾安裝比較好
例如Anaconda3版本下:先進入cmd 進入DOS 後打入cd  C:\Anaconda3\Scripts    <<==依你實際資料夾為準
安裝前,先升級pip  語法:"pip install --upgrade pip"
pandas:pip install pandas
安裝pandas的同時它好像也會幫你安裝

html5lib也是pip:pip install html5lib ,若已經有安裝了,那就升級它 pip install -U html5lib -U是升級的意思 U 必須大寫

至於 lxml 大多已經安裝,但舊版本容易出錯,所以要先反安裝  conda remove lxml
lxml 用pip不好安裝,所以我是用 easy_install 安裝的  easy_install lxml

其他版本也是一樣需要到其目錄(Scripts)安裝比較妥當
作者: c_c_lai    時間: 2016-9-8 09:33

回復 48# lpk187
非常感謝,我來學著試試安裝看看,
我看了 Anaconda 的說明都沒提及,所以至今還是幼兒初級生,
慚愧慚愧!
那麼 Python 3.5 的環境下是否依需如同  Anaconda Script 一樣
需要執行 Pip 的套件來安裝升級?
作者: c_c_lai    時間: 2016-9-8 10:03

回復 48# lpk187
修正套件後,執行之畫面如下,看起來是 OK,
但卻沒看見 Test.xlsx 檔案?它會產生在哪裡?
這樣的畫面顯示是屬正確嗎?
謝謝你的指導!
[attach]25178[/attach]
作者: zyzzyva    時間: 2016-9-8 10:13

回復 46# c_c_lai
不太確定您想達到什麼樣的效果,如果只是要把所有的資料列出來可以用for迴圈,把print那邊改一下:
  1. for td in tbl:
  2.     print(td.text)
複製代碼
這樣可以簡單把我們取出的table裡的td的資料全部印出來。如果是要特定的格式,那就要另外處理。
作者: zyzzyva    時間: 2016-9-8 10:22

回復 50# c_c_lai
ipython的話可能會在C:\Users\登入中使用者底下,可以找找看。
作者: c_c_lai    時間: 2016-9-8 10:30

回復 51# zyzzyva
謝謝你!
我想求出如下之內容 (結果) (如圖示):
不知可行否,如此我也得以學到如何抓取網頁資料。
一窺 Python 是如何輕易能得知結果的。
[attach]25179[/attach]
作者: c_c_lai    時間: 2016-9-8 10:50

回復 51# zyzzyva
我想要的出來結果是:(如 下)
  1. Sub Ex()
  2.     Dim strURL$ '宣告strURL為變數
  3.     strURL = "http://www.taifex.com.tw/chinese/3/7_12_3.asp"    '定義strURL變數內容
  4.     [a1].CurrentRegion.ClearContents   '  清除文字沒清除格式(美化好的表格)
  5.    
  6.     With ActiveSheet.QueryTables.Add(Connection:= _
  7.                   "URL;" & strURL, Destination:=Range( _
  8.                   "$A$1"))
  9.         .Name = "期貨契約"
  10.         .FieldNames = True
  11.         .RowNumbers = False
  12.         .FillAdjacentFormulas = False
  13.         .PreserveFormatting = False
  14.         .RefreshOnFileOpen = False
  15.         .BackgroundQuery = False
  16.         .RefreshStyle = xlOverwriteCells
  17.         .AdjustColumnWidth = False
  18.         .WebSelectionType = xlSpecifiedTables
  19.         .WebFormatting = xlWebFormattingNone
  20.         .WebTables = "3"         '   第 3 個 Table
  21.         .WebPreFormattedTextToColumns = True
  22.         .WebConsecutiveDelimitersAsOne = True
  23.         .WebSingleBlockTextImport = False
  24.         .WebDisableDateRecognition = True
  25.         .WebDisableRedirections = False
  26.         .Refresh BackgroundQuery:=False
  27.         .Delete
  28.     End With
  29. End Sub
複製代碼
[attach]25180[/attach]
作者: lpk187    時間: 2016-9-8 10:53

回復 49# c_c_lai


    是的一樣進入到python3.5資料夾的Scripts資料夾進行 安裝  
若是在其他的資料夾或根目錄下安裝,比較會錯亂,其因是安裝多個版本的開係!
有時pip不能下載安裝可以嘗試其他安裝方法 例如用 easy_install 安裝或者參考 其模塊的官網說明
作者: c_c_lai    時間: 2016-9-8 10:56

本帖最後由 c_c_lai 於 2016-9-8 10:58 編輯

回復 52# zyzzyva
回復 43# lpk187
內容是?
[attach]25181[/attach]
作者: lpk187    時間: 2016-9-8 11:06

回復 50# c_c_lai


    所產生的檔案會在這個所儲存程式碼下的資料夾出現
以jupyter 來說一般都在"文件"資料中
[attach]25182[/attach]
作者: zyzzyva    時間: 2016-9-8 11:11

回復 54# c_c_lai
通常我都只需要網頁裡少數的幾個數字,所以也沒有認真研究過表格的完整抓取,這vba的code看起來已經很簡潔了,
跑出來的效果也很好,如果是要放到excel裡,我會直接用您的code。L大提的pandas可以達到類似的效果,但是像這種格式比較雜的還是要做調整,
再放到excel裡頭可能還沒有這個漂亮。
作者: c_c_lai    時間: 2016-9-8 11:26

本帖最後由 c_c_lai 於 2016-9-8 11:27 編輯

回復 57# lpk187
回復 58# zyzzyva
ipython 的話就如 zyzzyva 大大所說的,
會存在在 C:\Users\ 登入中使用者底下。
在此向你們學到了不少 Python 的有關知識,
這亦是前陣子我為何將 Python 停擺的緣故,
謝謝你們呦!
作者: c_c_lai    時間: 2016-9-8 12:18

回復 57# lpk187
回復 58# zyzzyva
應用 Pandas 試出結果了,
dfs[3][0:][1:] 的 [3] 即為指 "第三個 Table" 之意。
[attach]25185[/attach]
作者: zyzzyva    時間: 2016-9-10 21:55

前幾天c大回覆的時候有貼了vba的code,讓我想到如果找一些在excel版的問題用python試做看看,也許有興趣的朋友可以相互參照。
抓資料很多問題想起來不困難,但像我都只做簡單的應用,經驗有限,真要做比較完整的資料爬取,撞牆的細節問題想必非常多。
最近比較有時間,剛好趁這個機會練習一下。歡迎版上的朋友一起研究討論,如果有其他使用python的前輩,也請不吝給我一些提點跟建議。
一開始我想就從這篇開始http://forum.twbts.com/thread-18259-1-2.html
GBKEE版大已經用vba提供了很好的解決方案,但若是想換個口味還是可以用python試試看把資料爬取下來。

網址網址:http://church.oursweb.net/slocation.php?w=1&c=TW&a=&t=&p=
[attach]25207[/attach]
網頁看起來沒有什麼奇奇怪怪的javascript,如果只是要抓圖片中的簡易資料,那只要:
  1. #準備工具
  2. import requests
  3. from bs4 import BeautifulSoup

  4. #建立一個session
  5. s = requests.session()

  6. for i in range(11,14):
  7.     #網址變動的只有最後一個數字,共286頁,用range(1,287)就可以把所有數字跑過一次
  8.     #測試時請不要跑太多頁,用(1,3)、(11,14)、(280,283)之類的就好
  9.     url = 'http://church.oursweb.net/slocation.php?w=1&c=TW&a=&t=&p=' + str(i)
  10.     res = s.get(url)
  11.     #若收到的res文字為亂碼就加個encoding
  12.     res.encoding = 'utf-8'
  13.     soup = BeautifulSoup(res.text, 'lxml')
  14.         
  15.     #取得資料,我們要的資料都存在這兩種tr裡   
  16.     data = soup.find_all('tr',['tb__a', 'tb__b'])

  17.     #將資料印出
  18.     for d in data:
  19.         print(d.text)
  20.         
  21.     i += 1
複製代碼
那如果要收集詳細資料呢?那就要取得每頁裡的各個教會的連結,一個一個進去爬取。
作者: c_c_lai    時間: 2016-9-11 07:03

回復 61# zyzzyva
請教 print(d.text) 它會從哪裡顯示結果?
我按了 Shift Enter 後即石沉大海,謝謝你!
作者: zyzzyva    時間: 2016-9-11 08:04

本帖最後由 zyzzyva 於 2016-9-11 08:06 編輯

回復 62# c_c_lai
石沉大海...因為真的沒有資料XD
不知道為啥程式碼貼上的時候論壇系統會修改,下面這段
data = soup.find_all('tr',['tb__a', 'tb__b']),應該是
[attach]25208[/attach]
修改一下應該就正常了。
作者: c_c_lai    時間: 2016-9-11 08:31

回復 63# zyzzyva
感謝! 終於石榴開花了!
[attach]25209[/attach]
速度非常快, 再來多個好範例學習學習。
謝謝囉!
作者: zyzzyva    時間: 2016-9-11 08:42

本帖最後由 zyzzyva 於 2016-9-11 08:45 編輯

到這邊離GBKEE版大爬到的詳細資料還有相當距離。
我們的下一步應該是要取得頁面中各教會的連結:
  1. import requests
  2. from bs4 import BeautifulSoup

  3. s = requests.session()

  4. for i in range(11,13):
  5.     url = 'http://church.oursweb.net/slocation.php?w=1&c=TW&a=&t=&p=' + str(i)
  6.     res = s.get(url)
  7.     res.encoding = 'utf-8'
  8.     soup = BeautifulSoup(res.text, 'lxml')

  9. #--------下面改成這樣以取出頁面中各教會的連結
  10.     for d in soup.select('a[href^="church.php?pkey"]'):
  11.             myUrl = 'http://church.oursweb.net/' + d.get('href')
  12.             print(myUrl)    #先把連結印出來測試一下
  13.             #get_detail(myUrl,s) 之後用個function處理頁面中的資料
  14.     i += 1
複製代碼
再來就是要弄個function,看了一下網頁,這裡應該是比較麻煩的地方。
作者: zyzzyva    時間: 2016-9-11 08:43

回復 64# c_c_lai
這個我會做比較完整的,目標是像GBKEE版大抓下來的各教會的詳細資料。
作者: c_c_lai    時間: 2016-9-11 09:00

回復 66# zyzzyva
[attach]25210[/attach]
靜觀其變,先謝謝囉!
其實我個人也蠻希望如此窮追不捨地去尋根。
作者: zyzzyva    時間: 2016-9-11 10:38

本帖最後由 zyzzyva 於 2016-9-11 10:41 編輯

因為最後希望能輸出到csv(準備使用csv module的dictwriter,以key:value的方式寫入),所以要先把資料處理好。
試著直接把資料印出來
[attach]25211[/attach]
好像還可以。那試著把資料放到list裡看看
[attach]25212[/attach]
還真是醜,應該是因為全部的資料都在同一個td裡,中間又有空白、換行,實在不知道從何處理起。
[attach]25213[/attach]
換個方式先把字串取出來,順便把空白去掉,看起來好多了,是我能夠處理的資料了。
(這樣要多一個list,感覺有點繞路,應該有更好的處理方式,不過暫時沒想出來,先能work再說)
因為最後希望得到的是[ {dic1},{dic2},{'建檔 ID':'811223', '分類':'教育訓練' ,...}, {dic4}....]的格式,所以還有一些問題:
1、'回報資料錯誤 ' 不是我們要的,
2、'電郵'、'網址'等有中斷,實際資料跑到list的下一個元素去了。(其實還有宗派、母會,每個教會的資料有些許不同)
先準備幾個資料:一個空的字典(dictionary)、2個空的串列(list),這個要在function外面。
myDict = {}
myList = []
tmpList = []
  1. def get_detail(url, s):
  2.     print(url)
  3.     res = s.get(url)
  4.     res.encoding = 'utf-8'
  5.     soup = BeautifulSoup(res.text, 'lxml')
  6.     detail = soup.find_all('td', 'church_detail')
  7.     for ddd in detail[0].stripped_strings:
  8.         if '回報資料錯誤 >' in ddd:
  9.         #如果字串是 '回報資料錯誤 >',不動作,直接進入下一次迴圈
  10.             continue         
  11.         else:
  12.             tmpList.append(ddd)  #其他的都放進tmpList裡

  13.     for i, s in enumerate(tmpList):
  14.         if s == "":
  15.          #如果是空字串,不動作,直接進入下一次迴圈
  16.             continue         
  17.         elif any(x in s for x in ['電郵', '網址', '宗派', '母會']):
  18.          #如果是'電郵', '網址', '宗派', '母會'其中之一,將其去除':'後做為key值,tmpList的下一個元素做為value,新增至myDict
  19.             myDict[s.replace(':', '')] = tmpList[i+1]   
  20.         else:                                                                        
  21.             try:
  22.                 myDict[s.split(':')[0]] = s.split(':')[1]
  23.           #其他的以':'分割,前部做為key值,後部做為value,新增至myDict  
  24.             except:
  25.           #如果有例外,跳過不處理
  26.                 pass
  27.           #將myDict整個放到myList裡                                               
  28.     myList.append(myDict)
複製代碼
這樣get_detail應該就差不多完成了,下午有空再來測試一下。
作者: zyzzyva    時間: 2016-9-11 10:44

加了註解變得有點亂,附一個純code的。
  1. def get_detail(url, s):
  2.     print(url)
  3.     res = s.get(url)
  4.     res.encoding = 'utf-8'
  5.     soup = BeautifulSoup(res.text, 'lxml')
  6.     detail = soup.find_all('td', 'church_detail')
  7.     for ddd in detail[0].stripped_strings:
  8.         if '回報資料錯誤 >' in ddd:
  9.             continue
  10.         else:
  11.             tmpList.append(ddd)

  12.     for i, s in enumerate(tmpList):
  13.         if s == "":
  14.             continue
  15.         elif any(x in s for x in ['電郵', '網址', '宗派', '母會']):
  16.             myDict[s.replace(':', '')] = tmpList[i+1]
  17.         else:
  18.             try:
  19.                 myDict[s.split(':')[0]] = s.split(':')[1]
  20.             except:
  21.                 pass
  22.     myList.append(myDict)
複製代碼

作者: c_c_lai    時間: 2016-9-11 16:46

回復 69# zyzzyva
有錯誤訊息,如下:
[attach]25215[/attach]
作者: zyzzyva    時間: 2016-9-11 17:36

回復 70# c_c_lai
[attach]25216[/attach]
tmpList沒有定義。
要記得在function外面加上:
myDict = {}
myList = []
tmpList = []
然後那個print(myUrl)可以註解掉。
作者: c_c_lai    時間: 2016-9-11 17:42

回復 71# zyzzyva

[attach]25217[/attach]
作者: c_c_lai    時間: 2016-9-11 17:52

回復 71# zyzzyva
[attach]25218[/attach]
作者: zyzzyva    時間: 2016-9-11 17:59

回復 73# c_c_lai
跟get_detail放的位子也有關係(call function的時候python就會去找,如果還沒定義就會有問題)。
改了一個bug(之前會址沒處理到),加上輸出的部份。
目前的code我整理了一下,您用這個再測試看看。
  1. import requests
  2. from bs4 import BeautifulSoup
  3. import csv


  4. def get_detail(url, s):
  5.     print(url)
  6.     res = s.get(url)
  7.     res.encoding = 'utf-8'
  8.     soup = BeautifulSoup(res.text, 'lxml')
  9.     detail = soup.find_all('td', 'church_detail')
  10.     for ddd in detail[0].stripped_strings:
  11.         if '回報資料錯誤 >' in ddd:
  12.             continue
  13.         else:
  14.             tmpList.append(ddd)

  15.     for i, s in enumerate(tmpList):
  16.         if s == "":
  17.             continue
  18.         elif any(x in s for x in ['電郵', '網址', '宗派', '母會']):
  19.             myDict[s.replace(':', '')] = tmpList[i+1]
  20.         elif '會址' in s:
  21.             myDict[s.split(':')[0]] = (s.split(':')[1] + tmpList[i+1])
  22.         else:
  23.             try:
  24.                 myDict[s.split(':')[0]] = s.split(':')[1]
  25.             except:
  26.                 pass
  27.     myList.append(myDict)


  28. myDict = {}
  29. myList = []
  30. tmpList = []
  31. s = requests.session()

  32. for i in range(1, 2):
  33.     url = 'http://church.oursweb.net/slocation.php?w=1&c=TW&a=&t=&p=' + str(i)
  34.     res = s.get(url)
  35.     res.encoding = 'utf-8'
  36.     soup = BeautifulSoup(res.text, 'lxml')

  37.     for d in soup.select('a[href^="church.php?pkey"]'):
  38.         myUrl = 'http://church.oursweb.net/' + d.get('href')
  39.         get_detail(myUrl,s)
  40.         myDict = {}

  41.     i += 1

  42. with open('gospel2.csv', 'a', new='', encoding='utf-8') as f:
  43.         fieldnames = ['建檔 ID', '中文名稱', '英文名稱', '分類', '宗派', '母會', '網址', '國別區域', '設立時間', '負責人', '電話', '傳真', '電郵', '會址', '通訊處']
  44.         w = csv.DictWriter(f, fieldnames)
  45.         w.writeheader()
  46.         w.writerows(myList)
複製代碼

作者: c_c_lai    時間: 2016-9-11 18:08

回復 74# zyzzyva
[attach]25219[/attach]
作者: zyzzyva    時間: 2016-9-11 18:24

回復 75# c_c_lai
跟早上一樣的問題,不知道是bug還是有特殊原因,論壇不能輸入「線」的英文。
[attach]25220[/attach]
這邊改一下應該就可以了。
作者: c_c_lai    時間: 2016-9-11 18:40

本帖最後由 c_c_lai 於 2016-9-11 18:42 編輯

回復 76# zyzzyva
[attach]25221[/attach]
謝謝你用心的指導!
作者: zyzzyva    時間: 2016-9-11 18:44

本帖最後由 zyzzyva 於 2016-9-11 18:45 編輯

回復 77# c_c_lai
這樣應該是有work了,用excel開看看,如果是亂碼要用筆記本開起來存檔一下再重開。
作者: c_c_lai    時間: 2016-9-11 18:55

回復 78# zyzzyva
筆記本內亦是一堆亂碼,有沒有辦法存檔時轉成 Big5 碼之類
如 Unicode 等,否則每次都需另找 NotePad++ 等工具轉碼
實在太麻煩了。
作者: zyzzyva    時間: 2016-9-11 19:08

回復 79# c_c_lai
怪怪,我的可以說,您的在ipython裡可以顯示可是用筆記本開反而不行?
編碼的問題我也一直很頭痛,會用utf-8是因為資料裡有一些不是big5,像「平瀬義樹 牧師」的「瀬」。
在最後with open那邊的encoding改成encoding='utf-8-sig'試試看。
作者: c_c_lai    時間: 2016-9-11 19:18

回復 80# zyzzyva
[attach]25222[/attach]
作者: zyzzyva    時間: 2016-9-11 19:26

回復 81# c_c_lai
[attach]25223[/attach]
我的是能正常顯示,可能是系統還是那邊的問題,有點事得出門,明天再找別台電腦測看看。
作者: c_c_lai    時間: 2016-9-12 04:29

回復 82# zyzzyva
下載後必須先行檢視『筆記本』之下載內容,如為亂碼則刪除再重新
執行一次,如此反複,如為正體則將它先行儲存一次,然後才去做
開啟 Excel 動作。 反之『筆記本』之下載內容如不先行儲存一次,
開啟之  Excel (CSV) 檔內容依然為亂碼。(............xDx)
[attach]25224[/attach]
作者: c_c_lai    時間: 2016-9-12 08:38

回復 55# lpk187
你對 #61 的案例有否看法? 如果改成使用 pandas 套件不知可行否?
我發現 Python 範圍還蠻廣的,你們的程式應用還真促成我對它的興趣,
謝謝你!
作者: clianghot546    時間: 2016-9-12 09:07

回復 32# c_c_lai
可參考 使用python(x,y)
作者: lpk187    時間: 2016-9-12 09:18

回復 84# c_c_lai

我和你一樣也只是初學Python ,對於Python也尚在研究之中,
昨天看到你和zyzzyva大大研究這篇倒也是引發我很大的興趣!
其實我對 pandas 認識也不深,也僅是剛好看到 pandas 可以製作表格 參考網址
其他的可不太懂的, HTML 代碼。對我來說,可是處在完全不懂啊!唉!
對Beautiful Soup 4,呃!也是看得花花的 ,參考網址
一起加油吧!
作者: c_c_lai    時間: 2016-9-12 09:30

回復 85# clianghot546
Python(x,y) is a free scientific and engineering development software for numerical computations, data analysis and data visualization based on Python programming language. 它對股市數據的分析圖表非常好用;
而目前的案例是非數值之資料錄數據,謝謝妳!
也歡迎你一同討論!
作者: c_c_lai    時間: 2016-9-12 09:32

回復 86# lpk187
你也是我的 Python 啟蒙老師呦!
一起加油吧!
作者: zyzzyva    時間: 2016-9-12 09:43

回復 83# c_c_lai
後面那段我能理解,是excel讀取csv預設編碼的問題,2007以後的版本應該寫入BOM(byte of mark)可以解決。
之前在encoding=utf-8後面加上sig就是加上BOM,不知道為什麼在2010不行。您有空的話再試試看把他改回去utf-8,
然後在下面加一行「f.write('\ufeff')」手動寫入試試看。
前面那段的問題我實在想不出原因,抓下來的資料在筆記本裡有時正常有時亂碼?
有沒有辦法複製錯誤?確認是不是特定情況或是頁面會出現亂碼的問題,這樣比較有個方向。
pandas就我所知主要用在後段的資料分析,準備資料通常應該還是需要其他工具輔助。
作者: c_c_lai    時間: 2016-9-12 10:15

本帖最後由 c_c_lai 於 2016-9-12 10:17 編輯

回復 89# zyzzyva
加上         f.write('\ufeff') 後,
一切即恢復平靜 (正常的不得了),這招還真管用呢!
謝謝囉!(執行前即先將 CSV 檔案移除,而後即從兩方面進行觀察,均不予以儲存條件下)
再來一個實用範例,那我的 Python 學習應將開始起步了!
  1. with open('gospel2.csv', 'a', new='', encoding='utf-8') as f:
  2.         fieldnames = ['建檔 ID', '中文名稱', '英文名稱', '分類', '宗派', '母會', '網址', '國別區域', '設立時間', '負責人', '電話', '傳真', '電郵', '會址', '通訊處']
  3.         f.write('\ufeff')
  4.         w = csv.DictWriter(f, fieldnames)
  5.         w.writeheader()
  6.         w.writerows(myList)
  7.         print('gospel2.csv 檔案儲存完畢!')
複製代碼

作者: zyzzyva    時間: 2016-9-12 11:30

回復 90# c_c_lai
太好了!如果這樣也不行就頭痛了。
原文中有提到希望可以用縣市為單位來抓。因為網站本身就有提供縣市別分類的連結,如:
http://church.oursweb.net/slocation.php?w=1&c=TW&a=台中市&t=
其實只要把連結換一下,總頁數改一下用現有的 code就可以把該區域的資料抓下來了。
但如果要讓使用者選擇呢?假設我們已經依使用者選擇進入該分區的頁面,但是要如何決定總頁數呢?
以台中市來說。[attach]25225[/attach],能把圖裡藍圈中的31抓出來嗎?
作者: c_c_lai    時間: 2016-9-12 11:50

回復 91# zyzzyva
現在談功力還差太遠了(初淺),還無法駕馭尚請指導,
努力學習中,我幾乎將近有半年多未曾接觸 Python,
應用方面還尚未完全上手,正好碰上你們才使我重拾信心。
(前半個月才動完眼睛手術) 真有麻煩你指教了!
作者: zyzzyva    時間: 2016-9-12 12:32

回復 92# c_c_lai
說指導不敢當,我也是趁這個機會一邊做一邊學。
其實好不好抓跟網頁的html編排有很大的關係,會提這個數字是因為我自己試了覺得這個數字還有點小麻煩。
[attach]25226[/attach]
您如果是用chrome,可以在想抓取的資料上按右鍵,選「檢查」,應該可以看到類似圖中的畫面(有時候需要點開樹狀結構)。
以這個結構來說,除了上面table的class="tb_pages",我沒有看到什麼容易用的東西,所以我會選這個table做為起始的參考點。
(通常找到目標的方式都會有非常多種,只要能找得到就好了),用下面的code就可以找到整個句子:
  1. url = 'http://church.oursweb.net/slocation.php?w=1&c=TW&a=台中市&t='

  2. res = requests.get(url)

  3. res.encoding='utf-8'

  4. soup = BeautifulSoup(res.text, 'lxml')

  5. target = soup.select('.tb_pages td')[0].text

  6. print(target)
複製代碼
但是數字還是藏在裡頭,真是有點煩人。
到這邊我是再用regular expression把它取出來。
  1. import re
  2. total_num = re.search(r'/\s\d{1,3}', target).group().replace('/ ','')
  3. print(total_num)
複製代碼
另一個比較簡單的方式則是用lxml。
作者: zyzzyva    時間: 2016-9-12 13:22

剛想了一下,以這個頁面來說,其實也不用用到BeautifulSoup,直接用re就可以了。
  1. import requests
  2. import re

  3. url = 'http://church.oursweb.net/slocation.php?w=1&c=TW&a=台中市&t='

  4. res = requests.get(url)

  5. total_num = re.findall(r'/\s\d{1,3}', res.text)[0].replace('/ ','')

  6. print(total_num)
複製代碼

作者: clianghot546    時間: 2016-9-12 13:39

想請問各位都是用python抓取完網路資料後再透過excel整理,還是可以用python一次處理到最後所要的結果。
作者: c_c_lai    時間: 2016-9-12 16:02

本帖最後由 c_c_lai 於 2016-9-12 16:22 編輯

回復 94# zyzzyva
Python 詮釋的實在太美了,簡潔扼要。
請問 r'/\s\d{1,3} 代表之涵義為何?
BeautifulSoup 一定是搭配 'lxml' 使用?
soup.select('.tb_pages td')[0] 其中的 [0]  指的是?
它能直接應用 regular expression 把它取出來實在是太厲害了。
#94 它怎麼知道要抓的是總頁數?
作者: zyzzyva    時間: 2016-9-12 17:11

回復 95# clianghot546
要看你是要什麼樣的結果。需要做那些處理。如果要做一些一般的運算我都還是會放到excel裡。
雖然理論上python也有很多套件可以做各種分析,不過一般使用來說,我還是覺得excel的工作表跟儲存格比較親切。
作者: zyzzyva    時間: 2016-9-12 17:33

回復 96# c_c_lai
r'/\s\d{1,3}':字串前面加上r是表示raw string,就是通知python不要理會特殊字元,照字串原本的樣子代進去re module。
後面就是re的表示,以「總共 5704 筆資料 《《上一頁 頁次 1 / 286 下一頁》》」來說, 「/」就是在兩個數字(1、286)之間
「/」之後有一個空白(在re裡就是「\s」,後面「\d」表示數字,「{1,3}」表示有1~3個前面的東西(以這裡來說就是「\d」。
BeautifulSoup不一定要用lxml做為parser,網頁如果結構良好,用那種差別其實不大(lxml速度可能好一些)。
可以參考https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id49
soup.select('.tb_pages td')返回的是一個list,list[0]就是list的第一個元素的意思。
regular expression的速度滿好的,應該各語言都有相應的模組,不過我比較少用,一個是不熟,一個是pattern比較廣的時候,怕會比對到意料外的資料。
python不會知道那是總頁數,還是要靠人觀察,python只能知道某個位子(或符合re pattern)的數字是什麼。
作者: c_c_lai    時間: 2016-9-12 18:09

回復 98# zyzzyva
非常感謝你的詳細說明。
手頭上有一現成的 Excel 範例,我將其日期訂為 105年09月08日,
應用 IE 物件去抓取該日的 "信用交易統計"。我非常希望能藉由此範例
使用 Python 來達成,一方面增長智慧、另一方面得以增進 Python 的學習,
及進一步之了解與應用。先行謝謝你囉!
  1. Sub 信用交易統計()
  2.     Dim i As Integer, j As Integer
  3.     Dim ie As Object, E As Object, Sh As Worksheet
  4.         
  5.     Set ie = CreateObject("InternetExplorer.Application")
  6.    
  7.     With ie
  8.         .Visible = True
  9.         .navigate "http://www.twse.com.tw/ch/trading/exchange/MI_MARGN/MI_MARGN.php"
  10.         
  11.         Do While .Busy Or .readyState <> 4: DoEvents: Loop
  12.         
  13.         .document.getElementById("date-field").Value = Format("2016/9/8", "EE/MM/DD")    '  填入
  14.                  
  15.         .document.all("selectType").SelectedIndex = 1      '   1 全部; 7 水泥工業; 8 食品工業
  16.         .document.all("query-button").Click
  17.         
  18.         Do While .Busy Or .readyState <> 4: DoEvents: Loop
  19.         
  20.         '  Set Sh = ActiveSheet
  21.         Set Sh = Sheets("信用交易統計")                     '  工作表單名稱
  22.         Sh.UsedRange.Clear
  23.         '  Sh.[A:A].NumberFormatLocal = "G/通用格式"        '  解決 "0050"  ->  "50" (不理想)
  24.         '  Sh.[A:A].NumberFormatLocal = "@"                 '  解決 "0050"  ->  "50" (左上角會有三角形)
  25.         
  26.         i = 0
  27.         With .document
  28.             For Each E In .all.tags("table")(3).Rows
  29.                 i = i + 1 '
  30.                 For j = 0 To E.Cells.Length - 1
  31.                     If j = 0 And Left(E.Cells(j).innerText, 1) = "0" Then    '  改以 .Formula 的方式處理
  32.                         Sh.Cells(i, j + 1).Formula = "=""" & E.Cells(j).innerText & """"
  33.                     Else
  34.                         Sh.Cells(i, j + 1) = E.Cells(j).innerText
  35.                     End If
  36.                 Next
  37.             Next
  38.             
  39.             i = i + 1         '  間隔出一空白行,易於上下區隔辨識
  40.             For Each E In .all.tags("table")(4).Rows
  41.                 i = i + 1 '
  42.                 For j = 0 To E.Cells.Length - 1
  43.                     If j = 0 And Left(E.Cells(j).innerText, 1) = "0" Then
  44.                         Sh.Cells(i, j + 1).Formula = "=""" & E.Cells(j).innerText & """"
  45.                     Else
  46.                         Sh.Cells(i, j + 1) = E.Cells(j).innerText
  47.                     End If
  48.                 Next
  49.             Next
  50.         End With
  51.         
  52.         .Quit
  53.         With Sh
  54.             .[A:A].HorizontalAlignment = xlLeft           '  A 欄值全數靠左
  55.             .Select
  56.         End With
  57.     End With
  58. End Sub
複製代碼
[attach]25228[/attach]
[attach]25229[/attach]
作者: zyzzyva    時間: 2016-9-12 19:03

回復 99# c_c_lai
這個有提供csv下載阿,用我們這個討論串開頭的方式直接抓csv應該是最快的。
  1. import requests

  2. headers = {"User-Agent":"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"}
  3.            
  4. url = 'http://www.twse.com.tw/ch/trading/exchange/MI_MARGN/MI_MARGN.php'

  5. payload={'download':'csv',
  6.         'qdate':'105/09/07',
  7.         'selectType':'ALL'}

  8. res = requests.post(url, headers=headers, data=payload, stream=True)

  9. with open('test.csv', 'wb',) as f:
  10.     for chunk in res.iter_content(1024):
  11.         f.write(chunk)
複製代碼





歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)