前言:

在之前介绍requests的基础上,现在开始进行实战。

目标网站:http://q.10jqka.com.cn//index/index/board/all/field/zdf/order/desc/page/

一  涉及到的技术点:

(1)requests: 用于网页请求

(2)beautifulsoup:用于提取数据

(3)urllib.parse:用于拼接url

(4)cvs:用于保存结果

二 数据结构分析:

首先看下要抓取的数据的外观:

点击下一页发现在搜索框中的url并未发生变化,这个时候可以猜想,其数据加载的方式采用的ajax加载的方式,因此,右键—>“查看元素”,点击网络—>消息头,如下图:

可以发现第二页的url为:http://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/2/ajax/1/

点击下一页,可以发现第三页的url为:http://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/3/ajax/1/

从上面可以看出,不同页面的url的区别在于page后面的数字,可以再多看几个页面来验证这个猜想。

通过上面的分析,可以得出数据是通过ajax的方式加载出来的。接下来查看通过ajax加载的数据格式是什么样的。

点击 网络下面的响应,可以看到响应载荷,如下图:

通过url获取到部分数据如下:

<table class="m-table m-pager-table"><thead><tr><th style="width:4%">序号</th><th style="width:6%">代码</th><th style="width:8%">名称</th><th style="width:6%" ><a href="javascript:void(0)" field="xj" >现价<i></i></a></th><th style="width:8%"  class="cur"><a href="javascript:void(0)" field="zdf" order="desc"  class="desc">涨跌幅(%)<i></i></a></th><th style="width:6%" ><a href="javascript:void(0)" field="zd" >涨跌<i></i></a></th><th style="width:8%" ><a href="javascript:void(0)" field="zs" >涨速(%)<i></i></a></th><th style="width:8%" ><a href="javascript:void(0)" field="hs" >换手(%)<i></i></a></th><th style="width:6%" ><a href="javascript:void(0)" field="lb" >量比<i></i></a></th><th style="width:6%" ><a href="javascript:void(0)" field="zf" >振幅(%)<i></i></a></th><th style="width:7%" ><a href="javascript:void(0)" field="cje" >成交额<i></i></a></th><th style="width:8%" ><a href="javascript:void(0)" field="ltg" >流通股<i></i></a></th><th style="width:8%" ><a href="javascript:void(0)" field="ltsz" >流通市值<i></i></a></th><th style="width:7%" ><a href="javascript:void(0)" field="syl" >市盈率<i></i></a></th><!--th>概念题材</th--><th style="width:4%">加自选</th></tr></thead><tbody><tr><td>41</td><td><a href="http://stockpage.10jqka.com.cn/603718/" target="_blank">603718</a></td><td><a href="http://stockpage.10jqka.com.cn/603718/" target="_blank">海利生物</a></td><td class="c-rise">13.53</td><td class="c-rise">6.28</td><td class="c-rise">0.80</td><td class="c-fall">-0.15</td><td>1.53</td><td class="c-rise">1.75</td><td class="c-rise">7.86</td><td>1.32亿</td><td>6.44亿</td><td>87.13亿</td><td>140.56</td><td><a class="j_addStock" title="加自选" href="javascript:void(0);"><img src="http://i.thsi.cn/images/q/plus_logo.png" alt=""></a></td></tr><tr><td>42</td><td><a href="http://stockpage.10jqka.com.cn/002331/" target="_blank">002331</a></td><td><a href="http://stockpage.10jqka.com.cn/002331/" target="_blank">皖通科技</a></td><td class="c-rise">9.15</td><td class="c-rise">6.15</td><td class="c-rise">0.53</td><td class="">--</td><td>2.66</td><td class="c-rise">1.51</td><td class="c-rise">6.15</td><td>7247.43万</td><td>3.03亿</td><td>27.75亿</td><td>41.17</td><td><a class="j_addStock" title="加自选" href="javascript:void(0);"><img src="http://i.thsi.cn/images/q/plus_logo.png" alt=""></a></td></tr>

可以看到其数据都是包含在html的标签中。一个<tr>标签包含一个股票信息。

至此,数据分析部分已经完成。

三 需求分析及模块划分

同花顺股票网站具有很好的反扒能力,因此,需要增加一部分功能来应对这部分问题。在简单怕爬虫的基础上需要增加,改变请求头和增加代理的功能,因此整个函数的模块划分如下:

(1)代理获取模块

(2)url构建模块

(3)失败无限尝试模块

(4)下载模块

(5)解析及存储模块

