Python 从网站获取表数据时出错

Python 从网站获取表数据时出错,python,pandas,beautifulsoup,Python,Pandas,Beautifulsoup,我正试图为我的项目从网上获取一些与股票相关的数据。我遇到了几个问题。 问题1: 我试图从这个网站上抓取表格 它起作用了,但列没有按顺序抓取。例如:“Company Name”列的值为“Open price”。我如何解决这个问题? 问题2: 我还试图从“价格历史记录”选项卡下获取特定于公司的数据。 这次我在抓取表数据时出错。我得到的错误是: self.data[key].append(cols[index].get_text()) IndexError: list index out of ra

我正试图为我的项目从网上获取一些与股票相关的数据。我遇到了几个问题。
问题1:
我试图从这个网站上抓取表格
它起作用了,但列没有按顺序抓取。例如:“Company Name”列的值为“Open price”。我如何解决这个问题?
问题2:
我还试图从“价格历史记录”选项卡下获取特定于公司的数据。
这次我在抓取表数据时出错。我得到的错误是:

self.data[key].append(cols[index].get_text())

IndexError: list index out of range    
代码如下所示:

import logging
import requests
from bs4 import BeautifulSoup
import pandas


module_logger = logging.getLogger('mainApp.dataGrabber')


class DataGrabberTable:
    ''' Grabs the table data from a certain url. '''

    def __init__(self, url, csvfilename, columnName=[], tableclass=None):
        module_logger.info("Inside 'DataGrabberTable' constructor.")
        self.pgurl = url
        self.tableclass = tableclass
        self.csvfile = csvfilename
        self.columnName = columnName

        self.tableattrs = {'class':tableclass} #to be passed in find()

        module_logger.info("Done.")


    def run(self):
        '''Call this to run the datagrabber. Returns 1 if error occurs.'''

        module_logger.info("Inside 'DataGrabberTable.run()'.")

        try:
            self.rawpgdata = (requests.get(self.pgurl, timeout=5)).text
        except Exception as e:
            module_logger.warning('Error occured: {0}'.format(e))
            return 1

        #module_logger.info('Headers from the server:\n {0}'.format(self.rawpgdata.headers))

        soup = BeautifulSoup(self.rawpgdata, 'lxml')

        module_logger.info('Connected and parsed the data.')

        table = soup.find('table',attrs = self.tableattrs)
        rows = table.find_all('tr')[1:]

        #initializing a dict in a format below
        # data = {'col1' : [...], 'col2' : [...], }
        #col1 and col2 are from columnName list
        self.data = {}
        self.data = dict(zip(self.columnName, [list() for i in range(len(self.columnName))]))

        module_logger.info('Inside for loop.')
        for row in rows:
            cols = row.find_all('td')
            index = 0
            for key in self.data:
                if index > len(cols): break
                self.data[key].append(cols[index].get_text())
                index += 1
        module_logger.info('Completed the for loop.')

        self.dataframe = pandas.DataFrame(self.data)    #make pandas dataframe

        module_logger.info('writing to file {0}'.format(self.csvfile))
        self.dataframe.to_csv(self.csvfile)
        module_logger.info('written to file {0}'.format(self.csvfile))

        module_logger.info("Done.")
        return 0

    def getData(self):
        """"Returns 'data' dictionary."""
        return self.data




    # Usage example

    def main():
        url = "http://sharesansar.com/c/today-share-price.html"
        classname = "table"
        fname = "data/sharesansardata.csv"
        cols = [str(i) for i in range(18)] #make a list of columns

        '''cols = [
          'S.No', 'Company Name', 'Symbol', 'Open price', 'Max price', 
         'Min price','Closing price', 'Volume', 'Previous closing', 
         'Turnover','Difference',
         'Diff percent', 'Range', 'Range percent', '90 days', '180 days',
         '360 days', '52 weeks high', '52 weeks low']'''

        d = DataGrabberTable(url, fname, cols, classname)
        if d.run() is 1:
            print('Data grabbing failed!')
        else:
            print('Data grabbing done.') 


    if __name__ == '__main__':
        main()    

没有什么建议会有帮助的。谢谢

您的列列表缺少一个元素有19列,而不是18列:

>>> len([str(i) for i in range(18)])
18
而且你似乎把事情复杂化了。应采取以下措施:

import requests
from bs4 import BeautifulSoup
import pandas as pd

price_response = requests.get('http://sharesansar.com/c/today-share-price.html')
price_table = BeautifulSoup(price_response.text, 'lxml').find('table', {'class': 'table'})
price_rows = [[cell.text for cell in row.find_all(['th', 'td'])] for row in price_table.find_all('tr')]
price_df = pd.DataFrame(price_rows[1:], columns=price_rows[0])

com_df = None
for symbol in price_df['Symbol']:
    comp_response = requests.get('http://merolagani.com/CompanyDetail.aspx?symbol=%s' % symbol)
    comp_table = BeautifulSoup(comp_response.text, 'lxml').find('table', {'class': 'table'})
    com_header, com_value = list(), list()
    for tbody in comp_table.find_all('tbody'):
        comp_row = tbody.find('tr')
        com_header.append(comp_row.find('th').text.strip().replace('\n', ' ').replace('\r', ' '))
        com_value.append(comp_row.find('td').text.strip().replace('\n', ' ').replace('\r', ' '))
    df = pd.DataFrame([com_value], columns=com_header)
    com_df = df if com_df is None else pd.concat([com_df, df])

print(price_df)
print(com_df)

我仍然得到列不匹配(问题1)。它成功了!非常感谢你。问题2呢?你发现什么错误了吗?@Kishor它在第一页上找到了所有的标记。将
.head(3)
添加到
price_df['Symbol']
中,以便
用于price_df['Symbol']中的符号。head(3):
,您将看到它提前终止。然后,您只获取前3个公司信息页面。关于问题2,在该站点中,当您向下滚动时,您将看到一个选项卡(包含关于、公告、新闻价格历史记录等列)。在“价格历史记录”选项卡下有一张表,我想抓住它。我试过了,但没有成功。你能帮我吗?@Kishor抓取id为divHistory的
div
。查找所有('div',{'id':'divHistory')
。从那里抓起桌子,然后像以前一样抓起行。试试看,如果你卡住了,告诉我们你的代码,以及它是如何失败的。我强烈建议您使用Chrome的检查工具,从右键单击上下文菜单。右键单击要查找的内容,然后检查。这将准确地告诉您需要刮什么。