返回列表 上一主題 發帖

[原創] python上市櫃三大法人買賣超日報資料下載

回復 103# koshi0413
謝謝你!
我好好地來研究一下。BS(res.text) 我修改成 BS(res.text, 'lxml')
最後之 print( ... ) (因我的版本是 3.5) 我再想想看有沒有更佳的表達處理。
請教 soup.select('table')[1] 為何是 [1]? soup.select('tr')[3:] 的 [3:] 指的又是?
Python 我算是幼兒生,還得向你們請益了。 謝謝囉!

TOP

本帖最後由 koshi0413 於 2016-9-12 20:33 編輯

小弟我終於可以回覆了,感動!!
這文章我追很久了 python 也是看到這篇才開始學的,
在此論壇學了不少vba  也看了些c_c_lai 學到不少,剛好看到c_c_lai有提問,來報答一下
下面為 c_c_lai  之需求,下載csv很方便,也很快!!!  但匯入 SQL麻煩,要在轉碼,故小弟會選擇直接提取(其實是還不會用python直接轉csv碼在自動匯入SQL)
ps:代碼為zyzzyva修改版
pps:源碼中段落有 # 皆為提取網頁時,反覆實驗用,這網頁為了提取所而段落也花了一小時來試各種網頁代碼來用BeautifulSoup提取
  1. # -*- coding: utf-8 -*-
  2. import requests
  3. import time
  4. import os
  5. from bs4 import BeautifulSoup as BS
  6. from datetime import date

  7. headers = {"User-Agent":"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"}
  8. url1 = "等級不夠,網址請自行輸入"
  9. payload = {"download":'',
  10.             "qdate":'105/09/10',
  11.             "selectType":"ALL"}
  12. res = requests.post(url1, headers=headers, data=payload)
  13. #print res.text

  14. soup = BS(res.text)
  15. #print soup.select('.board_trad')[0].text
  16. #tb = soup.select('#main-content')
  17. #print tb
  18. #tb = soup.findAll('table')
  19. soup = soup.select('table')[1]
  20. #print tb
  21. for ta in soup.select('tr')[3:]:
  22.     print ta.select("td")[0].text,ta.select("td")[1].text,ta.select("td")[2].text,ta.select("td")[3].text,ta.select("td")[4].text,ta.select("td")[5].text,ta.select("td")[6].text,ta.select("td")[7].text,ta.select("td")[8].text,ta.select("td")[9].text,ta.select("td")[10].text,ta.select("td")[11].text,ta.select("td")[12].text,ta.select("td")[13].text,ta.select("td")[14].text
複製代碼
這是結果。只po前幾段
0050   元大台灣50       194 104 0 1,056 1,146 194,125 0 5 0 496 501 194,125 19
0051   元大中型100      0 0 0 2 2 4,500 0 0 0 0 0 4,500 0
0052   FB科技           0 0 0 0 0 2,000 0 0 0 0 0 2,000 0
0053   元大電子         0 0 0 0 0 3,247 0 0 0 0 0 3,247 0
0054   元大台商50       0 0 0 0 0 4,656 0 0 0 0 0 4,656 0
0055   元大MSCI金融     20 5 0 622 637 17,163 0 4 0 118 122 17,163 0
0056   元大高股息       7 1 0 94 100 67,508 4 0 0 25 21 67,508 3
0057   FB摩台           0 0 0 0 0 2,006 0 0 0 0 0 2,006 0
0058   FB發達           0 0 0 0 0 1,299 0 0 0 0 0 1,299 0

TOP

回復 100# zyzzyva
假設不存成 csv,而一一顯示又會是如何處哩,
直截使用 res,好像無動作。(愈來愈喜愛 Python 了)
謝謝囉!

TOP

回復 100# zyzzyva
難怪大家會來使用 Python,光是看其執行能力就足矣。
原來是那麼地簡潔、扼要,又學到了,謝謝你的不吝指導!

TOP

回復 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)
複製代碼

TOP

回復 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
複製代碼
信用交易統計.rar (51.88 KB)

TOP

回復 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)的數字是什麼。

TOP

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

TOP

本帖最後由 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 它怎麼知道要抓的是總頁數?

TOP

想請問各位都是用python抓取完網路資料後再透過excel整理,還是可以用python一次處理到最後所要的結果。

TOP

        靜思自在 : 一句溫暖的話,就像往別人身上灑香水,自己會沾到兩三滴。
返回列表 上一主題