今天带大家进行模拟京东登录,并进行签到获取京豆,1000 个京豆 = 10 元,毕竟「苍蝇也是肉」,每天用脚本可以获取大概 n 个京豆,是不是一个发现了一个「发家致富」的好路子?
废话不多说,下面开始正题。
整体流程如下:
1 模拟登录
首先我们需要的就是模拟京东登录,只有登录了才能进行签到领京豆等操作。模拟登录其实就是通过 HTTP 的 POST 请求讲用户的登录信息发送给服务器进行认证的过程。
1.1 登录数据分析
登录过程表面上看着挺简单,我们只要在浏览器里输入用户名、密码,有时还需要输入一些连开发者都分辨不出的验证码。其实背后是浏览器帮忙做了很多工作(浏览器表示挺累的),因此我们要模拟登录,就要搞清楚浏览器在背后做了什么。
同样的套路,进入到京东的登录页面:https://passport.jd.com/uc/login?ltype=logout,按下 F12
,页面输入登录信息后,点击登录(可以尝试输入一个错误的密码,因为登录后页面直接跳转到了主页面,看不到我们要的数据了),可以看到一个 POST 请求:
这里可以看到,浏览器发送了一个 POST 请求到 https://passport.jd.com/uc/loginService,然后在请求头上面带上了一些基本的参数,其中有一个 FormData
,这里就是浏览器向服务器提交的表单信息。
看上去是不是一脸蒙蔽了,其实,这些信息大部分是可以在登录页面的源代码里找到的,源码中有一个 id 为 formlogin 的表单,其内容有:
1 | <form id="formlogin" method="post" onsubmit="return false;"> |
可以看到一批 hidden
,其实这些都是浏览器后台「偷偷」传给服务器的参数,只不过它们是被隐藏了的,前端页面不可见而已。可以用 BeautifulSoup 获取这些登录信息:
1 | sa_token = soup.find(id='sa_token')['value'] |
1.2 验证码的处理
普通登陆的情况下验证码 authcode 只要为空即可,但是若京东认为有安全风险问题时,会出现验证码,那这个验证码如何处理呢?
目前验证码处理仍然是一个比较困难的问题,处理方法一般可以分为自动识别和手动识别。
- 手动处理:就是通过验证码链接将验证码图片下载到本地,然后手动敲入完成信息录入。
- 自动识别:指使用一些高级的算法技术来完成的,如 OCR 文字识别,机器学习进行识别训练等。一般免费的文字识别算法识别率并不高,收费的识别效率还是可以接受的。
本文就采用手动录入验证码的方式。
首先,如何判断页面是否需要输入验证码?
调试时,可以看到有这么一个请求:https://passport.jd.com/uc/showAuthCode:
其返回值是:
1 | ({"verifycode":true}) |
显然,这个地址是用来判断是否该账号是否需要验证码的。
点击一下「换一张图片」,可以看到验证码的请求地址是:https://authcode.jd.com/verify/image?a=1&acid=36f24f99-f86d-4e1b-957e-bd51cd3257a4&uid=36f24f99-f86d-4e1b-957e-bd51cd3257a4&yys=1529922165515。
同时,在登录页面源码中可以得到图片的地址信息:src2=”//authcode.jd.com/verify/image?a=1&acid=37fe7934-fbc9-413d-b0a8-e0492e1d01b7&uid=37fe7934-fbc9-413d-b0a8-e0492e1d01b7”,显然图片的获取地址是由 http: + src2 + yys= + Unix时间戳
拼接组成:
1 | auth_code_url = soup.find(id='JD_Verification1').get('src2') |
这样我们就能得到图片的下载地址,将其下载到本地,然后根据图片内容输入验证码即可。
1.3 会话保持
假设我们已经登录成功,那该如何保持会话呢?也就是我们切换到其他网页后,如何保持会话状态,不用再次登录。
其实在后续访问其他页面时只要在 header 中包含用户 cookie 的话,不需用户名密码即可登录。
这里就要用到会话对象 requests.Session
,会话对象让你能够跨请求保持某些参数。它也会在同一个 Session 实例发出的所有请求之间保持某些参数,比如 cookies
,并且 requests 模块每次会自动处理 cookies,不需要我们手动来处理 cookie,是不是很方便!
所以如果你向同一主机发送多个请求,底层的 TCP 连接将会被重用,从而也可以带来显著的性能提升。其高级用法可以参考文档:http://docs.python-requests.org/zh_CN/latest/user/advanced.html。
2 获取京豆
通过上面的分析,我们解决了京东的登录问题,下面要做的就是京豆的领取啦。
领取京豆店铺签到的地址:http://bean.jd.com/myJingBean/list
分析店铺签到的页面源码(这里仅列出部分源码):
1 | <ul class="bean-shop-list"> |
可以看出,店铺列表是被 class="bean-shop-list"
包裹的 li
组成,其中有店铺的超链接,我们需要访问这些链接地址进入到店铺主页进行签到。
随便访问一个签到店铺,查看签到的源码是一个地址:https://mall.jd.com/shopSign-1000006984.html,发现是由 固定地址 + 店铺 id
拼接而成的,那我们主要的工作就是获取店铺 id 了。
另外,在访问店铺时,在其 response 是包含 shop_id 的:
1 | <input type="hidden" id="shop_id" value="1000003179" /> |
那我们就可以直接使用 BeautifulSoup 获取,然后拼接成签到地址:
1 | # 获取店铺 id |
这样就可以直接访问签到地址进行签到啦~
运行
1 | $ python jd_beans.py |
由于网络原因,部分店铺签到失败。
P.S. 签到后,在京东记录页面好像没找到京东增加的记录,泪奔,不过我们是来学技术的,不要在乎这些蝇头小利。
3 总结
本文的难点在于京东的登录过程,涉及到了 验证码、cookie 的处理,业务逻辑也稍微有些绕,需要判断是否需要验证码、是否登录成功等。其实,主要的就是在 HTTP 交互过程中抽取我们所要的目标数据。
另外,验证码处理部分还是有些问题,比如前面判断出登录不需要验证码,但是在登录时仍返回「请输入验证码」。还有,有兴趣的同学也可以进行扩展,比如秒杀、抢购等。
获取源码可以关注下面的公众号,回复「京东」即可。
参考: