记一次python爬虫实践

有将近一个月没写文章了,懒人日常就是纠结于写还是不写,有没有必要写之间。想写的主题确实有一些,但磨磨蹭蹭到最后一篇也没写。

今天想写一篇与Android无关的技术内容,语言是相通的,只要需求分析清楚,用什么语言来实现倒是其次。

先来看看一下午用python折腾出来的结果(整个耗时10s):

python01.png

需求

通过python脚本自动添加git@osc的权限

背景

我有不少代码是私有的,正常逻辑下给一个人添加权限的scenario:

  1. 登录git@osc
  2. 进入项目
  3. 项目设置
  4. 项目成员管理
  5. 添加
python02.png python03.png

如果有多个项目需要添加权限,那就要重复上述步骤。每次的操作耗费的时间成本在2分钟/人。

解题过程

好歹咱也是个程序员啊,总不能老是被这些重复又单调的事情所困扰。所以我打算用代码来解决它。

如果你对Stay分析问题的思路与解决问题的技巧感兴趣,不妨接着往下看。即使不会python也没关系,因为我也不怎么会:)

本篇文章算是对之前文章80%的问题,按这个套路都能找到解决方案的案例补充。

git@osc有现成的API吗?

这个问题应该问谁最方便?当然是wiki啊。如果官方都没有给你提供解决方案,那你就木有正规途径可以走了。好吧。找了一圈git@osc,没有发现open api。pass。oscchina的open api倒是有,并且还有官方开源的android客户端,想参考的同学可以看看。

既然没有正规途径可走,那就来点黑科技咯。google下看看有没有爬下来整理的私有api。关键词(gitosc open api) er… 好吧,gitosc还不够有名,没人愿意爬它的API list。

写代码是唯一的方法吗?

其实这个需求的优先级并不那么高,如果能快速的解决它,花半天时间我是愿意的。但如果超过就不划算了,毕竟现在的基数也不大,一天可能也就操作一次而已。2分钟还是耗的起。

好吧,其实我是想放弃了。我这么怕麻烦的人,宁愿每次都花2分钟,也不愿意当下多花的时间来一劳永逸。等等,再容我想想…

以前每当我花这两分钟的时候,我都在想,这纯体力劳动,能自动化得多好啊。这时候我就想起郭神的slogan:

每当你在感叹,如果有这样一个东西就好了的时候,请注意,其实这是你的机会

即使不写代码,最差我也能用按键精灵写出来啊。页面是固定的,每个UI component坐标都是固定的。逼急了就写一个只能在自己机器上跑的按键精灵脚本。每次只需要设置好初始参数,run就可以了。

慢着…这不对劲啊,虽然解放了双手。特么电脑还是要run脚本,模拟屏幕点击啊。有时候为了等页面刷新,还要多加一些时间等待。可能2分钟人工就能完成的事,用按键精灵要花3分钟了。

傻傻的看着电脑模拟点击响应,这我可忍不了。就跟在android用robotium写自动化测试一样无聊。按键精灵,pass…

不就是写代码么

理论上来说,你会多少种语言,就能写多少种实现。既然决定用代码实现,那就先拆分需求吧。

  1. 从登陆到添加权限一共有5步,中途load的网页有host/login, host/project, host/project/setting, host/project/team_member/new。
    注:host=git.oschina.net
  2. 通过chrome开发者工具network console,需要提交表单的地方就两个,一个登陆,一个添加权限。
  3. git@osc每一个页面都生成一个token,当内部请求api需要带上这个token
  4. 添加权限时的form需要账号对应的userid,而不是username
  5. userid可以通过api搜索username对应的结果集,需要检查唯一性,避免添加错误的user

认真调研下来,其实就是请求几个url,解析几个标签,post几个form表单。任务就搞定了。纠结的就是,该用什么语言来实现呢。假如你只会android,没事,java肯定可以写出来。至于是多少代码量就无法保证了。涉及到的知识点(JSOUP+HttpUrlConnection+CookieManager)

选什么语言好呢?

google: 模拟网页登陆

搜下来的结果集都是python版的(不过也可能是因为我经常搜python使然),python在数据采集上的优势是公认的。像这么简单的需求,用PHP,ruby都能轻松实现。不过PHP需要部署,没有python和ruby跑起来方便。

其实Stay上个月断断续续的在看python,选python也是想检验学习成果。

在google搜索结果集了,尽量早发布时间较新的文章,技术更新太快了,很可能12,13年的老帖已经无法适用现在的需求了,通过google,找到一个github repo fuck-login。模拟一些国内知名的网站登陆。虽然没有git@osc的网站登陆,不过照猫画虎,实现起来也挺快的。

代码实现

参考了不少文章,有几个通用代码块,先copy出来。

python04.png

在每次request之后需要手动同步cookie。session.cookies.save()

python05.png

class TokenParser继承的HtmlParser,HtmlParser是用来解析html的工具类。

有了以上来个基础,剩下来的就是写request了。因为可以直接通过脚本来请求request,所以不需要按照web操作的scenario一步步来。只要拼接好url就可以了。这样可以省略2,3步,只需要1登陆,4成员管理页面,5添加权限就够了。

一步步完成吧。

登陆实现

python06.png

formdata是通过chrome的network console查出来的。有兴趣的可以自己找个网站试试。chrome->settings->More Tools->Developer Tools->Network

fetch_access_token(url)方法是load login页面,解析整个html文本中的token标签对应的值。取出来赋值给formdata中的authenticity_token。这样模拟网页登陆,通过服务器token校验。

所幸git@osc不需要验证码,不然还得加个gui模块,把图片load出来,让用户手工输入验证码再登陆

添加某项目权限

python07.png

一样,先load项目成员管理页面,通过fetch_access_token(url)取token。拼装好formdata,调用API添加一个成员到项目中去。

userid怎么来的?

python08.png

这个API相当于模糊搜索,返回的是git@osc账号合集。
[{"id":340944,"name":"stay4it","username":"stay4it","hash":"0a5cd60ed0a5b79259b0eb6f8b23afe5","avatar":"http://git.oschina.net/uploads/44/340944_stay4it.jpg?1437179788"}]

解析json里的id就可以了。因为结果集是jsonarray,所以需要判断唯一性。

由于fetch_user(q)需要拿到唯一的userid,否则后续添加权限的操作都不能执行。所以脚本执行顺序可以调整下:

  1. login()
  2. fetch_user(q): userid
  3. join_project(project, userid)

通过上述代码就可以将一个账号添加到一个project中了。大功告成。

剩下的就是一些简单优化,以及一个账号添加多个project权限等需求扩展了。

整个代码150行搞定。虽然只有150行,期间调研方案,通过chrome console爬数据,token解析,formdata调试,还有一些python语法不熟悉需要现查。整体从立项到实现花了3个小时。

结束语

  1. 写代码是个很有趣的过程。如果一上来就想着找现成的代码,或者直接问大神怎么写,可能就要花好几天了。除非你有相关领域的大神朋友,否则还是像Stay这样好好分析需求,解决问题吧。

  2. 写代码只是需求实现的最后一环,考虑清楚了再写要比上来就胡乱写代码要高效得多。

  3. 常思考,常实践,别局限于某种语言,而是从生活化的需求着手分解,列出一个个小的task。按部就班的去实现它,不会的现查。久而久之,就成了全干工程师(⁎⁍̴̛ᴗ⁍̴̛⁎)

声明:本文为Stay原创,未经允许请勿转载 有心课堂(stay4it.com) 传递给你的不仅仅是技术~