好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

​【爬虫实战】CC98抽卡机

抽卡机是我第一个独立完成的小项目,它对我意义非凡。

抽卡?什么是抽卡?

CC98 抽卡 是由 CC98 和? NexusHD 共同推出的一款抽卡小游戏。卡牌内容包括? CC98 、 NexusHD ,以及浙江大学相关的各种人事物,不同的卡片具有不同的等级,同时也具有不同的价值和抽取几率。

个人收藏页面

等级介绍

Mystery 是对98、NHD有杰出贡献的四位用户 *** 是98站务组和技术组正式成员、荣誉站长、创始人逗逼形象和NHD维护开发员、管理员 SR 是98正式版主和全站贵宾、拥有大于等于3个VIP(包括协会退休成员)或威望超过98或帖数超过10w的98用户,NHD总版主和发布员 R 是98实习版主、认证用户、版面贵宾、98运营管理团队成员和帖数大于等于10000或威望大于等于15的用户 N 是其他普通用户。

等级分布

等级 N R SR *** Mystery 比例 53.49% 30.00% 15.00% 1.50% 0.01% 最低数量 0 0 1 0 0

为什么需要抽卡机,手动抽不好吗

  原因也简单,懒呗。如果要手动抽完每个月从N站兑换来的100万财富值(现在缩水到80万了),就算不每次都全部点开,也得十几二十分钟,费时费力费鼠标。之前有人用按键精灵来抽卡,也算是一种解放劳动力的方案。今年十月份的时候我自学了一些爬虫的基础知识,就想着能不能学以致用,写一个能够完成自动抽卡的Python程序。

第一版抽卡机——用Cookie绕过登录

  起初,我以为所有网站的登录都差不多,无非就是用POST方法提交一个包含用户名和密码的表单,但是显然事情没有我想象得那么简单。

  登录CC98抽卡中心需要先登录CC98登录中心:

CC98登录中心登录页面

  登录后,还需要通过抽卡中心发起的许可,方可进入CC98抽卡中心。

授权许可页面

  在Chrome的开发者工具中看了一下登录CC98登录中心需要提交的信息:

登录CC98登录中心的Form Data

  这时我完全不知道这个 __RequestVerificationToken是 从哪来的,复制下来尝试用 Requests 来模拟登录,得到了状态码为400的响应——登录失败了。

  在网上查了很多资料以后发现一种可以绕过登录的方法——保存 cookie 。

  于是我去开发者工具里把抽卡页面的 cooki e保存了下来,然后对抽卡的API: https://card.cc98.org/Draw/Run/ 发送一个POST请求,终于,我第一次成功用Python完成了抽卡。

在Chrome中查看当前页面cookie

CSRF验证

  虽然能够抽卡了,我还是十分好奇Form-data里的那个 __RequestVerificationToken 是怎么来的,通过谷歌,我找到了这样一篇博客:

当爬虫遇到CSRF 验证(__RequestVerificationToken):https://HdhCmsTestjianshu测试数据/p/e0844a0a5e61

  原来这个 __RequestVerificationToken 是可以从页面的html中找到的,也就是说也可以用程序来获得:

 import?requests from?bs4?import?BeautifulSoup  #?获取CSRF验证 r?=?requests.get('https://card.cc98.org/Draw',?cookies=cookies) bs?=?BeautifulSoup(r.text,?'html.parser') token?=?bs.find('input',?{'name':'__RequestVerificationToken'})['value']  

  于是第一版的抽卡机就完成了我还加了一个小功能,就是把抽到的 *** 和 M 卡显示出来,代码如下:

 from?skimage?import?io  #?开抽! r?=?s.post('https://card.cc98.org/Draw/Run/{}'.format(action),? ???????????data=data, ???????????headers={"content-type":"application/x-www-form-urlencoded;?charset=UTF-8"}, ???????????cookies=cookies) bs?=?BeautifulSoup(r.text,?'html.parser')  N_cards?=?bs.find_all('div',?{'data-level':'0'}) R_cards?=?bs.find_all('div',?{'data-level':'1'}) SR_cards?=?bs.find_all('div',?{'data-level':'2'}) ***_cards?=?bs.find_all('div',?{'data-level':'3'}) M_cards?=?bs.find_all('div',?{'data-level':'4'}) print('抽到{}张N卡,{}张R卡,{}张SR卡,{}张***卡,{}张M卡!'.format(len(N_cards),?len(R_cards),?len(SR_cards),?len(***_cards),?len(M_cards)))  ***_M?=?***_cards?+?M_cards  #?显示抽到的***卡和M卡 if?***_M: ????for?i?in?***_M: ????????img_src?=?i.find_all('img')[1]['src'] ????????image?=?io.imread('https://card.cc98.org'+img_src) ????????io.imshow(image) ????????io.show()  

  还发现了一个好用的chrome插件:EditThisCookie,可以方便的把cookie存下来

EditThisCookie插件

第二版抽卡机——用Selenium获取Cookie

  第一版的抽卡机虽然可以将大部分工作自动完成,但是还是有一个手动操作的环节——复制一下 cookie 。

  实验室旁边工位的师兄是一个 Selenium 大师,他建议用它试试,试试就试试。其实并没有什么难度,就是学习 xpath 表达式的时候略微花了一些功夫。

 from?selenium?import?webdriver from?selenium.webdriver.chrome.options?import?Options  chrome_options?=?Options() #?chrome_options.add_argument("--headless") driver?=?webdriver.Chrome(options=chrome_options)  #?登录CC98登录中心 driver.get('https://openid.cc98.org/Account/LogOn') driver.find_element_by_id('UserName').send_keys('用户名') driver.find_element_by_id('Password').send_keys('密码') driver.find_element_by_xpath('//button[text()="立即登录"]').click()  #?#?授权给CC98抽卡中心 driver.get('https://card.cc98.org/') driver.find_element_by_xpath('//*[text()="登录"]').click() driver.find_element_by_xpath("//button[@class='btn?btn-success']").click()  cookies?=?{c['name']:?c['value']?for?c?in?driver.get_cookies()}  

  这里要注意的是,使用 XPATH 时应该避免使用数组索引(从Chrome的开发者工具里直接复制 XPATH 就会是这个样子),而应该使用有意义的 class 或者 id 来定位。

第三版抽卡机——层层剥开验证登录

  通过学习各种参考资料,我的爬虫水平有了一定程度的提高,也决定用Requests硬刚一下CC98抽卡中心的登录。

  在Network标签页中可以看到两次302跳转:

两次跳转

登录CC98登录中心

  首先是 用户名 、 密码 、然后 ValidTime 为空字符串, __RequestVerificationToken 和前面一样从html里解析出来。

通过验证界面

第二次POST请求的Form Data

  在Python中模拟,结果收到的响应是这样的:

错误的Response

  花了很长时间我才发现,Scopes这个参数竟然赋了两次值,第一次复制的结果自然就被第二次覆盖掉了。删掉第二次赋值 Scopes: profile 以后的响应是这样的:

正确的Response

  返回的这段 html 代码里包含了最后给 signin-cc98 发送POST请求时需要的表单信息,把他们都解析出来来就可以了。

第三次POST请求的Form Data

几个很坑的点

url多次跳转,要搞清楚现在在哪个页面 在开发者工具里看不到consent的response consent表单的字典里有两个相同的key

总结

通过这个小项目,我不经意间学到了很多东西,也发现了目标明确的时候一个人的效率可以有多高。全部代码已经上传到了GitHub,点击原文链接即可获取。

查看更多关于​【爬虫实战】CC98抽卡机的详细内容...

  阅读:59次