
我们经常会遇到这种情况,需要关注各个交易所的公告,并且找出自己感兴趣的内容。比如最近IEO比较火,需要关注币安的Launchpad, 火币的Prime, OK的Jumpstart,比特儿的GT售卖等等,一个个翻交易所公告还挺多;再比如我对币圈的各种活动、交易赛感兴趣,需要经常翻看公告,那么多交易所,每天光看这个就很占时间。
那有没有一种办法用程序快速查找各交易所公告,并筛选对你有用的内容呢?这是我最近非常想做的,因为python没学多久,今天终于花了近一天的时间,搞定了。
首先要感谢CSDN网站作者思无涯520的两篇文章,我是按照他的思路来做的:
Python爬虫之爬取静态网站——爬取各大币交易网站公告(一)
Python爬虫之爬取动态网站——爬取各大币交易网站公告(二)
我按照他的教程一学会了静态网站的抓取,也是ZB交易所;
接下来又按照教程二制抓取动态网站币虎Cointiger的公告,发现问题,只能获取一条英文的公告,因网站改版改各种参数也无效。
后来想想,我关注的至少有几十个交易所,如果这样一个个搞下去,要累死个人啊,有没有简便的办法?
我当时想到一点,在两个网站上有集成的交易所公告,就是汇集了各个交易所的公告,一个是非小号,一个是MyToken,如果我把这两个抓取成功,那不就是以一抵百了嘛!
因为非小号最近改版,导致不少交易所还没有入驻,公告当然也没有,我就先从MyToken下手。
Python版本:Python3.X
运行平台:MAC
IDE:PyCharm
浏览器:Chrome
(一)分析网站
查看https://www.mytoken.io/announcement/的网页源代码(Chrome—视图—开发者—显示源代码),无法在HTML中找到对应公告信息,判断为动态网站,许多数据并不是写死在HTML中,而是通过js动态载入的,是在页面加载到浏览器后动态生成的。否则可以直接在网页源代码找到显示公告的内容为静态网站。

在Chrome浏览器中,点击F12,打开Network中的XHR,我们来抓取对应的js文件来进行解析。如下图:

刷新页面,我们看到以下界面:通过查找发现Medialist那里与我们想要的相关,点击展开得到:

为了获取这些信息,点击Headers,获得我们要抓取的访问条件:

我们得到了Requests Header的请求参数。page:1那里指第一页。
(二)通过requests模块发送请求数据如下
headers = {
'User - Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36',
'Referer':'https://www.mytoken.io/announcement/'
}
req = requests.get(url=target,headers=headers)
html = req.text
html_doc = json.loads(html) #json.loads()解码python json格式
(三)提取信息
点击Preview,我们得到:

