强智系统爬虫分析

强智系统爬虫分析

  • 一、登录分析
  • 二、其他分析

一、登录分析

我校使用的教务管理系统是叫做强智系统,有一天我就突发奇想想要搞一个爬虫去给他搞一搞。
1.刚开始我以为是非常简单的一个post请求就解决的事情,我就post了一个

data = {
		username: 'xxxx',
		password: 'xxxx',
		RANDOMCODE: 'XXXX',
		}

由于我还是太年轻,没有经历过反爬虫的毒打,果然返回了登陆失败。然后我就看了下网页源代码
强智系统爬虫分析_第1张图片
咋回事?这玩意就提交了一个encoded和RANDOMCODE,竟然没有提交username和password。根据我多年的后端经验(假的,ε=ε=ε=┏(゜ロ゜;)┛)肯定这个encoded就是password和username进行加密编码后的产物。果然当我阅读他后面的一段js代码我发现了隐秘。
强智系统爬虫分析_第2张图片
从中我们可以看到它通过一个叫encodeInp的函数进行加密(转码)然后把这两个通过%%%进行连接(好智障的一个设定)。然后我再一个叫做conwork.js的js文件中发现了这个函数。
在这里插入图片描述
强智系统爬虫分析_第3张图片
找到这个文件就好解决了,我通过PyExecJs来调用这个js文件里面的函数。
登录代码如下

'''简单解析验证码'''
def parse_verity_code(session, img_url):
    img_content = session.get(img_url)
    img = Image.open(BytesIO(img_content.content))
    img.save('a.png')
    verify_image = Image.open('a.png')
    code = pytesseract.image_to_string(verify_image)
    time.sleep(2)
    return code


'''
对账号密码进行编码
'''

def make_user_token(username, password):
    with open('conwork.js') as f:
        ctx = execjs.compile(f.read())
        username_encode = ctx.call('encodeInp', username)
        password_encode = ctx.call('encodeInp', password)
    token = username_encode + '%%%' + password_encode
    print(token)
    return token    

二、其他分析

其实在登录之后事情就变的简单多了,这管理系统没有那么多的反爬机制,所以你想干啥就能干啥。下面完整代码展示下,我这里隐去我们学校的网站

# encode: utf-8
import re
from io import BytesIO
import requests
from lxml import etree
from PIL import Image  # 用于显示图片
import pymongo
import pytesseract
import time
import execjs

#
# MONGO_CLIENT = pymongo.MongoClient("mongodb://127.0.0.1:27017")
# mydb = MONGO_CLIENT['xxu_jwxt']
# mycol = mydb['score_list']

BASE_URL = "https://jwxt.xx大学.edu.cn"

SCORE_FOR_USER = []

USERNAME = '2017xxxxxx'
PASSWORD = 'xxxxxxxxxx'


def parse_verity_code(session, img_url):
  img_content = session.get(img_url)
  img = Image.open(BytesIO(img_content.content))
  img.save('a.png')
  verify_image = Image.open('a.png')
  code = pytesseract.image_to_string(verify_image)
  time.sleep(2)
  return code


'''
对账号密码进行编码
'''


def make_user_token(username, password):
  with open('conwork.js') as f:
      ctx = execjs.compile(f.read())
      username_encode = ctx.call('encodeInp', username)
      password_encode = ctx.call('encodeInp', password)
  token = username_encode + '%%%' + password_encode
  print(token)
  return token


'''
  解析登录页面
'''


def parse_login(url):
  headers = {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
  }
  session = requests.session()
  resp = session.get(url, headers=headers)
  text = resp.text

  html = etree.HTML(text)
  img = html.xpath("//img/@src")[1]
  img_url = BASE_URL + img
  while True:
      try:
          code = parse_verity_code(session, img_url)
          code = re.sub("[^\d\w]", '', code)
          print("验证码:" + code)
          login_url = BASE_URL + "/jsxsd/xk/LoginToXk"
          print(login_url)
          '''
              用户名和密码会加密后以%%%连接
          '''
          encoded = make_user_token(USERNAME, PASSWORD)
          data = {
              'encoded': encoded,
              'RANDOMCODE': code,
          }
          print(data)

          rs = session.post(login_url, data)  # 进行登录操作

          # 成绩列表
          score_page_url = 'https://jwxt.xxu.edu.cn/jsxsd/kscj/cjcx_list'

          resp = session.get(score_page_url, headers=headers)
          score_list = etree.HTML(resp.text)
          data_list = score_list.xpath('//table[@id="dataList"]')[0]
          scores = data_list.xpath(".//tr")[1:]
          for score in scores:
              tds = score.xpath(".//td")
              goal_data = {
                  'id': tds[0].text,
                  'term': tds[1].text,
                  'cno': tds[2].text,
                  'cname': tds[3].text,
                  'score':  tds[4].xpath('.//a/text()')[0],
                  'point': tds[5].text,
                  'total_point': tds[6].text,
                  'GPA': tds[7].text,
              }
              SCORE_FOR_USER.append(goal_data)
              # mycol.save(goal_data) #  保存到mongo数据库中
              print(goal_data)
          if SCORE_FOR_USER:  # 验证码正确 跳出循环结束程序
              break
      except:
          print("验证码错误")


def main():
  url = "https://jwxt.xxu.edu.cn/jsxsd/"
  parse_login(url)


if __name__ == '__main__':
  main()

你可能感兴趣的:(爬虫,爬虫分析,模拟登陆,python)