(6)配置模块

四 模块设计

4.1 代理获取模块

代码如下:

 def proxy_get(self, num_retries=2):"""#代理获取模块"""try:r_proxy = requests.get(self.PROXY_POOL_API, timeout = 5)proxy = r_proxy.text    #指定代理print("代理是", proxy)proxies = {"http": 'http://' + proxy,"https": 'https://' + proxy,}return proxiesexcept:if num_retries > 0:print("代理获取失败,重新获取")
self.proxy_get(num_retries-1)

为了防止网络状况不佳等其他原因导致获取代理失败,增加了超时等待和失败重试功能

4.2  url 构建模块

在前文分析的基础上,得到不同页面的url的区别是数字这的不同,因此这部分的代码如下:

def url_yield(self):""":func 用于生成url:yield items"""for i in range(1, self.MAX_PAGE + 1 ):self.PAGE_TRACK = i         #页面追踪self.FLAG += 1              #每次加1print('FLAG 是:', self.FLAG)url = "{}{}{}".format(self.URL_START, i, self.PARAMS) yield url

使用yield函数,每次只返回一个url

4.3 失败无限尝试模块

将抓取失败的url,再次进行抓取

def url_omi(self):print("开始补漏")length_pl = len(self.PAGE_LIST) if length_pl != 0:          #判断是否为空for i in range(length_pl):self.PAGE_TRACK = self.PAGE_LIST.pop(0)                  #构造一个动态列表, 弹出第一个元素url = "{}{}{}".format(self.URL_START, self.PAGE_TRACK, self.PARAMS) yield url

4.4 下载模块

