股票数据定向爬虫

股票数据定向爬虫

(1)  目标:获取上交所和深交所所有股票的名称和交易信息

新浪股票:http://finance.sina.com.cn/stock/

百度股票:https://gupiao.baidu.com/stock/

选取原则:股票信息静态存在于HTML页面中,非js代码生成

没有Robots协议限制

选取方法:浏览器 F12,源代码查看等

选取心态:不要纠结于某个网站,多找信息源尝试

获取股票列表:

东方财富网:http://quote.eastmoney.com/stocklist.html

获取个股信息:

百度股票:https://gupiao.baidu.com/stock/

单个股票:https://gupiao.baidu.com/stock/sz002439.html

(2)  程序的结构设计

步骤1:从东方财富网获取股票列表

股票数据定向爬虫

获取股票信息列表代码:

# 获得股票的信息列表
# 第一个参数是列表类型,里面存储了所有股票信息
# 第二个参数就是获得股票列表的url
def getStockList(lst, stockURL):
    html = getHTMLText(stockURL, "GB2312")
    soup = BeautifulSoup(html, 'html.parser')
    a = soup.find_all('a')
    for i in a:
        try:
            #找到其属性
            href = i.attrs['href']
            # 用正则表达式的方法找到股票代码
            lst.append(re.findall(r"[s][hz]\d{6}", href)[0])
        except:
            continue

 

步骤2:根据股票列表逐个到百度股票获取个股信息

股票数据定向爬虫

代码:

# 获得每只个股的股票信息
# 第一个参数股票列表,第二个参数URL网站,第三个参数存储路径
def getStockInfo(lst, stockURL, fpath):
    count = 0
    for stock in lst:
        url = stockURL + stock + ".html"
        html = getHTMLText(url)
        try:
            if html == "":
                continue
            # 记录所有个股信息
            infoDict = {}
            soup = BeautifulSoup(html, 'html.parser')
            stockInfo = soup.find('div', attrs={'class': 'stock-bets'})
            # 获取股票名称
            name = stockInfo.find_all(attrs={'class': 'bets-name'})[0]
            infoDict.update({'股票名称': name.text.split()[0]})
            # 获取股票信息
            keyList = stockInfo.find_all('dt')
            valueList = stockInfo.find_all('dd')
            for i in range(len(keyList)):
                key = keyList[i].text
                val = valueList[i].text
                infoDict[key] = val
            # 将数据写到文件中
            with open(fpath, 'a', encoding='utf-8') as f:
                f.write(str(infoDict) + '\n')
                count = count + 1
                # 实现爬取动态进度条
                print("\r当前进度: {:.2f}%".format(count * 100 / len(lst)), end="")
        except:
            #为了知道出错是在哪一行
            traceback.print_exc()
            count = count + 1
            print("\r当前进度: {:.2f}%".format(count * 100 / len(lst)), end="")
            continue

 

 

 

步骤3:将结果存储到文件

(3)  整体代码

# CrawBaiduStocksB.py
import requests
from bs4 import BeautifulSoup
import traceback
import re


def getHTMLText(url, code="utf-8"):
    try:
        r = requests.get(url)
        r.raise_for_status()
        r.encoding = code
        return r.text
    except:
        return ""

# 获得股票的信息列表
# 第一个参数是列表类型,里面存储了所有股票信息
# 第二个参数就是获得股票列表的url
def getStockList(lst, stockURL):
    html = getHTMLText(stockURL, "GB2312")
    soup = BeautifulSoup(html, 'html.parser')
    a = soup.find_all('a')
    for i in a:
        try:
            #找到其属性
            href = i.attrs['href']
            # 用正则表达式的方法找到股票代码
            lst.append(re.findall(r"[s][hz]\d{6}", href)[0])
        except:
            continue

# 获得每只个股的股票信息
# 第一个参数股票列表,第二个参数URL网站,第三个参数存储路径
def getStockInfo(lst, stockURL, fpath):
    count = 0
    for stock in lst:
        url = stockURL + stock + ".html"
        html = getHTMLText(url)
        try:
            if html == "":
                continue
            # 记录所有个股信息
            infoDict = {}
            soup = BeautifulSoup(html, 'html.parser')
            stockInfo = soup.find('div', attrs={'class': 'stock-bets'})
            # 获取股票名称
            name = stockInfo.find_all(attrs={'class': 'bets-name'})[0]
            infoDict.update({'股票名称': name.text.split()[0]})
            # 获取股票信息
            keyList = stockInfo.find_all('dt')
            valueList = stockInfo.find_all('dd')
            for i in range(len(keyList)):
                key = keyList[i].text
                val = valueList[i].text
                infoDict[key] = val
            # 将数据写到文件中
            with open(fpath, 'a', encoding='utf-8') as f:
                f.write(str(infoDict) + '\n')
                count = count + 1
                # 实现爬取动态进度条
                print("\r当前进度: {:.2f}%".format(count * 100 / len(lst)), end="")
        except:
            #为了知道出错是在哪一行
            traceback.print_exc()
            count = count + 1
            print("\r当前进度: {:.2f}%".format(count * 100 / len(lst)), end="")
            continue


