設為首頁收藏本站

艾歐踢論壇

 找回密碼
 立即註冊

QQ登錄

只需一步,快速開始

搜索
熱搜: 活動 交友 discuz
查看: 364|回復: 0
打印 上一主題 下一主題

twstock stock.py change rand sleep time to 3-10 sec for request

[複製鏈接]
跳轉到指定樓層
樓主
發表於 2023-3-24 14:12:17 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
stock.py   change rand sleep time to 3-10 sec for request to avoid ban

tock.py source as below:
twstock/stock.py#L57 的下一行
for 迴圈裏面 增加 以下兩行 code 即可import time
import random
  1. # -*- coding: utf-8 -*-

  2. import datetime
  3. import time
  4. import urllib.parse
  5. from collections import namedtuple
  6. import random
  7. from twstock.proxy import get_proxies

  8. try:
  9.     from json.decoder import JSONDecodeError
  10. except ImportError:
  11.     JSONDecodeError = ValueError

  12. import requests

  13. try:
  14.     from . import analytics
  15.     from .codes import codes
  16. except ImportError as e:
  17.     if e.name == 'lxml':
  18.         # Fix #69
  19.         raise e
  20.     import analytics
  21.     from codes import codes


  22. TWSE_BASE_URL = 'http://www.twse.com.tw/'
  23. TPEX_BASE_URL = 'http://www.tpex.org.tw/'
  24. DATATUPLE = namedtuple('Data', ['date', 'capacity', 'turnover', 'open',
  25.                                 'high', 'low', 'close', 'change', 'transaction'])


  26. class BaseFetcher(object):
  27.     def fetch(self, year, month, sid, retry):
  28.         pass

  29.     def _convert_date(self, date):
  30.         """Convert '106/05/01' to '2017/05/01'"""
  31.         return '/'.join([str(int(date.split('/')[0]) + 1911)] + date.split('/')[1:])

  32.     def _make_datatuple(self, data):
  33.         pass

  34.     def purify(self, original_data):
  35.         pass

  36. class TWSEFetcher(BaseFetcher):
  37.     REPORT_URL = urllib.parse.urljoin(
  38.         TWSE_BASE_URL, 'exchangeReport/STOCK_DAY')

  39.     def __init__(self):
  40.         pass

  41.     def fetch(self, year: int, month: int, sid: str, retry: int=5):
  42.         params = {'date': '%d%02d01' % (year, month), 'stockNo': sid}
  43.         for retry_i in range(retry):
  44.             randNum = random.randrange(3,10)
  45.             time.sleep(randNum)
  46.             r = requests.get(self.REPORT_URL, params=params,
  47.                              proxies=get_proxies())
  48.             try:
  49.                 data = r.json()
  50.             except JSONDecodeError:
  51.                 continue
  52.             else:
  53.                 break
  54.         else:
  55.             # Fail in all retries
  56.             data = {'stat': '', 'data': []}

  57.         if data['stat'] == 'OK':
  58.             data['data'] = self.purify(data)
  59.         else:
  60.             data['data'] = []
  61.         return data

  62.     def _make_datatuple(self, data):
  63.         data[0] = datetime.datetime.strptime(
  64.             self._convert_date(data[0]), '%Y/%m/%d')
  65.         data[1] = int(data[1].replace(',', ''))
  66.         data[2] = int(data[2].replace(',', ''))
  67.         data[3] = None if data[3] == '--' else float(data[3].replace(',', ''))
  68.         data[4] = None if data[4] == '--' else float(data[4].replace(',', ''))
  69.         data[5] = None if data[5] == '--' else float(data[5].replace(',', ''))
  70.         data[6] = None if data[6] == '--' else float(data[6].replace(',', ''))
  71.         # +/-/X表示漲/跌/不比價
  72.         data[7] = float(0.0 if data[7].replace(',', '') ==
  73.                         'X0.00' else data[7].replace(',', ''))
  74.         data[8] = int(data[8].replace(',', ''))
  75.         return DATATUPLE(*data)

  76.     def purify(self, original_data):
  77.         return [self._make_datatuple(d) for d in original_data['data']]


  78. class TPEXFetcher(BaseFetcher):
  79.     REPORT_URL = urllib.parse.urljoin(TPEX_BASE_URL,
  80.                                       'web/stock/aftertrading/daily_trading_info/st43_result.php')

  81.     def __init__(self):
  82.         pass

  83.     def fetch(self, year: int, month: int, sid: str, retry: int=5):
  84.         params = {'d': '%d/%d' % (year - 1911, month), 'stkno': sid}
  85.         for retry_i in range(retry):
  86.             r = requests.get(self.REPORT_URL, params=params,
  87.                              proxies=get_proxies())
  88.             try:
  89.                 data = r.json()
  90.             except JSONDecodeError:
  91.                 continue
  92.             else:
  93.                 break
  94.         else:
  95.             # Fail in all retries
  96.             data = {'aaData': []}

  97.         data['data'] = []
  98.         if data['aaData']:
  99.             data['data'] = self.purify(data)
  100.         return data

  101.     def _convert_date(self, date):
  102.         """Convert '106/05/01' to '2017/05/01'"""
  103.         return '/'.join([str(int(date.split('/')[0]) + 1911)] + date.split('/')[1:])

  104.     def _make_datatuple(self, data):
  105.         data[0] = datetime.datetime.strptime(self._convert_date(data[0].replace('*', '')),
  106.                                              '%Y/%m/%d')
  107.         data[1] = int(data[1].replace(',', '')) * 1000
  108.         data[2] = int(data[2].replace(',', '')) * 1000
  109.         data[3] = None if data[3] == '--' else float(data[3].replace(',', ''))
  110.         data[4] = None if data[4] == '--' else float(data[4].replace(',', ''))
  111.         data[5] = None if data[5] == '--' else float(data[5].replace(',', ''))
  112.         data[6] = None if data[6] == '--' else float(data[6].replace(',', ''))
  113.         data[7] = float(data[7].replace(',', ''))
  114.         data[8] = int(data[8].replace(',', ''))
  115.         return DATATUPLE(*data)

  116.     def purify(self, original_data):
  117.         return [self._make_datatuple(d) for d in original_data['aaData']]


  118. class Stock(analytics.Analytics):

  119.     def __init__(self, sid: str, initial_fetch: bool=True):
  120.         self.sid = sid
  121.         self.fetcher = TWSEFetcher(
  122.         ) if codes[sid].market == '上市' else TPEXFetcher()
  123.         self.raw_data = []
  124.         self.data = []

  125.         # Init data
  126.         if initial_fetch:
  127.             self.fetch_31()

  128.     def _month_year_iter(self, start_month, start_year, end_month, end_year):
  129.         ym_start = 12 * start_year + start_month - 1
  130.         ym_end = 12 * end_year + end_month
  131.         for ym in range(ym_start, ym_end):
  132.             y, m = divmod(ym, 12)
  133.             yield y, m + 1

  134.     def fetch(self, year: int, month: int):
  135.         """Fetch year month data"""
  136.         self.raw_data = [self.fetcher.fetch(year, month, self.sid)]
  137.         self.data = self.raw_data[0]['data']
  138.         return self.data

  139.     def fetch_from(self, year: int, month: int):
  140.         """Fetch data from year, month to current year month data"""
  141.         self.raw_data = []
  142.         self.data = []
  143.         today = datetime.datetime.today()
  144.         for year, month in self._month_year_iter(month, year, today.month, today.year):
  145.             start = time.time()
  146.             self.raw_data.append(self.fetcher.fetch(year, month, self.sid))
  147.             self.data.extend(self.raw_data[-1]['data'])
  148.             done = time.time()
  149.             elapsed = int(done - start)
  150.             print('fetch from {}/{}, time:{}'.format(year, month, elapsed), end=' ')
  151.         return self.data

  152.     def fetch_31(self):
  153.         """Fetch 31 days data"""
  154.         today = datetime.datetime.today()
  155.         before = today - datetime.timedelta(days=60)
  156.         self.fetch_from(before.year, before.month)
  157.         self.data = self.data[-31:]
  158.         return self.data

  159.     @property
  160.     def date(self):
  161.         return [d.date for d in self.data]

  162.     @property
  163.     def capacity(self):
  164.         return [d.capacity for d in self.data]

  165.     @property
  166.     def turnover(self):
  167.         return [d.turnover for d in self.data]

  168.     @property
  169.     def price(self):
  170.         return [d.close for d in self.data]

  171.     @property
  172.     def high(self):
  173.         return [d.high for d in self.data]

  174.     @property
  175.     def low(self):
  176.         return [d.low for d in self.data]

  177.     @property
  178.     def open(self):
  179.         return [d.open for d in self.data]

  180.     @property
  181.     def close(self):
  182.         return [d.close for d in self.data]

  183.     @property
  184.     def change(self):
  185.         return [d.change for d in self.data]

  186.     @property
  187.     def transaction(self):
  188.         return [d.transaction for d in self.data]
複製代碼
  1. https://github.com/joytsay/twstock/blob/master/twstock/stock.py">twstock/stock.py at master · joytsay/twstock · GitHub
複製代碼




分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 轉播轉播 分享分享 分享淘帖
回復

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

小黑屋|Archiver|手機版|艾歐踢創新工坊    

GMT+8, 2024-5-15 16:47 , Processed in 0.256683 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表