热门搜索 :
考研考公
您的当前位置:首页正文

(五)"股票数据定向爬虫"(学习笔记)|Py

来源:东饰资讯网

1."股票数据定向爬虫"实例介绍
2."股票数据定向爬虫"代码及显示结果
3."股票数据定向爬虫"实例编写
4."股票数据定向爬虫"实例优化
5.单元小结

最近更新:2018-01-19

1."股票数据定向爬虫"实例介绍

1.1功能描述

1.2候选数据网站的选择


  • 打开"新浪股票" 确定一个股票,然后按F12,查找价格,在源代码找不到,推测不是静态存在于HTML页面中.因此本例不适应
  • 打开"百度股市通
    市"
    确定其中一个股票的价格,比如,我选择易联众,价格是12.16.查看页面源代码,查看价格12.16对应的位置区域,说明对应百度股票来讲,每一只股票信息写在html代码中.

  • 相比这两个网站,百度股市通更适合定向爬虫爬取数据来源.
  • 确定数据来源之后,还要确立当前股票市场所有的股票列表.在百度股票中,我们很难找到一个页面,包含所有的股票信息.我们这里使用另外一个网站叫
    适合获取所有的股票信息.

1.3程序的结构设计

我们点击百度股票各股的信息.我看一下浏览器的显示.我们发现在百度股票中,每一个各股的网页都有一个各股的编号.作为网页地址的一部分.而这个编号恰巧是股票对应的深圳交易所或上海交易所的股票代码.由此我们构造一个程序结构.大概分为三个步骤:


  • 百度各股信息的源代码的描述情况.百度股票的个股信息是采用截图图这样的方式存储的,具体如下:


  • 在我们设计程序的时候,可以考虑参照页面这种存储信息的方式对每一个信息源以及信息的值做相关的标定,其实就是一个键值对.那我们就可以利用一种键值对的数据结构来维护.在python程序中,字典类型,维护键值对的数据类型.我们可以用字典来保持各股的相关信息.然后再用字典把所有股票的信息记录起来.最终用他来记录中间结构,最终把这个结构输出到文件中.

2."股票数据定向爬虫"代码及显示结果

2.1代码显示结果

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 ""

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

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:
            count = count + 1
            print("\r当前进度: {:.2f}%".format(count * 100 / len(lst)), end="")
            continue
def main():
    stock_list_url = 
    stock_info_url = 
    output_file = 'D:/BaiduStockInfo.txt'
    slist = []
    getStockList(slist, stock_list_url)
    getStockInfo(slist, stock_info_url, output_file)
main()

3."股票数据定向爬虫"实例编写

3.1流程框架设计

整个程序定义四个函数的设计,具体如下:

  • getHTMLText(url),是获得url的页面.
def getHTMLText(url):
    return ""
  • def getStockList(lst,stockURL),是获得股票的信息列表.这个函数有两个参数.
    • 首先第一个参数是列表保持的列表类型,里面存储了所有的股票信息.
    • 第二个参数是获得股票的URL网站.
def getStockList(lst,stockURL):
    return ""
  • getStockInfo(lst,stockURL,fpath),是获得每一只个股的股票信息,并且把它存储在数据结构.这个函数有三个参数,如下:
    • 第一个lst是保存所有股票的信息列表.
    • 第二个stockURL获得股票信息的url网站.
    • 第三个fpath以及将来要把信息存到文件的文件路径.
def getStockInfo(lst,stockURL,fpath):
    return ""
  • main(),定义主程序.具体如下:
    • 这里有两个url链接,一个获得股票列表的链接,一个是获取股票信息的链接的主体部分.
    • 储存的文件是保持在D盘的根目录下.
    • 股票的信息存储在slist上.
    • 我们调用之前定义的两个函数,首先用getStockList(),获得股票列表.其次用getStockInfo()根据股票列表到相关网站上获取股票信息,并存储在相关文件中.
def main():
    stock_list_url = 
    stock_info_url = 
    output_file = 'D:/BaiduStockInfo.txt'
    slist = []
    getStockList(slist, stock_list_url)
    getStockInfo(slist, stock_info_url, output_file)
  • 调用main(),使整个程序运行起来.
main()

整个程序的主体框架编写完成

3.2具体函数的介绍

3.1.1 getHTMLText()

这个函数运用过很多次,因此直接将以前的代码套用即可.

def getHTMLText(url,code="utf-8"):
  try:
        r=requests.get(url)
        r.raise_for_status()
        r.encoding=code
        return r.text
  except:
        return ""
3.1.2 getStockList()
  • 用getHTMLText()获得一个页面.
  • 用 BeautifulSoup去解析这个页面,找到所有的a标签.
  • 找a标签用fine_all这个方法
  • 对a标签每一个进行遍历,来做相关的处理,具体如下:
    • 去找到每一个a标签的属性,并且判断属性的链接,把链接后面的数字提取出来.可以采取正则表达式的方式进行匹配.
    • 因为深圳和上海交易所的股票代码有一定的规则性.上海交易所的代码是以sh开头,深圳交易所的代码是以sz开头,而股票的数据是以6位数字组成,所以我们可以构造一个正则表达式.在链接中寻找此类型的表达式,并且提取出来.
    • 还需要考虑全页面中包含很多的a标签,不止是记录股票代码的a标签,还有记录其他任何链接的a标签.所有的a标签不一定都符合正则表达式,中间可能会出现各种各样的错误和异常,采用try and except,将统一的非正常模式,纳入到一个except的管理.如果出现异常,说明不是我们解析的范围,我们直接continue,使程序继续运行即可.
    • 定义正则表达式 [s][hz]\d{6},意思是以s为开头,中间以h或z字符,后面有6个数字,在所有的a标签链接域去找它,如果匹配则输出,并且存储在lst,
  • 通过这个方式能将东方财富网所有的股票的信息保存起来.
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
3.1.3 getStockList()

