这个部分主要是账单信息的获取, 文笔和语法可能都有点差,大家包涵
最近想给自己的网站接入支付和自动发货系统,踩了一些坑, 其中用到一些爬虫技术,放在这里和大家分享一下。
支付宝对个人用户太不友好了,自己网站想接入支付宝支付的话,必须要签约, 签约得要营业执照。总之各种蛋疼。这不,我想出了一个「折衷的解决办法」。
整个处理流程效率十分低下,但总比我手动发货好那么一点。 再次吐槽坑爹的支付宝,不开放接口!!!
一开始的思路是,通过 POST 数据登录支付宝 web 版。 后来尝试了一下,发现。支付宝关闭了 POST。 想要登录获取信息的话, 那么只剩下一条路了: 通过『 cookies 』登录
手动登录支付宝 web 版本, 打开 chrome 开发工具,找到 cookies, 复制出来。
上述步骤很我们在 爬取螺纹钢数据 这篇文章里已经详细的描述过了, 我就不过多介绍了。
我就说一个将字符串快速转换为字典类型的技巧
# 将复制到 cookies 转换为字典,方便调用 raw_cookies = 'JSESSIOnID=RZ13thOM1d 后面省略了,调式的话用自己的 ' cookie = SimpleCookie(raw_cookies) cookies = {i.key: i.value for i in cookie.values()}
得到了 cookies,我们就能在登录状态下获取数据了。 主要用到的是: requests 模块的 session
下面就看看 v1 版本的整体代码吧 整体代码:
''' 尝试登录支付宝 并获账单记录 ''' import requests from http.cookies import SimpleCookie from bs4 import BeautifulSoup # 自定义 headers HEADERS = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', 'Referer': 'https://consumeprod.alipay.com/record/advanced.htm', 'Host': 'consumeprod.alipay.com', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Connection': 'keep-alive' } # 将复制到 cookies 转换为字典,方便调用 raw_cookies = 'JSESSIOnID=RZ13thOM1dM5K05460101"; 中间省略了 One=RZ250AATO/mr4CZ1cRnxgFmVR' cookie = SimpleCookie(raw_cookies) cookies = {i.key: i.value for i in cookie.values()} # 尝试使用面向对象的方式来造爬虫 class Alipay_Bill_Info(object): '''支付宝账单信息''' def __init__(self, headers, cookies): ''' 类的初始化 headers:请求头 cookies: 持久化访问 info_list: 存储账单信息的列表 ''' self.headers = headers self.cookies = cookies # 利用 requests 库构造持久化请求 self.session = requests.Session() # 将请求头和 cookies 添加到缓存之中 self.session.headers = self.headers self.session.cookies.update(self.cookies) self.info_list = [] def login_status(self): '''判断登录状态''' status = self.session.get( 'https://consumeprod.alipay.com/record/standard.htm', timeout=5, allow_redirects=False).status_code print(status) if status == 200: return True else: return False def get_data(self): ''' 利用 bs4 库解析 html 并抓取数据, 数据以字典格式保存在列表里 ''' status = self.login_status() url = 'https://consumeprod.alipay.com/record/standard.htm' if status: html = self.session.get(url).text soup = BeautifulSoup(html, 'lxml') # 抓取前五个交易记录 trades = soup.find_all('tr', class_='J-item ')[:5] for trade in trades: # 做一个 try except 避免异常中断 try: # 分别找到账单的 时间 金额 以及流水号 time = trade.find('p', class_='text-muted').text.strip() amount = trade.find( 'span', class_='amount-pay').text.strip() code = trade.find( 'a', class_='J-tradeNo-copy J-tradeNo')['title'] self.info_list.append( dict(time=time, amount=amount, code=code)) except: self.info_list.append({'error': '出现错误,请加站长支付宝好友获取充值码'}) else: self.info_list.append({'error': '出现错误,请加站长支付宝好友获取充值码'}) # 测试一下: test = Alipay_Bill_Info(HEADERS, cookies) test.get_data() print(test.info_list) ''' OUT: 200 [{'time': '07:34', 'amount': '- 3.00', 'code': '2017081521001004100329637047'}, {'time': '07:08', 'amount': '- 100.00', 'code': '2017081521001004100329622812'}, {'time': '05:37', 'amount': '+ 0.14', 'code': '20170815344111650101'}, {'time': '01:08', 'amount': '+ 10.00','code': '20170815200040011100040078948930'}, {'time': '22:23', 'amount': '+ 10.00', 'code': '20170814200040011100060079678223'}] '''
可以看到 我需要的前 5 个订单记录的 时间,流水,金额都已经出来了。 来对比一网页版截图:
上面那个爬虫虽然实现了爬取账单信息的功能,
但实际上,完全没有用有没有?
因为 每次都得我们手动输入 cookies
那这个爬虫完全没有存在的 意义了!
当然,这是夸张的说法, 通过上面那个爬虫,我们实践证明了爬取账单的可能性。
剩下的只需要想办法 自动获取 cookies 就行了!
如何自动获取 cookies 呢?
想出的一个比较笨的方法:
说起来很简单有没有?
但实际上我整整调试了一个下午才成功啊!!!
你觉得是为啥呢?
当然是支付宝坑爹的认证机制:
说多了都是辛酸泪,大家调试的时候,注意点就好。
下面给出获取 cookies 的代码片段
def wait_input(self, ele, str): '''减慢账号密码的输入速度''' for i in str: ele.send_keys(i) time.sleep(0.5) def get_cookies(self): '''获取 cookies''' # 初始化浏览器对象 sel = webdriver.PhantomJS() sel.maximize_window() sel.get(Login_Url) sel.implicitly_wait(3) # 找到用户名字输入框 uname = sel.find_element_by_id('J-input-user') uname.clear() print('正在输入账号.....') self.wait_input(uname, self.user) time.sleep(1) # 找到密码输入框 upass = sel.find_element_by_id('password_rsainput') upass.clear() print('正在输入密码....') self.wait_input(upass, self.passwd) # 截图查看 # sel.save_screenshot('1.png') # 找到登录按钮 butten = sel.find_element_by_id('J-login-btn') time.sleep(1) butten.click() # sel.save_screenshot('2.png') print(sel.current_url) # 跳转到账单页面 print('正在跳转页面....') sel.get(Bill_Url) sel.implicitly_wait(3) # sel.save_screenshot('3.png') # 获取 cookies 并转换为字典类型 cookies = sel.get_cookies() cookies_dict = {} for cookie in cookies: if 'name' in cookie and 'value' in cookie: cookies_dict[cookie['name']] = cookie['value'] return cookies_dict # 关闭浏览器 sel.close() def set_cookies(self): '''将获取到的 cookies 加入 session''' c = self.get_cookies() self.session.cookies.update(c) print(self.session.cookies)
这个部份主要是利用了 selenuim 模拟 PhanomJS 来模拟浏览器,登录支付宝账号密码 最后获取 cookies,并格式化。
有详细的注释,详细都能看懂的吧!
对于浏览器模拟爬虫不熟悉的,可以看我以前写的文章:
可以看到,我们已经可以完全自动化的查询账单信息了。
剩下的就是后台支付系统的把编写了, 由于不涉及到爬虫的相关技术 我就不 pull 上来啦~
''' 尝试登录支付宝 并获取账单记录 通过 seleium 登录支付宝, 获取 cookies ''' import requests from selenium import webdriver from bs4 import BeautifulSoup import time # 登录 url Login_Url = 'https://auth.alipay.com/login/index.htm?goto=https%3A%2F%2Fwww.alipay.com%2F' # 账单 url Bill_Url = 'https://consumeprod.alipay.com/record/standard.htm' # 登录用户名和密码 USERNMAE = '' PASSWD = '' # 自定义 headers HEADERS = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', 'Referer': 'https://consumeprod.alipay.com/record/advanced.htm', 'Host': 'consumeprod.alipay.com', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Connection': 'keep-alive' } class Alipay_Bill_Info(object): '''支付宝账单信息''' def __init__(self, headers, user, passwd): ''' 类的初始化 headers:请求头 cookies: 持久化访问 info_list: 存储账单信息的列表 ''' self.headers = headers # 初始化用户名和密码 self.user = user self.passwd = passwd # 利用 requests 库构造持久化请求 self.session = requests.Session() # 将请求头添加到缓存之中 self.session.headers = self.headers # 初始化存储列表 self.info_list = [] def wait_input(self, ele, str): '''减慢账号密码的输入速度''' for i in str: ele.send_keys(i) time.sleep(0.5) def get_cookies(self): '''获取 cookies''' # 初始化浏览器对象 sel = webdriver.PhantomJS() sel.maximize_window() sel.get(Login_Url) sel.implicitly_wait(3) # 找到用户名字输入框 uname = sel.find_element_by_id('J-input-user') uname.clear() print('正在输入账号.....') self.wait_input(uname, self.user) time.sleep(1) # 找到密码输入框 upass = sel.find_element_by_id('password_rsainput') upass.clear() print('正在输入密码....') self.wait_input(upass, self.passwd) # 截图查看 # sel.save_screenshot('1.png') # 找到登录按钮 butten = sel.find_element_by_id('J-login-btn') time.sleep(1) butten.click() # sel.save_screenshot('2.png') print(sel.current_url) # 跳转到账单页面 print('正在跳转页面....') sel.get(Bill_Url) sel.implicitly_wait(3) # sel.save_screenshot('3.png') # 获取 cookies 并转换为字典类型 cookies = sel.get_cookies() cookies_dict = {} for cookie in cookies: if 'name' in cookie and 'value' in cookie: cookies_dict[cookie['name']] = cookie['value'] return cookies_dict # 关闭浏览器 sel.close() def set_cookies(self): '''将获取到的 cookies 加入 session''' c = self.get_cookies() self.session.cookies.update(c) print(self.session.cookies) def login_status(self): '''判断登录状态''' # 添加 cookies self.set_cookies() status = self.session.get( Bill_Url, timeout=5, allow_redirects=False).status_code print(status) if status == 200: return True else: return False def get_data(self): ''' 利用 bs4 库解析 html 并抓取数据, 数据以字典格式保存在列表里 ''' status = self.login_status() if status: html = self.session.get(Bill_Url).text soup = BeautifulSoup(html, 'lxml') # 抓取前五个交易记录 trades = soup.find_all('tr', class_='J-item ')[:5] for trade in trades: # 做一个 try except 避免异常中断 try: # 分别找到账单的 时间 金额 以及流水号 time = trade.find('p', class_='text-muted').text.strip() amount = trade.find( 'span', class_='amount-pay').text.strip() code = trade.find( 'a', class_='J-tradeNo-copy J-tradeNo')['title'] self.info_list.append( dict(time=time, amount=amount, code=code)) except: self.info_list.append({'error': '出现错误,请加站长支付宝好友获取充值码'}) else: self.info_list.append({'error': '出现错误,请加站长支付宝好友获取充值码'}) return self.info_list # test: test = Alipay_Bill_Info(HEADERS, USERNMAE, PASSWD) data = test.get_data() print(data)
每天的学习记录都会 同步更新到: 微信公众号:findyourownway
知乎专栏: https://zhuanlan.zhihu.com/Ehco-python
blog:www.ehcoblog.ml
Github: https://github.com/Ehco1996/Python-crawler
![]() | 1 just1 2017-08-15 18:31:28 +08:00 via Android 什么叫做支付宝关闭了 POST。 还不是技术不到位 |
![]() | 3 6IbA2bj5ip3tK49j 2017-08-15 18:48:00 +08:00 你要是之前开了当面付,就不用这么麻烦了。 |
![]() | 4 ss098 2017-08-15 19:10:21 +08:00 厉害,这应该是免签比较好的一个方案了。 |
![]() | 5 Sanko 2017-08-15 19:11:01 +08:00 via Android 思路不错 |
![]() | 6 akira 2017-08-15 19:18:10 +08:00 呃。。淘宝上面现成的系统应该是 30 块左右一套。 |
9 FanWall 2017-08-15 19:25:31 +08:00 现在支付宝的 POST 是相当有难度的(param ua),起码我不大相信 1#能做到[doge] 楼主这种是业内实现成本最低也是最普遍的解决思路 |
![]() | 11 brucewzp 2017-08-15 20:19:29 +08:00 实际操作的时候如果太频繁,支付宝会刷验证码出来,而且有时候出现验证码的概率和你的 IP 有很大关系 |
![]() | 12 akira 2017-08-15 21:22:43 +08:00 @Ehco1996 以前看到的大部分都是 windows 下的。 刚看了下淘宝,以前的关键字被屏蔽了。你可以试试谷歌关键字“免签约”,里面还是有提到的。 |
14 neoblackcap 2017-08-15 21:50:29 +08:00 @Ehco1996 小心太快了账号被封,我以前也搞过,实在是太苦逼了。我的方案是用 headless browser,成功率还高那么一点点。楼主可以参考一下。不过支付宝还有风控系统,一旦他们觉得你异常(我是不知道具体的指标了),你的账号就会被封,小心点吧。 |
![]() | 16 sola97 2017-08-15 23:48:04 +08:00 感觉不会稳定的 |
![]() | 17 580a388da131 2017-08-16 03:59:55 +08:00 不给接入是因为个人备案号不能经营盈利性网站。 |
![]() | 18 cszeus 2017-08-16 05:34:04 +08:00 如果已经用 selenium 登录了,为什么不用 selenium 一口气搞完?再用 requests 有什么区别么。 |
![]() | 19 XiaoFaye 2017-08-16 06:18:03 +08:00 请个刚高考完的学生做,当暑假工,一个月下来也没多少钱。 |
![]() | 20 Ehco1996 OP @neoblackcap 好的,我去查查看 谢谢 @580a388da131 政策问题 @cszeus 用 selenium 获取数据总觉得效率会差一点,当然这也是我的使用习惯。 @XiaoFaye 我也还是学生。也没多少钱 |
![]() | 21 lifeintools 2017-08-16 07:51:48 +08:00 mark 非常感兴趣 谢谢 lz PS: 其实也可以写 chrome 插件来实现这个功能。 |
22 thundernet8 2017-08-16 08:09:22 +08:00 via iPhone 我觉得你这个好费劲 实际上支付宝的 cookies 可以持久很长时间有效的 所以我做了这个脚本 https://github.com/thundernet8/AlipayOrdersSupervisor 唯一不好的是隔一段时间换下 cookie |
23 Jasmine2016 2017-08-16 08:41:52 +08:00 我想吐槽。。。登陆太快和太慢都不行,简直没人权 ![]() |
![]() | 24 qq292382270 2017-08-16 08:48:39 +08:00 我对个人支付宝的自动付款研究了两年. 已经有两三款很不错的成品,稳定几个月不掉线没问题.另外个人帐号实时数据功能也搞定了...  |
25 kikyous 2017-08-16 08:53:57 +08:00 有一种思路是开个淘宝店,出售类似充值卡的东西,然后利用自动发卡平台发送卡号和密码 然后用户自己充入个人帐号 就是把支付环节转移到淘宝上面 |
![]() | 26 est 2017-08-16 08:54:21 +08:00 直接收支付宝的邮件即可。 |
27 youthdou 2017-08-16 09:04:22 +08:00 mark 一下。 |
28 q409195961 2017-08-16 09:24:17 +08:00 楼主写得 666,有些网站也是直接转账,然后输入流水号充值的。 另:button 不是 butten ![]() |
![]() | 30 Enivel 2017-08-16 09:34:21 +08:00 楼主的方法,无法处理二次验证吧. 几年前图形验证码好过. 现在改成滑块,但终归也找到合适的方法绕过. headless 效率较低其实登录完全可以接口形式完成,登录稳定还可以过二次验证 |
![]() | 31 yangxin0 2017-08-16 09:40:21 +08:00 via iPhone @qq292382270 支付宝不是支持自动付款吗 |
32 734506700qq 2017-08-16 09:47:26 +08:00 这个想法不错,可以试试 |
![]() | 33 laoertongzhi 2017-08-16 10:01:52 +08:00 |
![]() | 34 Ehco1996 OP @thundernet8 原本我也想 做持久化的,可是现在貌似出了啥验证机制,十几分钟 cookie 就挂了。 @audoe @est 支付宝邮件提醒必须你没有绑定手机号,不然只会再 app 上或者短信提醒。我查到的资料是这样的,一开始我也想通过邮件来检测的 @LevineChen 是的 二次验证不行,请问可以分享一下你的方法么 @qq292382270 膜拜大佬 能分享一下么 |
![]() | 36 Ehco1996 OP |
![]() | 38 qq292382270 2017-08-16 10:52:23 +08:00 @yangxin0 这玩意的命名我一直都很纠结.. 功能就是获取到指定个人号的收款记录.并做成订单处理之类的一系列逻辑... @laoertongzhi 本来是没有网站的.做出来的程序只是自己几个朋友私下的用..前一个月才开始打算正规做 .. 自己一个人撸网站和 app 的前后台,心力憔悴.. 所以问题来了,还没上线,一些细节问题没考虑好.. 不过最迟这周应该可以发布.. 但应该不会来 V2 这里宣传.. 这玩意有点违法 @Ehco1996 还差一点.. 这周应该可以发布.. |
![]() | 39 zhuf 2017-08-16 10:54:31 +08:00 @qq292382270 有没详细介绍的啊,最近刚好有这需求 |
![]() | 40 qq292382270 2017-08-16 10:57:45 +08:00 @zhuf 我直接手打好咯.. 网站还差一点才上线.. 核心功能是,实时监控支付宝个人号(微信号也支持的),有新到帐订单后,立刻取出订单号,付款名,备注等等信息. 发送到服务器里面. 延迟差不多在 1-3 秒左右. 流程: 服务器创建订单->生成二维码->用户扫码支付或转账->服务器收到监控程序发来的新订单数据 ->处理订单为支付成功. |
![]() | 41 zhuf 2017-08-16 11:04:23 +08:00 @qq292382270 哦,网站上线了通知下哈,或者留个联系方式 |
![]() | 42 sofs 2017-08-16 11:05:22 +08:00 lz,blog 音乐自动播放关闭掉吧 |
![]() | 43 qq292382270 2017-08-16 11:16:30 +08:00 @zhuf 嗯.. 话说我的联系方式.... 就在我昵称上了.. 唉.. 当初以为是设置网站 id 以及名字可以改 .. 没想到.. |
44 magiclobster 2017-08-16 11:24:33 +08:00 @q409195961 最近公司想搞一个爬招行流水的功能,客户转到公司的卡上,去爬流水看到账没,这个有类似的样例没 |
![]() | 45 Charkey 2017-08-16 11:27:51 +08:00 支付宝风控严 |
![]() | 46 eoo 2017-08-16 11:49:00 +08:00 via Android 我在弄 QQ 扫码支付 |
![]() | 47 Ehco1996 OP |
![]() | 48 tjxiter 2017-08-16 13:55:46 +08:00 爬 google play 的 apk,楼主有没有好的建议啊?用 seleninum 写了,只能下载到模拟器或手机。 需求是要下载到本地电脑。 |
49 youxiachai 2017-08-16 13:57:16 +08:00 这种玩意...其实..最怕风控..了..很容易就被封了.. |
50 anhaoh 2017-08-16 14:03:53 +08:00 你输入账号密码的时候不能过快 你输入账号密码的时候不能过慢 这个太扯蛋吧。。。。你让用浏览器保存了秘密自动填充的人怎么办 |
![]() | 51 Felldeadbird 2017-08-16 14:07:55 +08:00 强,这个思路还真折中,有点猥琐。 唉。国内个人开发者,想做点支付都 TM 得艰难。 |
![]() | 52 greatghoul 2017-08-16 14:16:16 +08:00 via Android chrome 浏览器扩展常驻取支付宝信息,想要什么数据有什么数据。 无需模拟登录,自己手动登录一次就可以了,访问页面用的就是你平日用的浏览器,不太可能支付宝发现和屏蔽。缺点,得有自己的一台电脑常年开机。 |
![]() | 53 chroming 2017-08-16 14:18:09 +08:00 爬虫入门知识+推广广告 |
![]() | 54 Beckham 2017-08-16 15:27:06 +08:00 来学习一下爬虫 |
![]() | 55 vincenth520 2017-08-16 16:18:07 +08:00 个人你完全可以去申请那种第三方支付,费率高一点而已 |
![]() | 56 Anshi 2017-08-16 16:21:59 +08:00 。。。今天看见你三次了 |
57 sunsh217 2017-08-16 18:35:04 +08:00 via Android @greatghoul 请教是哪款插件? |
58 sunsh217 2017-08-16 22:15:44 +08:00 @greatghoul 懂了。 |
![]() | 59 fzinfz 2017-08-16 22:29:15 +08:00 via iPad 换个思路:微店。如何? |
60 tbag781623489 2017-08-16 22:39:09 +08:00 via iPhone 又学到了点新东西 感谢 |
![]() | 61 Ehco1996 OP |
![]() | 62 ZengLeiPro 2017-08-16 23:49:50 +08:00 用第一种方法,手动获取 cookie,然后保持刷新频率,没办法长期保持登陆状态吗? |
![]() | 63 eoo 2017-08-16 23:55:58 +08:00 via Android 今晚已经实现 QQ 转账接入网站了,相比支付宝和微信 QQ 好弄多了。 |
![]() | 64 Ehco1996 OP |
65 luap 2017-08-17 14:29:59 +08:00 我自己开发的支付宝订单系统。是刷 cookie,至少可保持 1 个月不掉线。已经稳定使用半年了 |
![]() | 67 leavic 2017-08-17 19:30:20 +08:00 cookies 十分钟过期,我早就弃坑了。 |
![]() | 70 vovov 2017-08-19 16:20:07 +08:00 via Android 果然程序员思维解决问题啊,我要有这么多时间就申请营业执照去了。幸好自己有支付宝和微信支付接口,这样开发得累死。建议楼主去申请个个体工商户就行了 |
74 Buffer2Disk 2017-08-19 22:36:00 +08:00 @qq292382270 你应该是属于老司机了吧,你的思路是做楼上说的那种持久化的 cookies,还是像楼主这种定期去模拟登陆获取最新 cookies 呢?如果是第二种,频率把握不好的话,被支付宝风控的风险应该很大吧 |
![]() | 75 qq292382270 2017-08-20 01:48:32 +08:00 cookies 取登录时候的就可以用了 . 技术难点是怎么保持.. 我这里是放服务器里面执行. 几个月掉线一次.. 找不出掉线原因,估计是网络波动吧我的猜测.. @Buffer2Disk |
76 Buffer2Disk 2017-08-20 09:05:28 +08:00 @qq292382270 也有可能是支付宝的强制更新 session 的策略? |
![]() | 77 Ehco1996 OP @Buffer2Disk 是的,cookies 是动态更新的 最后我用的是模拟等登陆之后 随机访问一个页面,并动态获取更新 cookies 但这样也不稳定,一般 2 小时左右 就 remote close 了 |
78 jko123 2017-09-13 19:42:32 +08:00 centos 下,selenium + phantomjs 无法定位输入,楼主知道怎么解决吗? |
![]() | 79 ZhLTE 2018-07-19 13:49:36 +08:00 selenium + phantomjs 基本没法登陆成功了~ |