股票数据的爬取(selenium的使用)
皮猪 28 2

目录

  • 前言
  • 编写代码
  • 总结

前言

本次我们使用selenium来获取网页中的股票id,然后根据这些id拼接出url,访问相应的url获取到我们想要的数据,存储到excel里。 不多说,先上结果图。 2021-05-02 155559

编写代码

1.分析网页

QQ截图20210502155925 本次爬取的网站是东方财富网中的上证A股、深证A股、创业版、科创版4个板块中所有股票的行情。例如N志特我们需要的就是棕色框框内的内容。 QQ图片20210502160153 其实股票id可以通过这个网址获取,速度更快,但第一次时我还是傻乎乎地使用了selenium来获取。 QQ截图20210502160707 不过也没关系,我们可以尝试着使用一下selenium这个自动化工具。 当然,使用selenium获取我们还需要模拟点击下一页,因为一页上的股票是展示不全的。 获取到股票id后,我们就可以拼接出对应的url了。 比如N志特的url就是http://quote.eastmoney.com/sz300986.html 其中的sz是对应的板块,300986就是它的股票id。 进入到对应的股票界面,进行抓包。我们发现所需要的数据在这个地方。 QQ截图20210502161506 但有个问题,我们不知道这些数据的对应关系,可能有人说可以将这里的数据和网页上的数据一个个比对,这样是可以,但很麻烦而且不准确,所以我们还是到对应的js文件里看看是如何处理这些数据的吧。 在调试界面按ctrl+shift+F打开全局搜索,然后搜索一个字段,我们发现我们找到了所需要的对应关系,不放心的话按照这个将数据和网页上的进行对比,发现没错,就是这个! QQ截图20210502163339 接下来我们就可以开始写代码了!

2.编写代码

首先是获取股票id页面源代码的selenium使用函数,注意一下里面的time.sleep函数里的值和你浏览器渲染网页的速度有关,如果太小,就会出现网页没渲染完代码就获取到源代码进行下一步操作了,这样会有很大的问题。

def get_html(url):
    #获取项目页面的源码
    page_sources = []
    while True:
        try:
            #打开谷歌浏览器
            wd = webdriver.Chrome()
            #发起请求
            wd.get(url)
            page_sources.append(wd.page_source)
            while True:
                #寻找加载更多按钮进行点击
                html = wd.page_source
                h1 = etree.HTML(html)
                button = h1.xpath('//a[@class="next paginate_button"]')
                #找不到按钮退出
                if len(button) == 0:
                    break
                #寻找结束按钮
                later = h1.xpath('//a[@class="next paginate_button disabled"]')
                if len(later) == 0:
                    #找不到结束按钮则加载更多
                    i = wd.find_element_by_xpath('//*[@class="next paginate_button"]')
                    i.click()
                    time.sleep(0.5)
                    page_sources.append(wd.page_source)
                else:
                    break
        except BaseException:
            wd.quit()
            time.sleep(0.5)
            print("正在重新获取")
        else:
            # 正常结束则关闭浏览器
            wd.quit()
            time.sleep(0.5)
            break
    return page_sources

接下来是从网页源代码中解析出我们需要的股票id,至于里面的td是股票开头的序列号。

def get_ids(page_sources):
    #解析出id
    id_lists = []
    b = 1
    for page_source in page_sources:
        ids1 = []
        xp = etree.HTML(page_source)
        td = xp.xpath('//table[@id="table_wrapper-table"]/tbody/tr/td[1]/text()')
        ids = xp.xpath('//table[@id="table_wrapper-table"]/tbody/tr/td[2]/a/text()')
        # urls = xp.xpath('//table[@id="table_wrapper-table"]/tbody/tr/td[2]/a/@href')
        for i in range(len(ids)):
            # urls[i] = 'http:' + str(urls[i])
            # urls1.append({td[i]:urls[i]})
            ids1.append({td[i]: ids[i]})
        # print(td,urls)
        id_lists.append({str(b):ids1})
        b += 1
    return id_lists

然后是根据股票id获取到股票的基本行情。

