一、如何用python 爬虫抓取金融数据
获取数据是数据分析中必不可少的一部分,而网络爬虫是是获取数据的一个重要渠道之一。鉴于此,我拾起了Python这把利器,开启了网络爬虫之路。
本篇使用的版本为python3.5,意在抓取证券之星上当天所有A股数据。程序主要分为三个部分:网页源码的获取、所需内容的提取、所得结果的整理。
一、网页源码的获取
很多人喜欢用python爬虫的原因之一就是它容易上手。只需以下几行代码既可抓取大部分网页的源码。
import urllib.request
url='ar.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])
二、python爬虫抓取电影top20排名怎么写
初步接触python爬虫(其实python也是才起步),发现一段代码研究了一下,觉得还比较有用处,Mark下。
上代码:
#!/usr/bin/python#coding=utf-8#Author: Andrew_liu#mender:cy"""
一个简单的Python爬虫,用于抓取豆瓣电影Top前100的电影的名称
Anthor: Andrew_liu
mender:cy
Version: 0.0.2
Date: 2017-03-02
Language: Python2.7.12
Editor: JetBrains PyCharm 4.5.4
"""import stringimport reimport urllib2import timeclass DouBanSpider(object):
"""类的简要说明
主要用于抓取豆瓣Top100的电影名称
Attributes:
page:用于表示当前所处的抓取页面
cur_url:用于表示当前争取抓取页面的url
datas:存储处理好的抓取到的电影名称
_top_num:用于记录当前的top号码
"""
def __init__(self):
self.page= 1
self.cur_url="h0?start={page}&filter=&type="
self.datas= []
self._top_num= 1
print u"豆瓣电影爬虫准备就绪,准备爬取数据..."
def get_page(self, cur_page):
"""
根据当前页码爬取网页HTML
Args:
cur_page:表示当前所抓取的网站页码
Returns:
返回抓取到整个页面的HTML(unicode编码)
Raises:
URLError:url引发的异常
"""
url= self.cur_url try:
my_page= urllib2.urlopen(url.format(page=(cur_page- 1)* 25)).read().decode("utf-8") except urllib2.URLError, e: if hasattr(e,"code"): print"The server couldn't fulfill the request."
print"Error code:%s"% e.code elif hasattr(e,"reason"): print"We failed to reach a server. Please check your url and read the Reason"
print"Reason:%s"% e.reason return my_page def find_title(self, my_page):
"""
通过返回的整个网页HTML,正则匹配前100的电影名称
Args:
my_page:传入页面的HTML文本用于正则匹配
"""
temp_data= []
movie_items= re.findall(r'<span.*?class="title">(.*?)</span>', my_page, re.S) for index, item in enumerate(movie_items): if item.find(" ")==-1:
temp_data.append("Top"+ str(self._top_num)+""+ item)
self._top_num+= 1
self.datas.extend(temp_data) def start_spider(self):
"""
爬虫入口,并控制爬虫抓取页面的范围
"""
while self.page<= 4:
my_page= self.get_page(self.page)
self.find_title(my_page)
self.page+= 1def main():
print u"""
###############################
一个简单的豆瓣电影前100爬虫
Author: Andrew_liu
mender: cy
Version: 0.0.2
Date: 2017-03-02
###############################
"""
my_spider= DouBanSpider()
my_spider.start_spider()
fobj= open('/data/moxiaokai/HelloWorld/cyTest/blogcode/top_move.txt','w+') for item in my_spider.datas: print item
fobj.write(item.encode("utf-8")+'\n')
time.sleep(0.1) print u"豆瓣爬虫爬取完成"if __name__=='__main__':
main()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
运行结果:
三、Python 爬虫爬坑路(二)——B站图片,咸鱼的正确 GET 姿势
昨天在写完入门级爬虫之后,马上就迫不及待的着手开始写 B站的图片爬虫了,真的很喜欢这个破站呢(〜 ̄△ ̄)〜
这里不涉及到 Python爬虫的高级技巧,没有使用框架,没有考虑反爬机制,没有使用异步IO技术,因为这些,我都不会!
我们选定 B站的动画区进行测试,打开后我们发现有好多好多图....
但当我们使用 F12查看这些图片的时候,发现并没有图片的地址...
这就是目前大多网站使用的 Ajax技术动态加载数据的锅,可遇到这种情况这么办呢?别急别急,我们知道这些图片的地址一定是需要加载的,而目前常见WEB传输数据的基本就是方式 XML和 Json(其实是我就知道这两种...),那好我们去看看请求的 XML和 Json文件。
以下省略查找过程....
我们发现 B站的图片地址是保存在 Json里面的,ok,我们保存好这个 json地址:
https://api.bilibili.com/x/web-interface/dynamic/region?callback=jQuery172071087417824369_1505783866149&jsonp=jsonp&ps=15&rid=24&_=1505783866453
这个是 MAD·AMV最新动态的 Json文件,利用上面相同的方法,我们找到 3D区、短片·配音区、综合区以及右边排行部分的相应 json地址。
好在 Chrome浏览器提供了一个 Preview功能,自动帮我们整理好数据,如下
这样就很清晰啦,我们只需要一层层解析拿到 pic即可。于是我们这样写:
我们利用 requests内置的 json解码器,很不幸,报错:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1(char 0)
它提示说:解码 Json数据的时候出了问题,可能是在第一行第一列,咦?好奇怪,刚才不是用浏览器看过结构了吗,没毛病啊,怎么还在报错:Σ( ̄□ ̄||)
别急别急,我们先看看原始的 Json数据长啥样?用浏览器打开上面的 json链接就可以了。
(/TДT)/前面的那些字母是干嘛的呀,为什么还有括号啊!
所以我们知道了 Json解析错误的原因啦:后面在处理的时候把前面的这部分删掉就好啦,另外我们也发现了 archives这个关键字,我们在上一张图看见过的哦,有印象吗?啊,你说没有呀,没关系,这里你只需要记着它是一个 List的数据类型就好了呀!
为了防止被当作是恶意访问从而被封 IP,这里我们选择牺牲时间,取巧使用 sleep(x),让其等待一段时间之后再发出请求。
你可能会问我,呀,你这个,根本没有代理、没有混淆IP防止反爬、也没有模拟 Ajax请求动态抓取云云~
那我可以很负责的告诉你,你!走错地方了!你要找的技术贴出门右拐!( ̄へ ̄)
我们恰巧使用的是 B站的 Ajax技术,只要哪个视频有了最新评论(或者是一下其它的条件),就会使用 Ajax将最新的数据取出来。就像下面这样:
所以可能在访问人数多的时候,更新越快,越有可能获得更多不同的图片啦!
之后你就可以在吃饭的时候,把它挂起,然后吃饭回来就会发现有好多好多的图片!(=・ω・=)
之后会陆续的更新自己爬虫的爬坑过程,希望能够找到小伙伴一起学习呀!
OK,本文到此结束,希望对大家有所帮助。