python爬虫之股票数据定向爬取

python爬虫之股票数据定向爬取

功能描述

  • 目标:获取上交所和深交所所有股票的名称和交易的信息
  • 输出:保存到文件中
  • 技术路线:requests-bs4-re

前期分析

  • 选取原则:股票的信息静态存在HTML页面中,非js代码生成,没有robots协议限制
  • 选取方法:查看网页原码不纠结于某个网站,多找信息源尝试

没有成功,价格没有搜索到
在这里插入图片描述
在源码中搜索价格,不存在

在这里插入图片描述
搜索价格没有
在这里插入图片描述
没有找到相关的价格信息
在这里插入图片描述
没有找到相关价格信息
在这里插入图片描述

没有找到相关的价格信息
在这里插入图片描述
多此尝试之后,发现基本上都没有找到,于是找教程推荐的
百度股票,已经不见了
在这里插入图片描述

  • 总结:个人观点,股票价格这种实时更新的数据怎么会写在网页,大部分应该都是写在js中,然后又服务器发送相关数据,但是仍旧不失为一个练习的思路,还是来分析一下吧

教程提供的信息:

  • 关於单个股票的信息

    • 点击每个股票的连接,发现会出现相关的跳转,反映在网址上的变化就是多了几个关键字
    • 思路:获取每个股票的标号,输入到对应的网址中,即可获得相关股票的实时价格

在这里插入图片描述

  • 通过东方财富网获取所有股票的序号

在这里插入图片描述

  • 东方财富网的股票的序号

从图上就可以看出,是在对应的a标签中,可以采用正则表达式进行筛选r’[zh|sh]\d{6}’
在这里插入图片描述

程序编写

  • 第一步,编写相关的整体步骤
    • 从东方财富网获取股票的列表 getHTMLText(url)
    • 根据股票列表逐个到百度股票中获取个股的信息 getStockList(lst,stockURL)
    • 将结果存储到文件中 getStockInfo(lst,stockURL,fpath)
    • main函数将所有的函数连接起来
import requests
import re
from bs4 import BeautifulSoup

# 获取相关网页的html文件
def getHTMLText(url):
    return''

# 获取所有股票的序号
def getStockList(lst,stockURL):
    return ''

# 获取所有股票的价格
def getStockInfo(lst,stockURL,fpath):
    return ''


def main():
    stock_list_url = 'http://quote.eastmony.com/stocklist.html'
    # 获取股票信息序号的网站
    stock_info_url = 'https://gupiao.baidu.com/stock/'
    # 获取单个股票的价格的网页
    output_file = 'D://SpiderTest//BaiduStockInfo.txt'
    # 文件保存的连接
    slist = []
    getStockList(slist,stock_info_url)
    getStockInfo(slist,stock_info_url,output_file)
    
main()
  • 第二步,逐步完善各个步骤

    • 总是必须的获取相关页面的代码
def getHTMLText(url):
    try:
        r = requests.get(url)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return''
  • 获取相关的股票列表

这里有值得学习的东西,先获取所有的a标签,然后再逐个进行排除,如果是a标签,那就添加,不是那就跳过当前的循环,学会用try——except语句

def getStockList(lst,stockURL):
    html =  getHTMLText(stockURL)
    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))
        except:
            continue
  • 获取相关股票实时信息并将之写入相关的文件
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':'bets-name'})
            # 结合属性和名称,获取特定的标签

            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')
        except:
            traceback.print_exc()
         
            continue
  • 这里写的还是很好看的,分析一下,首先,看下图,百度股市通中,某单股的原码
  • 清晰可见,关于股票的信息都在对应的< div > … < /div >标签中,并且属性中的class是极特殊的class = ‘stock-bets’的
  • 而在< div > … < /div >的标签中的,a标签的值在对应的就是对应的信息,不同的信息他的属性又是不同
  • 在其子标签中dt和dd标签有都含有所有与该股票相关的信息
    在这里插入图片描述
  • 第一步,先获取最外层最特殊的div标签,并且说明属性
  stockInfo = soup.find('div',attrs={'class':'stock-bets'})
            # 结合属性和名称,获取特定的标签
  • 第二步,提取div标签的具有相关信息属性的标签,这个属性,就说明了这个标签代表的内容就是名字或者对应的信息
    • 注意:这里有一个注意点,这里标签的text属性,不是对应的string属性,text是输出所有的子节点和自身的string内容,用空格连接
      。string仅仅输出当前节点的string内容,如果有字节点,那就输出None
      详见 https://www.cnblogs.com/gl1573/archive/2018/11/14/9958716.html
   name = stockInfo.find_all(attrs={'class':'bets-name'})[0]
   infoDict.update({'股票名称':name.text.split()[0]})
  • 第三步,提取所有的dd标签和dt标签,二者的数量相同,并作为键值对进行保存
  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
  • 第四步,采用IO流进行写入,注意类型的转换
  with open(fpath,'a',encoding = 'utf-8') as f:
                f.write(str(infoDict) + '\n')
  • 最后一步,就是异常的处理,调用traceback库,进行异常的处理
  except:
            traceback.print_exc()
            continue
最后一步,代码的优化
  • 为了创造一个更好的用户体验,就创建了写入一个会实时显示进度的语块
  count = count + 1
  print('\r 当前进度:{:.2f}%'.format(count * 100 / len(lst)),end = "")

‘\r’会将输出的光标移到开头,覆盖原来的输出

总结
  • 关于搜索特定的标签,不仅仅是结合标签的名称,更是要结合标签的属性,通过属性和名称可以很好的对某一个标签进行定位
  • 关于try—except的处理,要知道引用traceback库函数,会反应出报错对的地方,不然不知道哪里出错很郁闷
  • 有一种设想,从一个网站爬取一定的数据或者项目序列,可以连续的爬取多个同类的网站
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章