包含更换请求头,失败重试功能和代理是否变更的功能。

 def downloader(self, url, num_retries=3):if self.proxy_con == 0:proxies = self.proxy_get()  #获取代理else:proxies = self.proxy_save   #继续使用代理self.proxy_save = proxies       #更换代理值headers_list = [{'Accept': 'text/html, */*; q=0.01','Accept-Encoding': 'gzip, deflate, sdch','Accept-Language': 'zh-CN,zh;q=0.8','Connection': 'keep-alive','Cookie':'log=; Hm_lvt_78c58f01938e4d85eaf619eae71b4ed1=1533992361,1533998469,1533998895,1533998953; Hm_lpvt_78c58f01938e4d85eaf619eae71b4ed1=1533998953; user=MDrAz9H9akQ6Ok5vbmU6NTAwOjQ2OTU0MjIzNDo3LDExMTExMTExMTExLDQwOzQ0LDExLDQwOzYsMSw0MDs1LDEsNDA7MSwxLDQwOzIsMSw0MDszLDEsNDA7NSwxLDQwOzgsMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEsNDA6Ojo6NDU5NTQyMjM0OjE1MzM5OTkwNzU6OjoxNTMzOTk5MDYwOjg2NDAwOjA6MTZmOGFjOTgwMGNhMjFjZjRkMWZlMjk0NDQ4M2FhNDFkOmRlZmF1bHRfMjox; userid=459542234; u_name=%C0%CF%D1%FDjD; escapename=%25u8001%25u5996jD; ticket=7c92fb758f81dfa4399d0983f7ee5e53; v=Ajz6VIblS6HlDX_9PqmhBV0QDdH4NeBfYtn0Ixa9SCcK4daNPkWw77LpxLZl','hexin-v': 'AiDRI3i0b1qEZNNemO_FOZlE8SXqKQQBpg9Y4Jox7pbOH8oZQjnUg_YdKIHp','Host': 'q.10jqka.com.cn','Referer': 'http://q.10jqka.com.cn/','User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',},{'Accept': 'text/html, */*; q=0.01', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Connection': 'keep-alive', 'Cookie': 'user=MDq62tH9NUU6Ok5vbmU6NTAwOjQ2OTU0MjA4MDo3LDExMTExMTExMTExLDQwOzQ0LDExLDQwOzYsMSw0MDs1LDEsNDA7MSwxLDQwOzIsMSw0MDszLDEsNDA7NSwxLDQwOzgsMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEsNDA6Ojo6NDU5NTQyMDgwOjE1MzM5OTg4OTc6OjoxNTMzOTk4ODgwOjg2NDAwOjA6MTEwOTNhMzBkNTAxMWFlOTg0OWM1MzVjODA2NjQyMThmOmRlZmF1bHRfMjox; userid=459542080; u_name=%BA%DA%D1%FD5E; escapename=%25u9ed1%25u59965E; ticket=658289e5730da881ef99b521b65da6af; log=; Hm_lvt_78c58f01938e4d85eaf619eae71b4ed1=1533992361,1533998469,1533998895,1533998953; Hm_lpvt_78c58f01938e4d85eaf619eae71b4ed1=1533998953; v=AibgksC3Qd-feBV7t0kbK7PCd5e-B2rBPEueJRDPEskkk8xLeJe60Qzb7jDj', 'hexin-v': 'AiDRI3i0b1qEZNNemO_FOZlE8SXqKQQBpg9Y4Jox7pbOH8oZQjnUg_YdKIHp', 'Host': 'q.10jqka.com.cn', 'Referer': 'http://q.10jqka.com.cn/', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36', },{'Accept': 'text/html, */*; q=0.01', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Connection': 'keep-alive', 'Cookie': 'user=MDq62sm9wM%2FR%2FVk6Ok5vbmU6NTAwOjQ2OTU0MTY4MTo3LDExMTExMTExMTExLDQwOzQ0LDExLDQwOzYsMSw0MDs1LDEsNDA7MSwxLDQwOzIsMSw0MDszLDEsNDA7NSwxLDQwOzgsMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEsNDA6Ojo6NDU5NTQxNjgxOjE1MzM5OTg0NjI6OjoxNTMzOTk4NDYwOjg2NDAwOjA6MTAwNjE5YWExNjc2NDQ2MGE3ZGYxYjgxNDZlNzY3ODIwOmRlZmF1bHRfMjox; userid=459541681; u_name=%BA%DA%C9%BD%C0%CF%D1%FDY; escapename=%25u9ed1%25u5c71%25u8001%25u5996Y; ticket=4def626a5a60cc1d998231d7730d2947; log=; Hm_lvt_78c58f01938e4d85eaf619eae71b4ed1=1533992361,1533998469; Hm_lpvt_78c58f01938e4d85eaf619eae71b4ed1=1533998496; v=AvYwAjBHsS9PCEXLZexL20PSRyfuFzpQjFtutWDf4ll0o5zbyKeKYVzrvsAz', 'hexin-v': 'AiDRI3i0b1qEZNNemO_FOZlE8SXqKQQBpg9Y4Jox7pbOH8oZQjnUg_YdKIHp', 'Host': 'q.10jqka.com.cn', 'Referer': 'http://q.10jqka.com.cn/', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36', 'X-Requested-With': 'XMLHttpRequest'},{'Accept': 'text/html, */*; q=0.01', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Connection': 'keep-alive', 'Cookie': 'Hm_lvt_78c58f01938e4d85eaf619eae71b4ed1=1533992361; Hm_lpvt_78c58f01938e4d85eaf619eae71b4ed1=1533992361; user=MDq62sm9SnpsOjpOb25lOjUwMDo0Njk1NDE0MTM6NywxMTExMTExMTExMSw0MDs0NCwxMSw0MDs2LDEsNDA7NSwxLDQwOzEsMSw0MDsyLDEsNDA7MywxLDQwOzUsMSw0MDs4LDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxLDQwOjo6OjQ1OTU0MTQxMzoxNTMzOTk4MjA5Ojo6MTUzMzk5ODE2MDo4NjQwMDowOjFlYTE2YTBjYTU4MGNmYmJlZWJmZWExODQ3ODRjOTAxNDpkZWZhdWx0XzI6MQ%3D%3D; userid=459541413; u_name=%BA%DA%C9%BDJzl; escapename=%25u9ed1%25u5c71Jzl; ticket=b909a4542156f3781a86b8aaefce3007; v=ApheKMKxdxX9FluRdtjNUdGcac08gfwLXuXQj9KJ5FOGbTKxepHMm671oBoh', 'hexin-v': 'AiDRI3i0b1qEZNNemO_FOZlE8SXqKQQBpg9Y4Jox7pbOH8oZQjnUg_YdKIHp', 'Host': 'q.10jqka.com.cn', 'Referer': 'http://q.10jqka.com.cn/', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36', 'X-Requested-With': 'XMLHttpRequest'},]try:time.sleep(random.random()*5)   #设置延时headers = random.choice(headers_list)r = requests.get(url, headers = headers, proxies=proxies, timeout=4)except:if num_retries > 0:print("重新下载")self.proxy_con = 0  #更换代理self.downloader(url,num_retries-1)else:if not self.PAGE_TRACK in self.PAGE_LIST:    #首先应该判断 该页是否存在列表中,如果不存在, 则将其加入其中self.PAGE_LIST.append(self.PAGE_TRACK)   #将获取失败的url保存起来,后面再次循环利用,将元素添加在末尾,else:            return r.text

