数据观察

沪、深证券交易所自1990年成立以来,已伴随中国经济发展将近30年了。在这将近30年里,沪、深股市起起落落、跌跌撞撞顽强走出了一条支撑中国企业、中国经济发展的股市成长道路。然而最近随着外部经济环境不断趋紧,国内经济也存在下行压力,沪深股市已经持续低迷相当长一段时间。为进一步了解沪深股市目前现状,这里使用python来爬取同花顺网上所有沪深上市公司基本信息以及当前市值信息,探讨沪深股市总体情况以及企业经营现状。

一、需求分析

(1)获得上证、深证所有上市公司名称与证券代码,包括上证A股、深证A股、创业板和中小板所有上市公司;

(2)获取各上市公司基本信息,包括所属地域、主营业务、上市日期、每股净资产、每股收益、净利润、净利润增长率、营业收入、每股现金流、每股公积金、每股未分配利润、总股本、流通股等信息;

(3)获取各上市公司当前市值情况,包括当前总市值、市净率、流通市值、市盈率等信息。

二、网页分析

根据数据获取需求,爬取网页主要有以下三块:

1、个股行情

python 获取同花顺持仓 爬取同花顺数据_爬虫

image

2、公司简介

python 获取同花顺持仓 爬取同花顺数据_上市公司_02

image

3、个股当前信息

python 获取同花顺持仓 爬取同花顺数据_python_03

image

三、爬虫思路

为便于数据处理方便,在本地搭建一个MYSQL数据库,将抓取的数据直接存入数据库中。程序抓数主要过程为:

(1) 通过个股行情页面,获得所有上市公司名称、股票代码、上市板块以及详细信息链接,然后将这些信息存入数据表一;在仔细分析各版块网页时,可发现网址未发生变化,而内容发生变化,这属于异步请求。打开F12查看Network中XHR发现会每次点击都会多出来一行,而多出一行的网址就是异步提取得数据,因此可以通过爬取该网页获得异步请求数据;

python 获取同花顺持仓 爬取同花顺数据_上市公司_04

image

python 获取同花顺持仓 爬取同花顺数据_python_05

image

(2)在详细信息链接中,抓数分为两块,一是公司简介,这属于静态网页,为提高抓数效率,直接可使用requests模块抓取;

(3)二是个股当前信息,通过分析网页可发现,该板块是网页内嵌滚动数据,这个使用selenium中switch_to.frame函数获得,然后将所有获得的详细信息存入数据表二。

四、数据获取

1、个股行情

(1)配置本地数据库,用于存储数据

def mysql_login():    ###连接数据库,数据库配置
    config = {
        'host': 'localhost',
        'port': 3306,
        'user': '*******',
        'password': '*******',
        'db': 'mysql',
        'charset': 'utf8',
        'cursorclass': pymysql.cursors.DictCursor,
    }
    # Connect to the database
    connection = pymysql.connect(**config)
    return connection

(2)获取个股行情链接,存入数据表tonghuashun_lianjie_001

def get_url():   ##获得代码、名称以及url
    connection=mysql_login()
    hs='http://q.10jqka.com.cn/index/index/board/hs/field/zdf/order/desc/page/'
    ss='http://q.10jqka.com.cn/index/index/board/ss/field/zdf/order/desc/page/'
    zxb='http://q.10jqka.com.cn/index/index/board/zxb/field/zdf/order/desc/page/'
    cyb='http://q.10jqka.com.cn/index/index/board/cyb/field/zdf/order/desc/page/'
    zq_market=[hs,ss,zxb,cyb]
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'}
    j=0
    for url in zq_market:
        bk_list=get_url(url,j)
        j+=1

    bk_name=['hs','ss','zxb','cyb']
    i=1
    #print(bk_name[j])
    #pages_all=2
    while(1):
        print(bk_name[j],i)
        if i==1:    ###抓第一页,获得总页数
            urls=url+str(i)+'/ajax/1/'
            browser=webdriver.Chrome(chrome_options=chrome_options)
            browser.get(urls)
            html_data2 = browser.page_source
            browser.close()
            root3 = etree.HTML(html_data2)
            p=root3.xpath('//*[@id="m-page"]/span/text()')[0]
            page_all=p[2:]
            no_list=root3.xpath('/html/body/table/tbody/tr/td[1]/text()')
            code_no=root3.xpath('/html/body/table/tbody/tr/td[2]/a/text()')
            code_name=root3.xpath('/html/body/table/tbody/tr/td[3]/a/text()')
            code_url=root3.xpath('/html/body/table/tbody/tr/td[2]/a/@href')
            for no in range(len(code_url)):
                sql = "INSERT INTO database.tonghuashun_lianjie_001 (bk_name,code_no,code_name,code_url,no) VALUES " \
                              "('" + bk_name[j] + "','" + code_no[no] + "','" + code_name[no] + "','" + code_url[no]   + "','" + no_list[no]   + "')"              
                with connection.cursor() as cursor:
                    cursor.execute(sql)    ####存入数据库中
            i+=1  

        if i>1 and i<=int(page_all):
            urls=url+str(i)+'/ajax/1/'
            browser=webdriver.Chrome(chrome_options=chrome_options)
            browser.get(urls)
            html_data2 = browser.page_source
            browser.close()
            root3 = etree.HTML(html_data2)
            no_list=root3.xpath('/html/body/table/tbody/tr/td[1]/text()')  # 序号
            code_no=root3.xpath('/html/body/table/tbody/tr/td[2]/a/text()') # 企业代码
            code_name=root3.xpath('/html/body/table/tbody/tr/td[3]/a/text()') #企业名称
            code_url=root3.xpath('/html/body/table/tbody/tr/td[2]/a/@href') #  链接
            for no in range(len(code_url)):
                sql = "INSERT INTO database.tonghuashun_lianjie_001 (bk_name,code_no,code_name,code_url,no) VALUES " \
                              "('" + bk_name[j] + "','" + code_no[no] + "','" + code_name[no] + "','" + code_url[no]   + "','" + no_list[no]   + "')"
                with connection.cursor() as cursor:
                    cursor.execute(sql)    ####存入数据库中
            i+=1  
        if i>int(page_all):
            break
    connection.commit()