def get_data2(id,i):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 Edg/89.0.774.76',
    }
    urls = [
        'http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&fltt=2&invt=2&volt=2&fields=f43,f57,f58,f169,f170,f46,f44,f51,f168,f47,f164,f163,f116,f60,f45,f52,f50,f48,f167,f117,f71,f161,f49,f530,f135,f136,f137,f138,f139,f141,f142,f144,f145,f147,f148,f140,f143,f146,f149,f55,f62,f162,f92,f173,f104,f105,f84,f85,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f107,f111,f86,f177,f78,f110,f262,f263,f264,f267,f268,f250,f251,f252,f253,f254,f255,f256,f257,f258,f266,f269,f270,f271,f273,f274,f275,f127,f199,f128,f198,f259,f260,f261,f171,f277,f278,f279,f288,f292,f182&secid=1.',
        'http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&invt=2&fltt=2&fields=f43,f57,f58,f169,f170,f46,f44,f51,f168,f47,f164,f163,f116,f60,f45,f52,f50,f48,f167,f117,f71,f161,f49,f530,f135,f136,f137,f138,f139,f141,f142,f144,f145,f147,f148,f140,f143,f146,f149,f55,f62,f162,f92,f173,f104,f105,f84,f85,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f107,f111,f86,f177,f78,f110,f260,f261,f262,f263,f264,f267,f268,f250,f251,f252,f253,f254,f255,f256,f257,f258,f266,f269,f270,f271,f273,f274,f275,f127,f199,f128,f193,f196,f194,f195,f197,f80,f280,f281,f282,f284,f285,f286,f287,f292,f293,f181,f294,f295,f279,f288&secid=0.',
    ]
    url = urls[i]+id
    data = requests.get(url,headers = headers).json()['data']
    return data

接着是将股票数据进行处理一下。

def jianxi(data,i):
    new_data = {}
    ys = [
        {
            'f57': 'id',
            'f58': '名称',
            'f60': '昨收',
            'f43': '最新',
            'f46': '今开',
            'f44': '最高',
            'f168': '换手率(%)',
            'f277': '注册资本',
            'f51': '涨停价',
            'f260': '盘后成交量(手)',
            'f47': '成交量(手)',
            'f45': '最低',
            'f50': '量比',
            'f278': '发行股本',
            'f52': '跌停价',
            'f261': '盘后成交额',
            'f48': '成交额',
            'f171': '振幅',
            'f71': '均价',
            'f164': '市盈率ttm',
            'f85': '流通股本',
            'f279': '同权同股(1为是)',
            'f288': '是否盈利(0为是,1为否)',
        },
        {
            'f57': 'id',
            'f58': '名称',
            'f60': '昨收',
            'f43': '最新',
            'f46': '今开',
            'f44': '最高',
            'f168': '换手率(%)',
            'f51': '涨停价',
            'f260': '盘后成交量(手)',
            'f47': '成交量(手)',
            'f45': '最低',
            'f50': '量比',
            'f52': '跌停价',
            'f261': '盘后成交额',
            'f48': '成交额',
            'f71': '均价',
            'f164': '市盈率ttm',
            'f85': '流通股本',
            'f293': '同权同股->是否有表决权差异(1为是)',
            'f288': '是否盈利(0为是,1为否)',
            'f167':'市净',
            'f116':'总市值',
            'f117':'流通市值'
        }
    ]
    for n in ys[i].keys():
        # print(n)
        new_data[ys[i][n]] = data[n]
    return new_data

最后是一个写入表格的函数。

def write_xls(name,data,i):
    wb = load_workbook('股票.xlsx')
    ws = wb.create_sheet(name,0)
    ys = [
        {
        'A': 'id',
        'B': '名称',
        'C': '昨收',
        'D': '最新',
        'E': '今开',
        'F': '最高',
        'G': '换手率(%)',
        'H': '注册资本',
        'I': '涨停价',
        'J': '盘后成交量(手)',
        'K': '成交量(手)',
        'L': '最低',
        'M': '量比',
        'N': '发行股本',
        'O': '跌停价',
        'P': '盘后成交额',
        'Q': '成交额',
        'R': '振幅',
        'S': '均价',
        'T': '市盈率ttm',
        'U': '流通股本',
        'V': '同权同股(1为是)',
        'W': '是否盈利(0为是,1为否)',
    },
        {
            'A': 'id',
            'B': '名称',
            'C': '昨收',
            'D': '最新',
            'E': '今开',
            'F': '最高',
            'G': '换手率(%)',
            'H': '涨停价',
            'I': '盘后成交量(手)',
            'J': '成交量(手)',
            'K': '最低',
            'L': '量比',
            'M': '跌停价',
            'N': '盘后成交额',
            'O': '成交额',
            'P': '均价',
            'Q': '市盈率ttm',
            'R': '流通股本',
            'S': '同权同股->是否有表决权差异(1为是)',
            'T': '是否盈利(0为是,1为否)',
            'U': '市净',
            'V': '总市值',
            'W': '流通市值'
        }
    ]
    for key, value in ys[i].items():
        ws[key + '1'] = value
        for n in range(len(data)):
            ws[key+str(n+2)] = data[n][value]
    wb.save('股票.xlsx')