4.5 解析及存储模块

这部分用来进行解析并将结果存储到csv中

 def items_return(self):sys.setrecursionlimit(5000)count = 0while True:if self.FLAG < self.MAX_PAGE:url_list = self.url_yield()   #获取urlelse:url_list = self.url_omi()if len(PAGE_LIST) ==0:breakprint("执行到了获取模块")for url in url_list:html = self.downloader(url)#打印提示信息print('URL is:', url)items = {}   #建立一个空字典,用于信息存储try:                      soup = BeautifulSoup(html, 'lxml')for tr in soup.find('tbody').find_all('tr'):td_list = tr.find_all('td')items['代码'] = td_list[1].stringitems['名称'] = td_list[2].stringitems['现价'] = td_list[3].stringitems['涨跌幅'] = td_list[4].stringself.writer.writerow(items)print(items)print("保存成功")#如果保存成功,则继续使用代理self.proxy_con = 1#print("解析成功")#yield items          #将结果返回except:print("解析失败")#解析失败,则将代理换掉self.proxy_con = 0   #print(html)if not self.PAGE_TRACK in self.PAGE_LIST:self.PAGE_LIST.append(self.PAGE_TRACK)else:count += 1if count == 2:break

4.5 配置模块

为了方便项目的管理,可以将部分参数的配置放到一个setting.py文件中

#必要参数设置
MAX_PAGE = 165   #最大页数
PAGE_TRACK = 1   #追踪到了第几页
MAX_GET = 1      #获取最大尝试次数
MAX_PARSE = 1    #解析尝试最大次数
MAX_CSV = 1      #文件保存最大次数
MAX_PROXY =1     #获取代理的最大次数
MAX_START = 1    #MAX_*的初始值
MAX_TRY = 4      #最大尝试次数
FLAG = 0         #用于标识,是否使用 url_omi() 函数#初始链接
URL_START = "http://q.10jqka.com.cn//index/index/board/all/field/zdf/order/desc/page/"
PARAMS = "/ajax/1/"#第一次爬取的 html 缺失的页面 的url 列表
#先进先出的列表
PAGE_LIST = [] #代理池接口
PROXY_POOL_API = "http://127.0.0.1:5555/random"  headers = {'Accept': 'text/html, */*; q=0.01','Accept-Encoding': 'gzip, deflate, sdch','Accept-Language': 'zh-CN,zh;q=0.8','Connection': 'keep-alive','Cookie': 'spversion=20130314; __utma=156575163.1163133091.1530233537.1530289428.1530369413.3; __utmz=156575163.1530369413.3.3.utmcsr=stockpage.10jqka.com.cn|utmccn=(referral)|utmcmd=referral|utmcct=/; Hm_lvt_78c58f01938e4d85eaf619eae71b4ed1=1530444468,1530505958,1530506333,1530516152; Hm_lpvt_78c58f01938e4d85eaf619eae71b4ed1=1530516152; historystock=300033%7C*%7C1A0001; v=AiDRI3i0b1qEZNNemO_FOZlE8SXqKQQBpg9Y4Jox7pbOH8oZQjnUg_YdKIHp','hexin-v': 'AiDRI3i0b1qEZNNemO_FOZlE8SXqKQQBpg9Y4Jox7pbOH8oZQjnUg_YdKIHp','Host': 'q.10jqka.com.cn','Referer': 'http://q.10jqka.com.cn/','User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest'}

至此,整个项目已经完成。

后记:

源码获取可以关注公众号,发送“ths”即可获取下载链接。另外公众号还会介绍大数据的相关知识,如hadoop, flink, spark

等,欢迎关注。