在这当中找到了我们想要的信息——交易所原始链接,文章id,时间,交易所名字,标题。有交易所的原始链接,MyToken的文章id不需要了。
提取方法如下:
print(html_doc)之后我们发现这是个字典,获得data数据,再获得list数据,如下
{'id': 30029, 'title': 'CEO交易所关于2019年4月7日CEO持仓、COO锁仓分红发放公告', 'abstract': 'https://ceo.bi/i/blog_c_1906.jsp', 'link': 'https://h5-cn-east.mytokenapi.com/native-support/announcement/?announceid=30029&language=zh_cn&legal_currency=cny&tt=1554652003', 'exchange_id': 1355, 'posted_at': 1554613703, 'lang_type': 'zh_cn', 'logo': 'https://cdn.mytoken.org/FhAuqDW1Xnqq61gOTkhNyVK2NcVv', 'exchange_name': 'CEO', 'exchange_alias': '', 'source': 'CEO'}
这样就变成我们可以直接获得的数据了,比如标题就用下面一行代码就能得到
title = html_doc.get('data').get(‘list')[n].get('title')
其它提取方法相同。
除此之外,这里的时间戳,需要将其转化为当地时间。
timestamp = html_doc.get('data').get('noticeInfoList')[n].get('ctime')
timeArray = time.localtime(timestamp)
now_time = time.strftime("%m-%d %H:%M", timeArray)
几项汇总到一起:
all = now_time +'\t' + source +'\t' + title +'\t' + abstract
(四)筛选我们想要的内容
我们可以把关注的关键字放到一个list中,比如与IEO相关的,注意中文要在前面加u进行转码,英文区分大小写。
key_array = [u"售卖",u"点卡","IEO",'Launchpad','Prime','Jumpstart’]
通过判断上述关键字是否都在标题中,如果在就打印出来,再加上循环,并防止重复打印。
# 判断是否包含交易赛相关字眼,如果是,打印
for key in key_array:
if key in title:
print(page, all)
break # 目的是当一个标题中出现多个关键词时,不用重复打印,只要打印一次就好了
最后网页默认是一页仅20条,我们想获得更多,加个页码的参数,并设定一个函数,循环获取每一页;过段时间网页的timestamp和code有可能还需要更新,也设为参数。
target ='https://speed-api.mytokenapi.com/media/medialist?type=6&keyword=exchange_announcement&need_pagination=1' #此为Request URL
target = target +'&page='+str(page) +'&size=20'+'×tamp='+ timestamp +'&code='+ code +'&platform=web_pc&v=1.0.0&language=zh_CN&legal_currency=CNY'
运行代码,查找与IEO相关的公告,一目了然。

如果漏掉一些公告,那说明关键字没设好,可以从公告标题中慢慢补全关键字。比如我把与交易赛相关的关键已经扩充到了这么多,争取一网打尽。
key_array = [u"瓜分", u"交易赛", u"强势", u"狂撒", u"排名", u"福利", u"奖励", u"糖果", u"赢", u"活动", u"PK赛", u"空投", u"壕送", u"大赛", u"礼", u"大奖", u"尽享", u"百万", u"送", u"倾情", u"百万", u"送"]
你可以选择你关注的内容设置不同的关键字:
比如你非常关注EOS相关公告,你设置key_array = ['EOS']
再比如你关注平台币相关公告,你设置key_array = ['BNB', 'HT', 'OKB']
再比如你关注上新相关信息,你设置key_array = [u"上新", u"上线"]
关键字随便你调整,再也不用从茫茫大海中一个个筛选了。
(五)遇到问题
程序调试是一个非常耗费脑力和精力的事,出现问题最好先一个一个输出,根据错误代码找解决办法,这个程序代码并不多,但初学菜鸟的我弄了几乎一整天。
调试MyToken的时候发现只能打印四页左右的内容,怀疑是网站的时间戳与code(类似签名)问题,因为抓取是抓的别人写好的,那时间戳与签名只能用别人的,可更新之后时间戳就变了。找MyToken客服也解决不了,因为客服一般都是妹子,她说要上班了转给技术。
无奈去调试非小号公告集成网页https://www.feixiaohao.com/exchange/notice/,原理一样,只不过非小号无法调取交易所原始链接,只能用他自己的,那就需要调取文章的id,因为每一篇公告的链接其实就是https://t.bqi.com/news/id.html
id = html_doc.get('data').get('list')[n].get('art_id')
href ='https://t.bqi.com/news/%s.html' % id# 非小号电脑链接
all = create_time +'\t' + nick_name +'\t' + title +'\t' + href
而且最崩溃的是非小号上每一页requests的url都需要输入对应页码的timestamp,nonce,sign三个参数,获取20页得输入20次,也要累死个人,MyToken至少一个可以输出4页,我只好返回去解决MyToken的问题。

MyToken在获取第4页出现问题,一行一行输出,看下到底哪个参数出问题,发现是source这个交易所名称,又定位到是'id': 29969出现问题,查看原始数据,发现这条公告来源交易所为空None,这才导致相加时一直报错 {'id': 29969, 。。。'exchange_name': None, 'exchange_alias': '', 'source': None}。
于是加个条件判断,如果为空,去掉它,问题解决,输出50页也没问题了。
if source ==None:
all = now_time +'\t' + title +'\t' + abstract
else:
all = now_time +'\t' + source +'\t' + title +'\t' + abstract
最后因为还在初学,难免出现差错,有问题欢迎交流。
附MyToken筛选公告总代码
import requests
import json
import time
import datetime
def get_contest_notice(page, key_array, timestamp, code):
headers = {
'User - Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36',
'Referer':'https://www.mytoken.io/announcement/'
}# 不同于交易所,此处不需要cookie
target ='https://speed-api.mytokenapi.com/media/medialist?type=6&keyword=exchange_announcement&need_pagination=1' #此为Request URL
target = target +'&page=' +str(page) +'&size=20' +'×tamp=' + timestamp +'&code=' + code +'&platform=web_pc&v=1.0.0&language=zh_CN&legal_currency=CNY'
req = requests.get(url=target, headers=headers)
html = req.text
html_doc = json.loads(html)#json.loads()解码python json格式
# print(html_doc)
num =len(html_doc.get('data').get('list'))
n =0
while (n < num):
source = html_doc.get('data').get('list')[n].get('source')
title = html_doc.get('data').get('list')[n].get('title')
timestamp = html_doc.get('data').get('list')[n].get('posted_at')
timeArray = time.localtime(timestamp)
now_time = time.strftime("%m-%d %H:%M", timeArray)
abstract = html_doc.get('data').get('list')[n].get('abstract')# 交易所原始链接
if source ==None:# 发现有一个数据来源是None,导致一直报错
all = now_time +'\t' + title +'\t' + abstract
else:
all = now_time +'\t' + source +'\t' + title +'\t' + abstract
# 判断是否包含相关字眼,如果是,打印
for key in key_array:
if key in title:
print(page, all)
break # 目的是当一个标题中出现多个关键词时,不用重复打印,只要打印一次就好了
n = n +1
page =1
page_total =20 #最多页数
key_array = [u"售卖", u"点卡", "IEO", 'Launchpad', 'Prime', 'Jumpstart'] # 注意区分大小写
while page <= page_total:
timestamp ='1554644184708'
code ='ab0d7d408191dc0a411d0ed292588ff1'
sum = get_contest_notice(page, key_array, timestamp, code)
page = page +1
网友评论