3.总的代码

#coding:utf-8
from openpyxl import Workbook
from openpyxl import load_workbook
from selenium import webdriver
from lxml import etree
import requests
import time

def get_html(url):
    #获取项目页面的源码
    page_sources = []
    while True:
        try:
            #打开谷歌浏览器
            wd = webdriver.Chrome()
            #发起请求
            wd.get(url)
            page_sources.append(wd.page_source)
            while True:
                #寻找加载更多按钮进行点击
                html = wd.page_source
                h1 = etree.HTML(html)
                button = h1.xpath('//a[@class="next paginate_button"]')
                #找不到按钮退出
                if len(button) == 0:
                    break
                #寻找结束按钮
                later = h1.xpath('//a[@class="next paginate_button disabled"]')
                if len(later) == 0:
                    #找不到结束按钮则加载更多
                    i = wd.find_element_by_xpath('//*[@class="next paginate_button"]')
                    i.click()
                    time.sleep(0.5)
                    page_sources.append(wd.page_source)
                else:
                    break
        except BaseException:
            wd.quit()
            time.sleep(0.5)
            print("正在重新获取")
        else:
            # 正常结束则关闭浏览器
            wd.quit()
            time.sleep(0.5)
            break
    return page_sources

def get_ids(page_sources):
    #解析出id
    id_lists = []
    b = 1
    for page_source in page_sources:
        ids1 = []
        xp = etree.HTML(page_source)
        td = xp.xpath('//table[@id="table_wrapper-table"]/tbody/tr/td[1]/text()')
        ids = xp.xpath('//table[@id="table_wrapper-table"]/tbody/tr/td[2]/a/text()')
        # urls = xp.xpath('//table[@id="table_wrapper-table"]/tbody/tr/td[2]/a/@href')
        for i in range(len(ids)):
            # urls[i] = 'http:' + str(urls[i])
            # urls1.append({td[i]:urls[i]})
            ids1.append({td[i]: ids[i]})
        # print(td,urls)
        id_lists.append({str(b):ids1})
        b += 1
    return id_lists

def get_html2(id_list,i):
    datas = []
    for pages in id_list:
        for page in pages.values(): #对于每一页
            for id in page:    #对于每一个链接
                new_id = list(id.values())[0]
                print(new_id)
                data = get_data2(new_id,i)
                new_data = jianxi(data,i)
                print(new_data)
                datas.append(new_data)
                time.sleep(0.5)
    return datas

def jianxi(data,i):
    new_data = {}
    ys = [
        {
            'f57': 'id',
            'f58': '名称',
            'f60': '昨收',
            'f43': '最新',
            'f46': '今开',
            'f44': '最高',
            'f168': '换手率(%)',
            'f277': '注册资本',
            'f51': '涨停价',
            'f260': '盘后成交量(手)',
            'f47': '成交量(手)',
            'f45': '最低',
            'f50': '量比',
            'f278': '发行股本',
            'f52': '跌停价',
            'f261': '盘后成交额',
            'f48': '成交额',
            'f171': '振幅',
            'f71': '均价',
            'f164': '市盈率ttm',
            'f85': '流通股本',
            'f279': '同权同股(1为是)',
            'f288': '是否盈利(0为是,1为否)',
        },
        {
            'f57': 'id',
            'f58': '名称',
            'f60': '昨收',
            'f43': '最新',
            'f46': '今开',
            'f44': '最高',
            'f168': '换手率(%)',
            'f51': '涨停价',
            'f260': '盘后成交量(手)',
            'f47': '成交量(手)',
            'f45': '最低',
            'f50': '量比',
            'f52': '跌停价',
            'f261': '盘后成交额',
            'f48': '成交额',
            'f71': '均价',
            'f164': '市盈率ttm',
            'f85': '流通股本',
            'f293': '同权同股->是否有表决权差异(1为是)',
            'f288': '是否盈利(0为是,1为否)',
            'f167':'市净',
            'f116':'总市值',
            'f117':'流通市值'
        }
    ]
    for n in ys[i].keys():
        # print(n)
        new_data[ys[i][n]] = data[n]
    return new_data