2、公司简介及股值
(1)读取数据库表链接,获取个股股票代码、名称和url。

def get_url()
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-dev-shm-usage')
    chrome_options.add_argument('--headless')
    connection=mysql_login()
    sql1='select distinct code_no,code_url,bk_name from database.tonghuashun_lianjie_001'
    with connection.cursor() as cursor:
        cursor.execute(sql1)
        mm=cursor.fetchall()
        code_no = [item['code_no'] for item in mm]
        code_code_url=[item['code_url'] for item in mm]
        code_market=[item['bk_name'] for item in mm]
    connection.commit()    
    for i in range(385,len(code_code_url)):
        stocks_content(i,code_no[i],code_code_url[i],code_market[i])
        if i%50==0:
            print(i,code_no[i])

(2)获取公司简介及股值。并存入数据库中

def stocks_content(i,code_no,url,code_market):
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'}
   ###公司简介信息获取
    web_data = requests.get(url,headers=headers)
    root = etree.HTML(web_data.text)
    name=root.xpath('//*[@id="in_squote"]/div/h1/a[1]/strong/text()')[0]
    main_busin=root.xpath('/html/body/div[9]/div[2]/div[3]/dl/dd[4]/@title')[0].strip()
    main_business=main_busin[:50]
    company_details=root.xpath('//dd/text()')
    ####股票当前信息获取
    browser2=webdriver.Chrome(chrome_options=chrome_options)  ##内嵌网页内容提取
    browser2.get(url)
    browser2.switch_to.frame('ifm')
    #ddd=browser.find_element_by_class_name('minus')
    html_data2 = browser2.page_source
    browser2.close()
    root3 = etree.HTML(html_data2)
    value_info=root3.xpath('//strong/text()')
    all_ss=[name,company_details[0],company_details[3],company_details[4],company_details[5],
                company_details[6],company_details[7],company_details[8],company_details[9],company_details[10],
    company_details[11] ,company_details[12],company_details[13]]+value_info+[main_business]
  ####数据存入数据库
    sql = "INSERT INTO database.tonghuashun_stocks_001 (no,item_no,market,item_name,area_loc,ipo_date, \      per_share_net_assets,per_share,net_profit,net_profit_growth_rate,operating_income,cash_flow_per_share,\     reserve_fund_per_share,udpps,capitalization,circulation_stock,today_price,today_volume,amplitude,max_price,\  turnover,turnover_rate,min_price,market_value,pbv,yesterday,circulattion_market_value,per,main_business) VALUES " \ "('" +str(i)+"','"+ code_no+"','"+ code_market+"','"+all_ss[0] + "','" + all_ss[1] + "','" +all_ss[2] + "','" + all_ss[3] + "','" + all_ss[4] + "','" + all_ss[5] + "','" \ +all_ss[6] + "','" +all_ss[7] + "','" + all_ss[8] + "','" + all_ss[9] +"','" + all_ss[10] +"','" + all_ss[11] +"','" + all_ss[12] +"','" \+all_ss[13] + "','" +all_ss[14] + "','" + all_ss[15] + "','" + all_ss[16] +"','" + all_ss[17] +"','" + all_ss[18] +"','" \
        +all_ss[19] + "','" +all_ss[20] + "','" + all_ss[21] + "','" + all_ss[22] +"','" + all_ss[23] +"','" + all_ss[24] +"','" + all_ss[25]  \
        + "')"
    with connection.cursor() as cursor:
        cursor.execute(sql)
    connection.commit()

五、总结
本文使用python来爬取同花顺网上所有沪深上市公司基本信息以及当前市值信息,主要解决了异步数据获取和网页内嵌滚动信息获取两个问题。本次爬数总共获得目前沪深所有上市公司信息,共3540家:其中上海证券交易所上市公司总计1401家;深圳证券交易所上市公司总计2139家,其中主板457家、中小板925家、创业板757家。