python爬虫成长之路(一):抓取证券之星的股票数据
获取数据是数据分析中必不可少的一部分,而网络爬虫是是获取数据的一个重要渠道之一。鉴于此,我拾起了Python这把利器,开启了网络爬虫之路。
本篇使用的版本为python3.5,意在抓取证券之星上当天所有A股数据。程序主要分为三个部分:网页源码的获取、所需内容的提取、所得结果的整理。
一、网页源码的获取
很多人喜欢用python爬虫的原因之一就是它容易上手。只需以下几行代码既可抓取大部分网页的源码。
import urllib.request
url='http://quote.stockstar.com/stock/ranklist_a_3_1_1.html' #目标网址
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64)"} #伪装浏览器请求报头
request=urllib.request.Request(url=url,headers=headers) #请求服务器
response=urllib.request.urlopen(request) #服务器应答
content=response.read().decode('gbk') #以一定的编码方式查看源码
print(content) #打印页面源码
虽说抓一页的源码容易,不过在一个网站内大量抓取网页源码却经常遭到服务器拦截,顿时感觉世界充满了恶意。于是我开始研习突破反爬虫限制的功法。
1.伪装流浪器报头
很多服务器通过浏览器发给它的报头来确认是否是人类用户,所以我们可以通过模仿浏览器的行为构造请求报头给服务器发送请求。服务器会识别其中的一些参数来识别你是否是人类用户,很多网站都会识别User-Agent这个参数,所以请求头最好带上。有一些警觉性比较高的网站可能还会通过其他参数识别,比如通过Accept-Language来辨别你是否是人类用户,一些有防盗链功能的网站还得带上referer这个参数等等。
2.随机生成UA
证券之星只需带User-Agent这个参数就可以抓取页面信息了,不过连续抓取几页就被服务器阻止了。于是我决定每次抓取数据时模拟不同的浏览器发送请求,而服务器通过User-Agent来识别不同浏览器,所以每次爬取页面可以通过随机生成不同的UA构造报头去请求服务器,
3.减慢爬取速度
虽然模拟了不同浏览器爬取数据,但发现有的时间段可以爬取上百页的数据,有时候却只能爬取十来页,看来服务器还会根据你的访问的频率来识别你是人类用户还是网络爬虫。所以我每抓取一页都让它随机休息几秒,加入此句代码后,每个时间段都能爬取大量股票数据了。
4.使用代理IP
天有不测风云,程序在公司时顺利测试成功,回寝室后发现又只能抓取几页就被服务器阻止了。惊慌失措的我赶紧询问度娘,获知服务器可以识别你的IP,并记录此IP访问的次数,可以使用高匿的代理IP,并在抓取的过程中不断的更换,让服务器无法找出谁是真凶。此功还未修成,欲知后事如何,请听下回分解。
5.其他突破反爬虫限制的方法
很多服务器在接受浏览器请求时会发送一个cookie文件给浏览器,然后通过cookie来跟踪你的访问过程,为了不让服务器识别出你是爬虫,建议最好带上cookie一起去爬取数据;如果遇上要模拟登陆的网站,为了不让自己的账号被拉黑,可以申请大量的账号,然后再爬入,此处涉及模拟登陆、验证码识别等知识,暂时不再深究...总之,对于网站主人来说,有些爬虫确实是令人讨厌的,所以会想出很多方法限制爬虫的进入,所以我们在强行进入之后也得注意些礼仪,别把人家的网站给拖垮了。
二、所需内容的提取
获取网页源码后,我们就可以从中提取我们所需要的数据了。从源码中获取所需信息的方法有很多,使用正则表达式就是比较经典的方法之一。我们先来看所采集网页源码的部分内容。
为了减少干扰,我先用正则表达式从整个页面源码中匹配出以上的主体部分,然后从主体部分中匹配出每只股票的信息。代码如下。
pattern=re.compile('<tbody[\s\S]*</tbody>')
body=re.findall(pattern,str(content)) #匹配<tbody和</tbody>之间的所有代码
pattern=re.compile('>(.*?)<')
stock_page=re.findall(pattern,body[0]) #匹配>和<之间的所有信息
其中compile方法为编译匹配模式,findall方法用此匹配模式去匹配出所需信息,并以列表的方式返回。正则表达式的语法还挺多的,下面我只罗列所用到符号的含义。
语法 | 说明 |
. | 匹配任意除换行符“\n”外的字符 |
* | 匹配前一个字符0次或无限次 |
? | 匹配前一个字符0次或一次 |
\s | 空白字符:[<空格>\t\r\n\f\v] |
\S | 非空白字符:[^\s] |
[...] | 字符集,对应的位置可以是字符集中任意字符 |
(...) | 被括起来的表达式将作为分组,里面一般为我们所需提取的内容 |
正则表达式的语法挺多的,也许有大牛只要一句正则表达式就可提取我想提取的内容。在提取股票主体部分代码时发现有人用xpath表达式提取显得更简洁一些,看来页面解析也有很长的一段路要走。
三、所得结果的整理
通过非贪婪模式(.*?)匹配>和<之间的所有数据,会匹配出一些空白字符出来,所以我们采用如下代码把空白字符移除。
stock_last=stock_total[:] #stock_total:匹配出的股票数据
for data in stock_total: #stock_last:整理后的股票数据
if data=='':
stock_last.remove('')
最后,我们可以打印几列数据看下效果,代码如下
print('代码','\t','简称',' ','\t','最新价','\t','涨跌幅','\t','涨跌额','\t','5分钟涨幅')
for i in range(0,len(stock_last),13): #网页总共有13列数据
print(stock_last[i],'\t',stock_last[i+1],' ','\t',stock_last[i+2],' ','\t',stock_last[i+3],' ','\t',stock_last[i+4],' ','\t',stock_last[i+5])
打印的部分结果如下
抓取证券之星上当天所有A股数据的最终程序如下
import urllib
import urllib.request
import re
import random
import time
#抓取所需内容
user_agent = ["Mozilla/5.0 (Windows NT 10.0; WOW64)", 'Mozilla/5.0 (Windows NT 6.3; WOW64)',
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36',
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; rv:11.0) like Gecko)',
'Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1',
'Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3',
'Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12',
'Opera/9.27 (Windows NT 5.2; U; zh-cn)',
'Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0',
'Opera/8.0 (Macintosh; PPC Mac OS X; U; en)',
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Win64; x64; Trident/4.0)',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)',
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E)',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Maxthon/4.0.6.2000 Chrome/26.0.1410.43 Safari/537.1 ',
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E; QQBrowser/7.3.9825.400)',
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0 ',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.92 Safari/537.1 LBBROWSER',
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; BIDUBrowser 2.x)',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/3.0 Safari/536.11']
stock_total=[] #stock_total:所有页面的股票数据 stock_page:某页的股票数据
for page in range(1,8):
url='http://quote.stockstar.com/stock/ranklist_a_3_1_'+str(page)+'.html'
request=urllib.request.Request(url=url,headers={"User-Agent":random.choice(user_agent)})#随机从user_agent列表中抽取一个元素
try:
response=urllib.request.urlopen(request)
except urllib.error.HTTPError as e: #异常检测
print('page=',page,'',e.code)
except urllib.error.URLError as e:
print('page=',page,'',e.reason)
content=response.read().decode('gbk') #读取网页内容
print('get page',page) #打印成功获取的页码
pattern=re.compile('<tbody[\s\S]*</tbody>')
body=re.findall(pattern,str(content))
pattern=re.compile('>(.*?)<')
stock_page=re.findall(pattern,body[0]) #正则匹配
stock_total.extend(stock_page)
time.sleep(random.randrange(1,4)) #每抓一页随机休眠几秒,数值可根据实际情况改动
#删除空白字符
stock_last=stock_total[:] #stock_last为最终所要得到的股票数据
for data in stock_total:
if data=='':
stock_last.remove('')
#打印部分结果
print('代码','\t','简称',' ','\t','最新价','\t','涨跌幅','\t','涨跌额','\t','5分钟涨幅')
for i in range(0,len(stock_last),13): #原网页有13列数据,所以步长为13
print(stock_last[i],'\t',stock_last[i+1],' ','\t',stock_last[i+2],' ','\t',stock_last[i+3],' ','\t',stock_last[i+4],' ','\t',stock_last[i+5])
python爬虫实例
python爬虫成长之路(一):抓取证券之星的股票数据的更多相关文章
- python爬虫之分析Ajax请求抓取抓取今日头条街拍美图(七)
python爬虫之分析Ajax请求抓取抓取今日头条街拍美图 一.分析网站 1.进入浏览器,搜索今日头条,在搜索栏搜索街拍,然后选择图集这一栏. 2.按F12打开开发者工具,刷新网页,这时网页回弹到综合 ...
- python爬虫构建代理ip池抓取数据库的示例代码
爬虫的小伙伴,肯定经常遇到ip被封的情况,而现在网络上的代理ip免费的已经很难找了,那么现在就用python的requests库从爬取代理ip,创建一个ip代理池,以备使用. 本代码包括ip的爬取,检 ...
- [Python爬虫] 之八:Selenium +phantomjs抓取微博数据
基本思路:在登录状态下,打开首页,利用高级搜索框输入需要查询的条件,点击搜索链接进行搜索.如果数据有多页,每页数据是20条件,读取页数 然后循环页数,对每页数据进行抓取数据. 在实践过程中发现一个问题 ...
- python爬虫成长之路(二):抓取代理IP并多线程验证
上回说到,突破反爬虫限制的方法之一就是多用几个代理IP,但前提是我们得拥有有效的代理IP,下面我们来介绍抓取代理IP并多线程快速验证其有效性的过程. 一.抓取代理IP 提供免费代理IP的网站还挺多的, ...
- scrapy爬虫成长日记之将抓取内容写入mysql数据库
前面小试了一下scrapy抓取博客园的博客(您可在此查看scrapy爬虫成长日记之创建工程-抽取数据-保存为json格式的数据),但是前面抓取的数据时保存为json格式的文本文件中的.这很显然不满足我 ...
- Python爬虫实战:使用Selenium抓取QQ空间好友说说
前面我们接触到的,都是使用requests+BeautifulSoup组合对静态网页进行请求和数据解析,若是JS生成的内容,也介绍了通过寻找API借口来获取数据. 但是有的时候,网页数据由JS生成,A ...
- Python爬虫抓取东方财富网股票数据并实现MySQL数据库存储
Python爬虫可以说是好玩又好用了.现想利用Python爬取网页股票数据保存到本地csv数据文件中,同时想把股票数据保存到MySQL数据库中.需求有了,剩下的就是实现了. 在开始之前,保证已经安装好 ...
- Python爬虫入门教程 46-100 Charles抓取手机收音机-手机APP爬虫部分
1. 手机收音机-爬前叨叨 今天选了一下,咱盘哪个APP呢,原计划是弄荔枝APP,结果发现竟然没有抓到数据,很遗憾,只能找个没那么圆润的了.搜了一下,找到一个手机收音机 下载量也是不错的. 2. 爬虫 ...
- Python爬虫入门教程 45-100 Charles抓取兔儿故事-下载小猪佩奇故事-手机APP爬虫部分
1. Charles抓取兔儿故事背景介绍 之前已经安装了Charles,接下来我将用两篇博客简单写一下关于Charles的使用,今天抓取一下兔儿故事里面关于小猪佩奇的故事. 爬虫编写起来核心的重点是分 ...
随机推荐
- Java程序:从命令行接收多个数字,求和并输出结果
一.设计思想:由于命令行接收的是字符串类型,因此应先将字符串类型转化为整型或其他字符型,然后利用for循环求和并输出结果 二.程序流程图: 三.源程序代码: //王荣荣 2016/9/23 ...
- [转载]网站地址栏小图标favicon.ico的制作方法
有人也许会好奇,有的网址前面有个漂亮的小图标而且有的网站图标还会动,这是怎么做到的呢? 如下图所示: 那个小图标有个名字叫favicon.ico,网站图标虽小但可以起到很好的点缀作用,尤其是当浏览者将 ...
- javaScript中的小细节-script标签中的预解析
首先介绍预解析,虽然预解析字面意思很好理解,但是却是出坑出的最多的地方,也是bug经常会有的地方,利用好预解析的特性可以解决很多问题,并且提高代码的质量及数量,浏览器在解析代码前会把变量的声明和函数( ...
- C#事件-使用事件需要的步骤
事件是C#中另一高级概念,使用方法和委托相关.奥运会参加百米的田径运动员听到枪声,比赛立即进行.其中枪声是事件,而运动员比赛就是这个事件发生后的动作.不参加该项比赛的人对枪声没有反应. 从程序员的角度 ...
- Maven安装
开发分布式的商场系统,用到了一些新的技术,做一个记录和分享 这里讲一下maven安装 首先什么是Maven Maven作为一个构建工具,不仅帮我们自动化构建,还能抽象构建过程,提供构建任务实现.他跨平 ...
- Atiti.大企业病与小企业病 大公司病与小公司病
Atiti.大企业病与小企业病 大公司病与小公司病 1. 大企业病,一般会符合机构臃肿 .多重领导 .人才流失的特点.1 2. 大企业病避免方法1 3. 小企业病 1 3.1.1. 表现1 4. 如何 ...
- Oracle 分页
--1:无ORDER BY排序的写法.(效率最高) --(经过测试,此方法成本最低,只嵌套一层,速度最快!即使查询的数据量再大,也几乎不受影响,速度依然!) SELECT * FROM (SELECT ...
- Linux实战教学笔记06:Linux系统基础优化
第六节 Linux系统基础优化 标签(空格分隔):Linux实战教学笔记-陈思齐 第1章 基础环境 第2章 使用网易163镜像做yum源 默认国外的yum源速度很慢,所以换成国内的. 第一步:先备份 ...
- BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]
2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3352 Solved: 919[Submit][Stat ...
- REGEX例子
作为REGEX的例子,代码9.3显示了一个给定的文件有多少行,具有给定的模式,通过命令行输入(注:有更有效率的方式来实现这个功能,如Unix下的grep命令,在这里只是给出了另一种方式).这个程序像下 ...