PHP,网站动态编程语言。
有一天,你入职了一家很大的公司,人事很快就把你拉入公司千人QQ工作群。上级给你布置了一项任务,他想要知道群里所有人QQ号、昵称和部门的关系。
oh,导出EXCEL员工QQ号信息表,我懂,这很简单。于是你打开QQ群,开始对着群成员列表疯狂复制粘贴进EXCEL,当你复制了几百个的时候,发现这群特么1000多人,还有一半没做完...woc,好像有几个人昵称复制错了Orz
作为一名初级工程师,键盘上Ctrl+c、v就要被你按烂了,你的怨念值在上升。你想到了尝试网上各种导出QQ群成员信息工具。于是找啊找,终于找到了那么一两个,可惜公司内网限制下载,好不容易下载安装,一打开还被提示植入病毒,公司电脑不敢瞎搞,只有老实复制粘贴吧!
旁边工位的老程序员老牛实在看不下去了,这很不Professional。喂,那个小白啊,你来在我这登下你的QQ,8分钟后桌面冒出个7.47MB的excel.xlsx文件,小白激动的打开,哇靠——几万条QQ信息,竟然是全公司全集团的所有人的QQ号啊,超乎想象。
小白:老牛我——爱—你
老牛:滚,不搞基
数天后...
教教我嘛,经过小白多日的软磨硬泡,外带非要请吃饭一周,老牛终于答应教小白了——那个,你就当有腾讯高级工程师给你写好了数据接口,现在需要你来对接,用程序登录授权,访问接口拿到数据,这样能理解了吧。我呢尽力给你讲详细点,但可能你是听不懂的,明白一点是一点。实在看不懂就分享给别人虐吧,请吃饭就不用了
出师—程序的诞生➳
①发现
对于你加入的任何一个QQ群(即使不是群主或管理员),你都可以看到其他成员的基础信息。例如:
看到这个页面,初级工程师想到的第一方案是让程序访问这个页面,获取页面HTML字符串,进行文档结构解析。经过进一步的操作分析,我们采用更好的方案——页面中成员信息就是AJAX异步加载的,前后端分离、接口。继续刷新当前页面,通过火狐浏览器F12可查看信息
随着页面下拉,浏览器AJAX异步发出数据请求,以st为起点,end为终止,每次获取20条数据。
[下拉刷新查看数据-gif]
太棒了,这里的数据就是通过访问接口获取的,不需要从页面HTML解析数据。也就是说我们只要模拟浏览器访问,通过接口就可以获取到JSON类型的数据。思路就是这样,但其实还有很多琐碎的工作需要完成和理解。
(针对本文的简要名词解释)
接口:访问一个页面URL地址,例如xxx.com/api/get_member ,页面返回一段字符串,这段字符串以(参数:值)的JSON格式呈现,返回数据。
②获取请求头
我们通过人工安全登录让浏览器就获得Cookie,程序将直接使用,通过火狐浏览器F12监控页面XHR,提取出请求头,Cookie也在其中。这样程序就可以像人工打开浏览器登录该页面一样,通过Cookie验证身份请求数据。
[获取请求头信息-gif]
完整的请求头信息参考:
注意POST之后的地址是需要根据接口不同变化的,另外一些参数我们在程序中是不需要使用的,
在PHP实际的程序中用到的:
以上信息表示:发起请求是64位win10系统的Firefox浏览器,我们设置将其中Cookie设置为参数$Cookie(键值对字符串),其他信息可以认为是固定的(首行POST地址实际是根据接口变化的)。所以只要获得登录后的Cookie,就能用程序模拟浏览器发出请求并且具有访问接口的权限。
请求头的部分已经完成了,通过F12浏览器开发者工具,也可以看到XHR传递到不同接口的参数,下面将详细说明。
③接口分析
现在我们需要分析上面JSON字段的含义,我们只用到其中两个接口,都需要Cookie,通过手动操作QQ登录后授权带参访问它,获得正确的JSON数据。
经过对字段的分析,在数据库中设计两个表qqGroup、qqMember来对接以上数据,我们尽可能保持字段命名的一致性。COMMENT注释中说明了字段的含义,后面的一些字段是为了方便查阅数据自定义追加的,用空行隔开了。
④程序实现思路
首先通过人为手动安全登录QQ,获取bkn和Cookie。其次,我们st设置为0,end直接设置为4000一次获取所有接口数据(虽然不够完美但省去每次20条分页循环),然后需要制定一个QQ群测试一下配置是否有效,然后就可以正式行动。有n个群,就需要反复修改n次QQ群号码。不,继续用程序获取所在QQ群列表,以这个列表为基础数据,循环去请求所有群内成员信息。
⑤程序清单
set.php中:
mycurl.php中:
已知异常返回JSON说明:
到这里所有的编程知识都交给你了。
喝口100ml的纯净水,需要休息好一会。
到这里我也是身感疲惫的,知识点和细节说明非常消耗元气。传道受业解惑,确实任重而道远。专心写文档比程序还难,尤其是程序之后的,想象完成后的神清气爽、如沐春风,为了信仰必须继续,可能吸引到同行小伙伴。中途休一天。
进击—数据会说话➳
⑥数据测试
我们发现最终的成员信息是少于每个群基本信息求和的,上面就相差了1670条。这个结果其实是意料之中的。对于一个真实成员4581人的群,理论只能查阅其中4000人的信息:
在成员管理界面,滚动条拉倒底恰好是4000,不再变化。
是接口设计如此吗?
所以对于一个超过4000人的群,理论上依靠接口仅能获取其中4000条信息,那我们来实际测试下一个4581人的群:
为什么会有事3971,接下来尝试几组参数
根据分析,将目光投向第二组测试数据
st=3972 到 end= 4000 ,应该获取28条,实际只有26,缺少2条。
难道是插入出了问题?我们观察到页面
其实我们的数据库和表字符集一开始已经是utf8mb4,网络上说了一大堆的修改,从MySQL配置my.ini到数据库再到改到表字符集。对于我们这个项目,其实只用改动插入类中设置的字符集即可。因为储存字符集已经是utf8mb4,所以只用传递也设置为utf8mb4就能正常插入。
那些缺失的数量都是由于名字含有特殊符号或表情导致的插入错误,满满的4000,这下圆满了。
至于怎么获取另外的581人,答复为接口设计如此。个人猜测可能开发版本较早,没有想到后来还有超过4000人的QQ群。对于4000人以上的群,部分成员管理从名单溢出,不知道这算不算BUG。另一方面,日常中很少会进到那个管理页面,在QQ群成员面板都可以进行大部分操作,所以完美改进的必要性似乎也很低。
⑦查询SQL
⑧总结
通过对页面的分析,我们知道QQ成员管理是前后端分离开发模式下的产品。前端发起请求,后端响应请求返回JSON数据,页面通过下拉刷新的方式加载数据。我们利用手动登录,拷贝Cookie和相关浏览器信息,让程序模拟浏览器请求数据,最终将公开可见的数据信息,依靠程序能够自动获取。
在这个过程中的很多工作,都是在做黑盒测试,因为我们对接口参数请求规则一无所知,是一个反复尝试求证的过程。另外呢程序其实还有不少需要改进的地方,一个是数据库批量插入,针对单条记录的插入在批量执行时存在重复操作;还有一个是程序是半自动的执行的,需要更加智能化自动获取Cookie的操作。那么,剩下的无尽的探索和发现就由你尽情发挥。have fun
以上。
领取专属 10元无门槛券
私享最新 技术干货