def main():
    # 获取股票列表的url
    stock_list_url = 'http://quote.eastmoney.com/stocklist.html'
    # 获取股票信息的url
    stock_info_url = 'https://gupiao.baidu.com/stock/'
    # 保存到盘的根目录
    output_file = 'E:/BaiduStockInfo.txt'
    slist = []
    getStockList(slist, stock_list_url)
    getStockInfo(slist, stock_info_url, output_file)


main()

 

(4)  输出结果

{'昨收': '1.14', '成交量': '3612手', '股票名称': '长信中证能源','折价率': '-0.62', '成交额': '41.80万', '今开': '1.14', '净值':'1.1360', '最高': '1.20', '最低': '1.12'}

{'昨收': '1.03', '成交量': '651手', '股票名称': '长信优选', '折价率': '2.40', '成交额': '6.68万', '今开': '1.03', '净值':'1.0029', '最高': '1.03', '最低':'1.03'}

{'昨收': '1.00', '成交量': '766手', '股票名称': '精准医疗', '折价率': '0.74', '成交额': '7.70万', '今开': '1.00', '净值':'1.0006', '最高': '1.01', '最低':'1.00'}

{'昨收': '0.95', '成交量': '74手', '股票名称': '互联医疗', '折价率': '0.64', '成交额': '7123', '今开': '0.95', '净值': '0.9459', '最高': '0.95', '最低': '0.95'}

{'昨收': '0.94', '成交量': '1手', '股票名称': '互联医C', '折价率': '1.13', '成交额': '95', '今开': '0.95', '净值': '0.9433', '最高': '0.95', '最低': '0.95'}

{'昨收': '1.22', '成交量': '2424手', '股票名称': '生物科技', '折价率': '-0.21', '成交额': '29.27万', '今开': '1.22', '净值':'1.2075', '最高': '1.22', '最低':'1.21'}

{'昨收': '1.21', '成交量': '1284手', '股票名称': '生物科C', '折价率': '-0.68', '成交额': '15.38万', '今开': '1.21', '净值':'1.2062', '最高': '1.21', '最低':'1.19'}

{'昨收': '1.08', '成交量': '125手', '股票名称': '中药基金', '折价率': '1.26', '成交额': '1.34万', '今开': '1.07', '净值':'1.0715', '最高': '1.09', '最低':'1.06'}

{'昨收': '1.07', '成交量': '1794手', '股票名称': '中药C', '折价率': '0.62', '成交额': '19.26万', '今开': '1.07', '净值':'1.0694', '最高': '1.08', '最低':'1.07'}

{'昨收': '0.97', '成交量': '2.69万手', '股票名称': '财通升级(LOF)', '折价率': '-1.13', '成交额': '259.98万', '今开':'0.97', '净值': '0.9760', '最高':'0.97', '最低': '0.96'}

{'昨收': '1.07', '成交量': '532手', '股票名称': '券商基金', '折价率': '0.23', '成交额': '5.66万', '今开': '1.06', '净值':'1.0636', '最高': '1.07', '最低':'1.06'}

{'昨收': '0.94', '成交量': '1507手', '股票名称': '国泰融丰', '折价率': '-2.77', '成交额': '14.14万', '今开': '0.94', '净值':'0.9647', '最高': '0.94', '最低':'0.94'}

{'昨收': '1.00', '成交量': '9417手', '股票名称': '南方原油', '折价率': '-1.39', '成交额': '94.33万', '今开': '1.00', '净值':'1.0141', '最高': '1.00', '最低':'1.00'}

{'昨收': '0.86', '成交量': '2476手', '股票名称': '军工基金', '折价率': '0.04', '成交额': '21.20万', '今开': '0.85', '净值':'0.8567', '最高': '0.86', '最低':'0.85'}

{'昨收': '1.10', '成交量': '154手', '股票名称': '国企改', '折价率': '-0.43', '成交额': '1.70万', '今开': '1.10', '净值':'1.1058', '最高': '1.10', '最低':'1.10'}