python爬虫实战-抓取同花顺股票信息相关推荐

  1. Python爬虫实战---抓取图书馆借阅信息

    Python爬虫实战---抓取图书馆借阅信息 原创作品,引用请表明出处:Python爬虫实战---抓取图书馆借阅信息 前段时间在图书馆借了很多书,借得多了就容易忘记每本书的应还日期,老是担心自己会违约 ...

  2. python爬虫招聘-Python爬虫实战-抓取boss直聘招聘信息

    实战内容:爬取boss直聘的岗位信息,存储在数据库,最后通过可视化展示出来 PS注意:很多人学Python过程中会遇到各种烦恼问题,没有人帮答疑容易放弃.为此小编建了个Python全栈免费答疑.裙 : ...

  3. python 爬虫实战 抓取学校bbs相关板块的发帖信息

    1. 前言 之前也因为感兴趣, 写过一个抓取桌面天空里面喜欢的动漫壁纸的爬虫代码.这两天突然看到有人写了这么一篇文章: 爬取京东本周热卖商品基本信息存入MySQL 觉得蛮有趣的, 正好临近找工作的季节 ...

  4. 【第4篇】Python爬虫实战-抓取B站弹幕视频

    目录 1.获取视频cid参数 2.程序源代码 3.程序运行结果 4.总结 1.获取视频cid参数 首先我们打开一个有弹幕的B站视频,比如:<我好像在哪见过你>人们把难言的爱都埋入土壤里_哔 ...

  5. Python爬虫实战 | 抓取小说网完结小说斗罗大陆

    储备知识应有:Python语言程序设计 Python网络爬虫与信息提取 两门课程都是中国大学MOOC的精彩课程,特别推荐初学者.环境Python3 本文整体思路是:1.获取小说目录页面,解析目录页面, ...

  6. Python爬虫实战抓取十一旅游最优惠的机票!

    目的 获取去哪儿默认页面的机票航班信息 详细需求 目标URL:https://m.flight.qunar.com/h5/flight/ 源码实现 #!/usr/bin/env python # -* ...

  7. python爬取boss直聘招聘信息_Python爬虫实战-抓取boss直聘招聘信息

    Python Python开发 Python语言 Python爬虫实战-抓取boss直聘招聘信息 实战内容:爬取boss直聘的岗位信息,存储在数据库,最后通过可视化展示出来 PS注意:很多人学Pyth ...

  8. python爬虫实战-爬取微信公众号所有历史文章 - (00) 概述

    http://efonfighting.imwork.net 欢迎关注微信公众号"一番码客"获取免费下载服务与源码,并及时接收最新文章推送. 最近几年随着人工智能和大数据的兴起,p ...

  9. python爬网页数据用什么_初学者如何用“python爬虫”技术抓取网页数据?

    原标题:初学者如何用"python爬虫"技术抓取网页数据? 在当今社会,互联网上充斥着许多有用的数据.我们只需要耐心观察并添加一些技术手段即可获得大量有价值的数据.而这里的&quo ...

最新文章

  1. qunee for html5 api,Qunee for HTML5 - 中文 : 常见问题
  2. html标题电脑快速输入,快速把纸上文字输入到电脑中的技巧
  3. C++重载和重写的条件以及重写后对基类函数的覆盖
  4. 将下载都是大写字母的网页里面的html转换为小写的简单方式
  5. 03bash特性详解
  6. openssl req
  7. 20135302魏静静——linux课程第三周实验及总结
  8. WPF如何得到一个在用户控件内部的元素的坐标位置
  9. 浅谈SQL注入攻击与防御(适用于小白观看)
  10. 接口文档模板,接口规范
  11. 弄清楚DL,D-H,CDH problem,CDH assumption,DDH,BDDH,BCDH
  12. 【学习笔记】seckill-秒杀项目--(2)登录功能及完善
  13. IDEA 2019 激活码(注册码)
  14. iphone怎么找本地音乐_为什么iPhone会发出蜂鸣声或振动? 这是找出方法
  15. 数据可视化与大数据分析
  16. 针对m3u8视频加密的一些尝试
  17. 重磅!大基金、华为、小米共同投资这家芯片公司!
  18. Kubernetes学习笔记(二):Pod控制器详解:资源元信息、ReplicaSet、Deployment、DaemonSet、Job、CronJob
  19. gensim LDA模型提取每篇文档所属主题(概率最大主题所在)
  20. 《大数据之路:阿里巴巴大数据实践》

热门文章

  1. python 16进制与图片互转
  2. Markdown插入图片 详细例子(本地图片,网络图片,base64) Windows
  3. 中科蓝汛通过蓝牙地址判断左右声道
  4. ntp的server的上游跳变对ntp的server及client的影响
  5. 解决URLToPDF 微信公众号文章图片不显示问题(全网唯一方案)
  6. Vue2解决axios跨域请求问题
  7. PCB走线宽度与铜箔厚度与电流的关系
  8. qpython op怎么用_QPython OPAPP推广手机版下载
  9. iphone 自定义控件,通讯录,网络,电子书,控件特效 等源码
  10. 微信小程序年审与支付规则