def get_data2(id,i):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36 Edg/89.0.774.76',
    }
    urls = [
        'http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&fltt=2&invt=2&volt=2&fields=f43,f57,f58,f169,f170,f46,f44,f51,f168,f47,f164,f163,f116,f60,f45,f52,f50,f48,f167,f117,f71,f161,f49,f530,f135,f136,f137,f138,f139,f141,f142,f144,f145,f147,f148,f140,f143,f146,f149,f55,f62,f162,f92,f173,f104,f105,f84,f85,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f107,f111,f86,f177,f78,f110,f262,f263,f264,f267,f268,f250,f251,f252,f253,f254,f255,f256,f257,f258,f266,f269,f270,f271,f273,f274,f275,f127,f199,f128,f198,f259,f260,f261,f171,f277,f278,f279,f288,f292,f182&secid=1.',
        'http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&invt=2&fltt=2&fields=f43,f57,f58,f169,f170,f46,f44,f51,f168,f47,f164,f163,f116,f60,f45,f52,f50,f48,f167,f117,f71,f161,f49,f530,f135,f136,f137,f138,f139,f141,f142,f144,f145,f147,f148,f140,f143,f146,f149,f55,f62,f162,f92,f173,f104,f105,f84,f85,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f107,f111,f86,f177,f78,f110,f260,f261,f262,f263,f264,f267,f268,f250,f251,f252,f253,f254,f255,f256,f257,f258,f266,f269,f270,f271,f273,f274,f275,f127,f199,f128,f193,f196,f194,f195,f197,f80,f280,f281,f282,f284,f285,f286,f287,f292,f293,f181,f294,f295,f279,f288&secid=0.',
    ]
    url = urls[i]+id
    data = requests.get(url,headers = headers).json()['data']
    return data

def write_xls(name,data,i):
    wb = load_workbook('股票.xlsx')
    ws = wb.create_sheet(name,0)
    ys = [
        {
        'A': 'id',
        'B': '名称',
        'C': '昨收',
        'D': '最新',
        'E': '今开',
        'F': '最高',
        'G': '换手率(%)',
        'H': '注册资本',
        'I': '涨停价',
        'J': '盘后成交量(手)',
        'K': '成交量(手)',
        'L': '最低',
        'M': '量比',
        'N': '发行股本',
        'O': '跌停价',
        'P': '盘后成交额',
        'Q': '成交额',
        'R': '振幅',
        'S': '均价',
        'T': '市盈率ttm',
        'U': '流通股本',
        'V': '同权同股(1为是)',
        'W': '是否盈利(0为是,1为否)',
    },
        {
            'A': 'id',
            'B': '名称',
            'C': '昨收',
            'D': '最新',
            'E': '今开',
            'F': '最高',
            'G': '换手率(%)',
            'H': '涨停价',
            'I': '盘后成交量(手)',
            'J': '成交量(手)',
            'K': '最低',
            'L': '量比',
            'M': '跌停价',
            'N': '盘后成交额',
            'O': '成交额',
            'P': '均价',
            'Q': '市盈率ttm',
            'R': '流通股本',
            'S': '同权同股->是否有表决权差异(1为是)',
            'T': '是否盈利(0为是,1为否)',
            'U': '市净',
            'V': '总市值',
            'W': '流通市值'
        }
    ]
    for key, value in ys[i].items():
        ws[key + '1'] = value
        for n in range(len(data)):
            ws[key+str(n+2)] = data[n][value]
    wb.save('股票.xlsx')

if __name__ == '__main__':
    wb = Workbook()
    wb.save('股票.xlsx')
    urls = [('上证A股','http://quote.eastmoney.com/center/gridlist.html#sh_a_board',0),
            ('深圳A股','http://quote.eastmoney.com/center/gridlist.html#sz_a_board',1),
            ('创业版','http://quote.eastmoney.com/center/gridlist.html#gem_board',1),
            ('科创版','http://quote.eastmoney.com/center/gridlist.html#kcb_board',0)
            ]
    for name,url,i in urls:    #对于每一个板块
        print(name)
        page_sources = get_html(url)
        id_list = get_ids(page_sources)
        datas = get_html2(id_list,i)
        # print(datas)
        print(len(datas))
        write_xls(name,datas,i)

总结

这次的代码爬到的数据量还是有点多的,爬取的速度比较慢,后续可能会采用多线程进行优化,提高爬取的速度。 需要股票数据进行分析的小伙伴们可以使用这次的代码来获取数据。 对于不使用selenium获取股票id的函数我在下一篇文章中会给出。

预览图
评论区

索引目录