利用Python實(shí)現(xiàn)批量下載上市公司財(cái)務(wù)報(bào)表
導(dǎo)語(yǔ)
用VBA做了個(gè)小工具,可以批量把某網(wǎng)站上的上市公司的財(cái)報(bào)下下來(lái)。
制作思路非常簡(jiǎn)單:
1、從該網(wǎng)站上的下載鏈接中找到規(guī)律:都是一段@#¥%……&開(kāi)頭加上想要下載的報(bào)表類型(BS,ER,SCF),加上會(huì)計(jì)期間(按年度、按報(bào)告期、按季度),再加上上市公司代碼。
2、然后用Excel表格排列組合生成那些下載鏈接,并訪問(wèn)。這里沒(méi)有直接用get/post,因?yàn)闀?huì)被網(wǎng)站識(shí)別出來(lái)并拒絕訪問(wèn),下載下來(lái)的文件就是空的。然后我就用了個(gè)比較笨的辦法,調(diào)用IE去訪問(wèn)這些網(wǎng)址,然后用VBA的Sendkeys方法模擬手工點(diǎn)擊下載按鈕。
運(yùn)行之后沒(méi)有被block掉,可行
感覺(jué)像是在用手榴彈炸直升機(jī),而且用VBA有個(gè)很大的缺陷:如果IE不能正確地出現(xiàn)在桌面的最前臺(tái)(比如微信突然彈出個(gè)消息……),這樣會(huì)導(dǎo)致application.sendkeys方法失效。
這里用Python再做一個(gè),但還是避免不了要借用一下VBA里面的一些功能……
思路和上面是一樣的,根據(jù)網(wǎng)站規(guī)則組裝好下載鏈接后調(diào)用IE去下載。
不一樣的是,這次沒(méi)有模擬快捷鍵,而是用pyautogui的圖像識(shí)別功能去調(diào)用鼠標(biāo)點(diǎn)擊下載按鈕。用這種方法的好處是不容易被彈窗打斷,命中率更高。
Python代碼:
""" 運(yùn)行前提 1、確保“從THS批量下載上市公司財(cái)報(bào).py”、“從THS批量下載上市公司財(cái)報(bào).xlsm”、“capture.png”三個(gè)文件存放在同一目錄下 2、確保安裝了以下幾個(gè)第三方庫(kù):pyautogui、pywin32、pandas、xlwings 3、確保把IE的默認(rèn)下載路徑改成本文件所在目錄 4、下載后立即最小化運(yùn)行窗口,避免遮擋屏幕導(dǎo)致pyautogui無(wú)法定位圖像位置 沒(méi)有安裝的話可以在命令提示符里面輸入“pip install 庫(kù)名”進(jìn)行安裝: pip install pyautogui pip install pywin32 pip install pandas pip install xlwings """ import pyautogui from win32com.client import DispatchEx import pandas import xlwings import time import os # 同花順網(wǎng)站下載{鏈接的固定字段:文件名固定字段} ref = {'main&type=report': 'main_report.xls', 'main&type=year': 'main_year.xls', 'main&type=simple': 'main_simple.xls', 'debt&type=report': 'debt_report.xls', 'debt&type=year': 'debt_year.xls', 'benefit&type=report': 'benefit_report.xls', 'benefit&type=year': 'benefit_year.xls', 'benefit&type=simple': 'benefit_simple.xls', 'cash&type=report': 'cash_report.xls', 'cash&type=year': 'cash_year.xls', 'cash&type=simple': 'cash_simple.xls'} df = pandas.read_excel(r'./從THS批量下載上市公司財(cái)報(bào).xlsm', sheet_name='Main', dtype='str', header=0) # 把表格中不足6位的公司代碼補(bǔ)全成6位,比如把'2'補(bǔ)全成'000002' df['公司代碼'] = df['公司代碼'].apply(lambda x: str('000000')[:(6 - len(x))] + str(x)) # 創(chuàng)建一個(gè){下載文件名:下載鏈接}的字典 urls = {} for i in ref.keys(): for j in df['公司代碼']: # 如果原來(lái)下載過(guò)就略過(guò)以節(jié)約時(shí)間 if not os.path.exists(f'{j}_{ref[i]}'): urls[f'{j}_{ref[i]}'] = str(f'http://basic.10jqka.com.cn/api/stock/export.php?export={i}&code={j}') wb = xlwings.App(visible=False, add_book=False).books.open(r'./從THS批量下載上市公司財(cái)報(bào).xlsm') # 這里用Excel宏的一個(gè)退出IE功能,比win32com的功能更好用 # 也是因?yàn)楸救思夹g(shù)太渣,不知道怎么用Python完全退出IE # QuitIE的宏代碼在后面 QuitIE = wb.macro('QuitIE') # 這里用Excel宏的XMLHTTP功能,下載效率更高 # XMLHTTP的宏代碼在后面 XMLHTTP = wb.macro('XMLHTTP') # IE瀏覽器下載button的截圖 img = r'./capture.png' def IEDownload(url): ie = DispatchEx('InternetExplorer.Application') ie.Navigate(url) # 最多嘗試查找5次,避免死循環(huán) times = 0 while times < 5: location = pyautogui.locateCenterOnScreen(img, confidence=0.9) if location is not None: pyautogui.click(location.x, location.y, clicks=1, button='left', duration=0.01, interval=0.01) break times += 1 windows = 0 for filename in urls: # 每7次調(diào)用一次xmlhttp,膽子大可以把這個(gè)值設(shè)小點(diǎn) if windows % 7 == 0: XMLHTTP(filename, urls[filename]) if not os.path.exists(f'./{filename}'): IEDownload(urls[filename]) windows += 1 else: IEDownload(urls[filename]) windows += 1 # 每7次關(guān)閉IE的所有窗口,釋放內(nèi)存 if windows % 7 == 0: time.sleep(0.05) QuitIE() time.sleep(0.05) QuitIE() wb.close() xlwings.App().quit() # 以下是可選功能,把xls格式的文件轉(zhuǎn)成最新的xlsx格式 # if not os.path.exists('./xlsx格式文件'): # os.mkdir('./xlsx格式文件') # for i in os.listdir('.'): # if not os.path.exists(f'./xlsx格式文件/{i}x') and i.endswith('xls'): # df=pandas.read_excel(f'./{i}',header=1,index_col=0) # df.to_excel(f'./xlsx格式文件/{i}x')
QuitIE宏代碼:
Sub QuitIE()
Dim winmgmts As Object
Dim ieprc As Object
Dim ieprcs As Object
Set winmgmts = GetObject("winmgmts://.")
Set ieprcs = winmgmts.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'iexplore.exe'")
For Each ieprc In ieprcs
On Error Resume Next
Call ieprc.Terminate
Next
Set ieprcs = Nothing
Set winmgmts = Nothing
End Sub
XMLHTTP宏代碼:
'傳進(jìn)來(lái)的兩個(gè)參數(shù)分別是文件名和下載鏈接
Sub XMLHTTP(FileName, url)
Dim h, s, fpath
fpath = ThisWorkbook.Path & "\"
'先判斷下文件是不是已經(jīng)下載過(guò)了
If Dir(fpath & FileName) = "" Then
Set h = CreateObject("Microsoft.XMLHTTP")
h.Open "GET", url, False '網(wǎng)絡(luò)中的文件URL
h.send
Set s = CreateObject("ADODB.Stream")
s.Type = 1
s.Open
s.write h.responseBody
s.savetofile fpath & FileName, 2 '本地保存文件名
s.Close
'萬(wàn)一被網(wǎng)站反爬了下載下來(lái)的就是空文件,刪掉
If FileLen(fpath & FileName) < 600 Then
Kill fpath & FileName
End If
End If
End Sub
以上就是利用Python實(shí)現(xiàn)批量下載上市公司財(cái)務(wù)報(bào)表的詳細(xì)內(nèi)容,更多關(guān)于Python下載報(bào)表的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
安裝python依賴包psycopg2來(lái)調(diào)用postgresql的操作
這篇文章主要介紹了安裝python依賴包psycopg2來(lái)調(diào)用postgresql的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01

淺談Python3.10 和 Python3.9 之間的差異

Python matplotlib 繪制雙Y軸曲線圖的示例代碼

python opencv 讀取圖片 返回圖片某像素點(diǎn)的b,g,r值的實(shí)現(xiàn)方法