【问题标题】:How do I use this for-loop to this webscraping stock module?我如何使用这个 for 循环到这个 webscraping stock 模块?
【发布时间】:2021-01-05 13:53:27
【问题描述】:

我有一个小问题,我不明白这个 for 循环

我有一个股票符号列表

Stocks = ['ADVANC.BK', 'AOT.BK', 'AWC.BK', 'BAM.BK', 'BBL.BK', 'BDMS.BK', 'BEM.BK', 'BGRIM.BK']

我使用模块parinya 来获取股票价格的数据 例如

data = parinya.getHistStock('ADVANC.BK, interval='1d', day_begin='01-01-2018', day_end='10-01-2018')
print(data)


Output >>
              Open   High    Low  Close   Adj Close      Volume
Date                                                          
2018-01-03  191.5  197.5  191.0  196.5  176.633011  15405400.0
2018-01-04  196.5  197.0  194.0  194.0  174.385773   8361700.0
2018-01-05  195.0  197.0  194.5  195.0  175.284637  10294800.0
2018-01-08  195.0  197.0  194.5  196.0  176.183548   8141500.0

所以我决定使用for-loop 来获取所有数据

Data_all_stock = []
for stock in Stocks:
    data = parinya.getHistStock(stock, interval='1d', day_begin='01-01-2018', day_end='10-01-2018')
    Data_all_stock.append(data)

print(Data_all_stock)

出现这个错误

/usr/local/lib/python3.6/dist-packages/parinya/stock.py in getHistStock(stock, interval, day_begin, day_end)
     89             data = website.text.split('\n')[:-1]
     90             data = [d.split(',') for d in data]
---> 91             col = data[0]
     92             #print(col)
     93     data = pd.DataFrame(data[1:])

IndexError: list index out of range

我也试试这个

Data_all_stock = []
for stock in Stocks:
    data = parinya.getHistStock(f"'{stock}'", interval='1d', day_begin='01-01-2018', day_end='10-01-2018')
    Data_all_stock.append(data)

print(Data_all_stock)

它仍然是错误的

/usr/local/lib/python3.6/dist-packages/parinya/stock.py in _get_crumbs_and_cookies(stock)
     68         crumb = re.findall('"CrumbStore":{"crumb":"(.+?)"}', str(soup))
     69 
---> 70         return (header, crumb[0], website.cookies)
     71 
     72 

IndexError: list index out of range

所以,我决定查看模块 parinya,这就是 stock.py 的样子:

import requests
from bs4 import BeautifulSoup
import re
import string
from datetime import datetime
from time import mktime
import pandas as pd
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from yahoo_fin import stock_info as si

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def getSETSymbols(sector = 'ALL'):
    if sector == 'ALL':
        symbols = []
        url = 'https://www.set.or.th/set/commonslookup.do?language=th&country=TH&prefix={{key}}'
        key = ['NUMBER']
        key.extend(list(string.ascii_uppercase))
        for k in key:
            r = requests.get(url.replace('{{key}}',k), verify=False)
            soup = BeautifulSoup(r.content, "html.parser")
            for i in soup.findAll('a', href=re.compile('.*companyprofile.*')):
                symbols.append(i.text)
        return symbols

    symbols = []
    url = 'https://marketdata.set.or.th/mkt/sectorquotation.do?sector=SET100&language=th&country=TH'
    if sector != 'SET100':
        url = url.replace('SET100', sector)
    r = requests.get(url, verify=False)
    soup = BeautifulSoup(r.content, "html.parser")
    for i in soup.findAll('a', href=re.compile('.*symbol.*')):
        symbols.append(i.text.strip())
    return symbols

def getSET100Price():
    url = 'https://marketdata.set.or.th/mkt/sectorquotation.do?sector=SET100&language=th&country=TH'
    r = requests.get(url, verify=False)
    soup = BeautifulSoup(r.content, "html.parser")
    for i in soup.findAll('caption'):
        timestamp = i.text
        timestamp = timestamp[timestamp.find('ข้อมูลล่าสุด'):].split()
        temp = timestamp[1].split('/')
        temp = temp[0] + '-' + temp[1] + '-' + str(int(temp[2]) - 543)
        timestamp = datetime.strptime(temp + ' ' + timestamp[2], '%d-%m-%Y %H:%M:%S')

    data = []
    for i in soup.findAll('a', href=re.compile('.*symbol.*')):
        children = i.parent.parent.findChildren("td", recursive=False)
        symbol = i.text.strip()
        price = float(children[9].text)
        data.append((symbol, price))

    return data, timestamp

def _get_crumbs_and_cookies(stock):
    url = 'https://finance.yahoo.com/quote/{}/history'.format(stock)
    with requests.session():
        header = {'Connection': 'keep-alive',
                  'Expires': '-1',
                  'Upgrade-Insecure-Requests': '1',
                  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) \
                   AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36'
                  }

        website = requests.get(url, headers=header, verify=False)
        soup = BeautifulSoup(website.text, 'lxml')
        crumb = re.findall('"CrumbStore":{"crumb":"(.+?)"}', str(soup))

        return (header, crumb[0], website.cookies)