需要知道股票个股信息在百度股票网站上显示的源代码.随便找了一只个股易联众,在页面源代码中查找确定当天价格12.07作为搜索,如下:


在搜索结果的区域有很多与个股相关的信息,这些信息就是我们要获得的信息,这些信息封装在一个html的格式中如下:
  • 首先向每一个个股发起请求,个股的股票编号存储在lst,也就是个股的股票编号是在东方财富网获得的.使用一个for循环,如下:
    • 用百度的链接+每个个股的链接,形成一个访问个股页面的url
    • 用getHTMLText函数来获取这个页面的内容.
    • 在分析html这个页面的过程中可能会出现很多的问题和异常.用 try and except 来解决所有的异常情况.在ry and except的框架下,判断当前的页面是否为空页面,如果是空页面,则继续执行.
    • 再定义一个字典,这个字典信息,存储这个页面返回或记录的所有个股信息.
    • 用来构建一个解析网页的类型.
    • 在源代码中,我们可以看到所有的股票信息封装在div标签属性为class="stock-bets",所以我们可以搜索这个标签,找到这个股票所存在大标签的信息,我们定义为stockInfo.获得div标签后,我们要进一步查找,查找的第一个内容就是股票名称,股票名称封装在bets-name标签中属性标签内.
      -然后将这个信息增加到字典中,这里使用split函数来获得股票对应名称的完整部分.因为我们看到有些名称后面还关联了其他的标识符,采用空格分开后,获得其中的第一部分,也就是完整的股票名称,其余部分则舍弃.
    • 我们在看股票的信息部分存储在dt/dd标签中,其中dt标签表明属性信息键的域,其中dd标签表明股票信息值的域,用fine_all的方法可以找到所有键的域和所有值的域.keyList和valueList是所有键值对的列表.
    • 对所有的键值对列表进行赋值,还原为键值对,并存储在字典中.采用for循环的方式.字典的用法是[key]=val,向字典新增内容.
    • 把所有的内容存储在文件中,把相关的信息保存在文件里
    • 为能够获得出错的时候以及出现异常的时候,知道哪些地方发生了异常,用traceback获得其中的错误信息.
  • 理解每一行全代码的含义,尤其是处理个股信息的页面中使用的BeautifulSoup和正则表达式所表示的代码内容.
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:
            count = count + 1
            print("\r当前进度: {:.2f}%".format(count * 100 / len(lst)), end="")
            continue

4"股票数据定向爬虫"实例优化

4.1速度提高:编码识别的优化

对"股票数据定向爬虫"进行小优化,优化的目的是提高用户体验,即提高速度.只要采用requests以及BeautifulSoup都不会提高速度.大家对爬虫速度有很高的要求,用scrapy库.只提一个小区域代码的地方,提高速度,这个代码位置就是encoding.


  • r.apparent是将获得的html文本页面中的内容进行分析,由程序来判断文本可能使用的编码方式.
    • r.encoding是从html头文件中去解析可能会遇到什么样的coding方式,很显然apparent_encoding需要很多时间,几乎需要分析文本中所有的内容.
    • 对于我们编写的定向爬虫,尤其是爬取的网站是固定的情况下,先用手工的方式获得编码的类型.apparent_encoding是什么样编码,直接赋给encoding就可以了 .
    • 这个变量默认的是"utf-8",用code赋值给encoding这样能节约不少时间.

修改前


修改后


  • 东方财富网的编码是"GB2312"编码,获取URL过程中直接把这个编码赋值给这个函数.

修改前


修改后


  • 因百度股票编码是"utf-8",因此不需要改动.

4.2体验提高:增加动态进度显示

在爬取的过程中,增加动态的显示,也就是代码在爬取页面的过程中,可能要爬取很多的页面,股票数据而言,有4000多个页面,需要一种动态的方法来显示进度.修改代码,增加一种不换行就可以显示的进度条.增加一个计数变量count,把初值赋为0,增加一个进度条,这个进度条打印当前爬取进度的百分比.



修改前


修改后

  • 是以股票列表的长度作为计数,当前的计数作为分子部分,这样获得比例.写一个print这样的字符串输出,进度条每条执行之后都会换行,并不是我们见到那种不换行的进度条,为了实现不换行的进度条.需要用到一个转义符,\r特殊空字符,\r能将打印的字符串最后的光标提到当前这一行的头部,下一次进行相关打印的时候,打印的信息就会覆盖之前打印的信息,这样实现了不换行动态变化的信息展示,

5.单元小结

  • 爬取数据来源的时候要注意它使用的编写代码是否为js动态的数据,还是html静态保持了数据的内容.这个路线只能爬取html页面存在的内容.
  • 数据内容检索中试图合理的使用BeautifulSoup库与正则表达式库的方法并且能够很好的两则结合,获取想要的内容.对有非常特征的数据,可以直接用正则表达式进行获取.存在区域相对固定,可以用beautifulSoup库定位到相关位置,再用正则表达式获取其中的内容.
  • 实现了一些优化,动态滚动条,可以用在其他的例子中.
  • 好的程序好在用户体验上,而非功能上.
Top