def convert_to_unix(date):
    datum = datetime.strptime(date, '%d-%m-%Y')
    return int(mktime(datum.timetuple()))


def getHistStock(stock, interval='1d', day_begin='01-03-2018', day_end='28-03-2018'):
    day_begin_unix = convert_to_unix(day_begin)
    day_end_unix = convert_to_unix(day_end)
    col = [1]
    while len(col)==1:
        header, crumb, cookies = _get_crumbs_and_cookies(stock)
        with requests.session():
            url = 'https://query1.finance.yahoo.com/v7/finance/download/' \
                  '{stock}?period1={day_begin}&period2={day_end}&interval={interval}&events=history&crumb={crumb}' \
                .format(stock=stock, day_begin=day_begin_unix, day_end=day_end_unix, interval=interval, crumb=crumb)
            website = requests.get(url, headers=header, cookies=cookies, verify=False)
            data = website.text.split('\n')[:-1]
            data = [d.split(',') for d in data]
            col = data[0]
            #print(col)
    data = pd.DataFrame(data[1:])
    data.columns = col
    data.set_index('Date', inplace=True)
    return data.apply(pd.to_numeric, downcast='float', errors='coerce')

def getLivePrice(stock):
    return si.get_live_price(stock)


【问题讨论】:

    标签: python html python-requests


    【解决方案1】:

    原因:

    我怀疑getHistStock 对无效日期选择没有足够的错误处理。我怀疑您当前选择的 day_begin='01-01-2018', day_end='10-01-2018' 日期超出了以预期形式返回数据的有效期限,至少对于您的某些代码;这会导致您的错误。

    如果我转到finance.yahoo.com 并查找那个时期,对于您的每个股票代码,当我到达AWC.BK 时,我看到网站显示Date shouldn't be prior to '2019-10-10' - quick check for the IPO date 给了我'10/10/2019'作为浮动/上市日期,即有数据的第一个日期。您可以对BAM.BKDate shouldn't be prior to '2019-12-16'Listed Date 16/12/2019 重复此操作。

    免责声明:您可以使用您选择的IPO 检查器。我对股票一无所知,所以只需使用来自https://www.set.or.th/ 的情况说明书来检查雅虎财经所指示的日期。


    可能的修复:

    最基本的 - 您可以在循环 for stock in Stocks: 中添加一个 try except 错误包装器;处理您认为合适的错误,例如在except 中添加一个“无数据”列表条目,然后继续循环。

    当然,您也可以提前查看每个代码的 IPO 日期,并相应地调整您要求的范围,但您可能仍需要错误处理作为应对意外结果的良好做法。


    假设的测试用例:(未测试

    预期失败 -

    data = parinya.getHistStock('AWC.BK', interval='1d', day_begin='01-01-2018', day_end='10-01-2018')
    print(data)
    

    预期通过 -

    data = parinya.getHistStock('AWC.BK', interval='1d', day_begin='10-10-2019', day_end='20-10-2019')
    print(data)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-12
      • 1970-01-01
      • 2019-07-25
      • 1970-01-01
      • 2016-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多