爬取某笔公考app公基题库的操作

最近在准备上岸,备考中需做大量的练习,手机APP让练习无处不在,但有个缺点,就是每次只能练习10-20道题目,不能用题海战术,海量做题。能不能把网站的题库及解析都弄下来,在本地电脑上做题呢?以下是我的思路:1、分析并爬取手机软件的题库;2、调整好格式存入xls文件中;3、导入PC版可自定义的考试系统中(如教之初考试系统免费版);4、自行设置考试模式,海量练习。

倒腾了两天,终于搞定,后续再更新文章!

涉及到几个点。

1、关于手机网络数据的分析,我是用Fiddler 4进行的分析。

2、关于excel表格的操控,之前想用xlwings模块,后因没装office,用的是wps2013政府阉割版,无法操控,后改用xlrd、xlutils、shutil、os模块自己写了一个excel操纵类对象,发现还是有问题,后卸载阉割版wps,换了wps2016最新版的,就可以操作了。后来也没换xlwings模块了,将就着用自写模块。大坑:xlrd模块好像不支持中文路径,全部换用英文路径,最后再把文件夹及文件名转换成中文的。

3、题库分类保存。

爬取的题库


教之初考试系统免费版

1、Fiddler抓包手机APP的网络请求

Fiddler是一款非常流行并且实用的http抓包工具,它的原理是在本机开启了一个http的代理服务器,然后它会转发所有的http请求和响应,不仅如此,它还可以支持请求重放等一些高级功能。显然它是可以支持对手机应用进行http抓包的。

设置在同一局域网下电脑端Fiddler抓取手机APP应用网络请求的步骤:

(1)电脑端启动Fiddler,打开菜单栏中的 Tools > Fiddler Options,打开“Fiddler Options”对话框。

Fiddler界面

(2)在Fiddler Options”对话框切换到“Connections”选项卡,然后勾选“Allow romote computers to connect”后面的复选框,然后点击“OK”按钮。(小技巧:HTTPS标签中可以设置下拉框为...from remote clients only ,貌似就只接收远程端的网络请求了)

Fiddler选项Connections界面
Fiddler选项HTTPS界面

(3)在电脑端的命令行输入:ipconfig,找到本机的ip地址。(我的局域网IP:192.168.1.10)

cmd命令行

(4)在手机端,打开android设备的“设置”->“WLAN”,找到你要连接的网络,在上面长按,然后选择“修改网络”,弹出网络设置对话框,然后勾选“显示高级选项”。(其实苹果手机也是类似的)

(5)在“代理”后面的输入框选择“手动”,在“代理服务器主机名”后面的输入框输入电脑的ip地址,在“代理服务器端口”后面的输入框输入8888,然后点击“保存”按钮。

手机端代理设置

(6)然后启动android设备中的APP应用,在fiddler中可以看到完整的请求和响应数据。

Fiddler响应数据

2、手机APP应用网络数据分析

手机上打开某笔公考软件后,从Fiddler左侧栏中可以看到大量的请求链接。

Fiddler网络请求响应

点击上图黄色区域的链接,可看到右侧详细数据。

详细数据

在右侧详细数据栏中,我们可以看到请求的网址:POST http://xxxbi.com/android/sydw/exercises?&platform=android22&version=6.4.3&vendor=Tencent&app=gwy&deviceId=F4J/K8kXx6+C24yqFuzAiA==&av=8&kav=3 HTTP/1.1

post请求的参数keypointId=621638&type=3&limit=15

返回的数据为Json格式,从返回数据中我们可以找出questionIds对应的题目编号,如2084744.

点击上上图(Fiddler网络请求响应)中红色框中的链接地址,我们可以看到右侧详细数据栏的数据

详细数据

从上图中我们可以找到ID号为2084744的题目的题干、选项、题型、答案等有用数据。

分析基本结束,此手机APP应用的模式基本是这样:先请求15道题的ids,再根据meidaoti的ids请求题目相关数据。后续测试发现,请求questionIds时,修改参数,能一次最多请求到100道题的ids。

另外,从左侧请求链接可以找出对应的章节分类请求链接,根据分类号再查找对应的questionids,就可以把所有的题目抓取出来。

基本抓取思路

3、xls操控

将就着基于xlrd模块编写自用模块。

自用xls操控模块

源码在此,可能格式错乱。需整理。

'''python

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

"""

Created on 2018-05-14 12:48:07

@author: wangzheng

Sys_Env : Windows_AMD64 Python3.5.2

Wechat : hrcl2015(微信)

Filename: MyXls.py

Description : xls文件操控类MyXls

            注意:文件路径中不能有中文名,否则出错

"""

from xlrd import open_workbook

from xlutils.copy import copy

import os,shutil

class MyXls:

    def __init__(self,fpath=None,modelfpath=None,sheetindex=None,protectrow=None,overwrite=True):

        self.openxlspath=''#已打开的xls文件

        self.sheetindex=None#当前工作表索引

        self.rb=None#

        self.wb=None#workbook工作簿

        self.ws=None#worksheet工作表

        self.headrow=0#开头保护行数

        if (fpath is not None) and (modelfpath is not None):

            self.open_copy_xls(modelfpath,fpath,True)

        elif fpath is not None:self.open_xls(fpath)

        if sheetindex is not None:self.get_sheet(sheetindex)

        if protectrow is not None:self.headrow=protectrow


    def open_xls(self,fpath):

        path=fpath

        try:

            rb = open_workbook(path)

        except Exception as err:

            print("File not exists: "+str(err))

            return False

        #通过sheet_by_index()获取的sheet没有write()方法

        #rs = rb.sheet_by_index(0)

        #rs = rb.sheet_by_name('sheet 1')

        self.wb = copy(rb)

        self.openxlspath=path

        return True


    def get_sheet(self,sheet_index=0):

        sheets=sheet_index

        #通过get_sheet()获取的sheet有write()方法

        self.ws = self.wb.get_sheet(sheets)

        self.sheetindex=sheets


    def write_xls(self,row_index,column_index,data_str):

        row,col,data=row_index,column_index,data_str

        #写入数据

        self.ws.write(row,col,data)#write(行,列,内容),索引从0开始


    def write_xls_bycolname(self,row_index,column_name,data_str):

        column_index=self.colname_to_num(column_name)

        row,col,data=row_index,column_index,data_str

        #写入数据

        self.ws.write(row,col,data)#write(行,列,内容),索引从0开始

    def write_xls_bysheet(self,sheetindex,row_index,column_name,data_str):

        '''在指定工作表的指定行列表格中写入数据'''

        if self.sheetindex != sheetindex :self.get_sheet(sheetindex)

        self.write_xls_bycolname(row_index,column_name,data_str)

    def save_xls(self,fpath=None):

        if fpath is None:

            self.wb.save(self.openxlspath)

            print('saved '+self.openxlspath)

        else:

            path=fpath

            self.wb.save(path)#保存xls文件

            print('saved '+path)

        return True


    def open_copy_xls(self,model_fpath,new_fpath,overwrite=True):

        '''参照模板文件,复制并打开xls文件'''

        if os.path.exists(model_fpath) :

            new_fpath=self.auto_mkdir(new_fpath)

            if (not os.path.exists(new_fpath)) or overwrite:

                #print('copy[%s]to[%s]'%(model_fpath,new_fpath))

                shutil.copy(model_fpath,new_fpath)

                return self.open_xls(new_fpath)

            else:print('新文件已存在,请修改新文件名!');return False

        else:print('模板文件不存在,不能复制到新文件!');return False

    def num_to_colname(self,col_index,start=0):

        #列索引转列名,基数start从0开始,0-->A

        if type(col_index) != int:

            return col_index

        if start==0:

            x=col_index+1

        elif start==1:

            x=col_index

        s=''

        flag=False#借位标志

        while x>26:

            y=x%26#取余0-25

            if y==0:y=26;flag=True;

            d=chr(y+64)#低位

            s=d+s

            x=x//26#整除取商

            if flag:x=x-1;flag=False;#如果借位,商要先-1

        g=chr(x+64)#高位

        s=g+s

        return s


    def colname_to_num(self,colname,start=0):

        #列名转列索引 A-->0,B->1,开始基数start为0

        if type(colname) is not str:

            return colname

        colname=colname.upper()#转成大写

        col = 0

        power  = 1

        #print(len(colname))#位数

        for i in range(len(colname) - 1, -1, -1):#range(start=0,stop,step=1)

            ch = colname[i] #倒序取字母

            #print(ch)#所在位上的字母

            col += (ord(ch) - ord('A') +  1 ) * power

            power *= 26

        #print(col-1)

        if start==0:return col-1

        if start==1:return col


    def auto_mkdir(self,fpath):

        '''自动补全目录,目录不存在就创建目录'''

        #fpath='D:\\MyPython\\粉笔公考题库提取\\678\\980\\test.txt'

        fpath=fpath.replace('\\','/')

        if not os.path.exists(fpath):

            plst=fpath.split(sep='/')

            path=''

            if not fpath.endswith('/'):plst=plst[:-1]

            for p in plst:

                path=path+p+'/'

                if not os.path.exists(path):os.mkdir(path)

            return fpath


if __name__=='__main__':

    model_fpath='D:\\MyPython\\model.xls'

    new_fpath='D:\\MyPython\\abc\\123/out.xls'

#    myxls=MyXls()

#    myxls.open_copy_xls(model_fpath,new_fpath)

#    myxls.get_sheet(0)

    myxls=MyXls(new_fpath,model_fpath,2,3)

    myxls.write_xls_bycolname(6,'K','K列6行数据')

#    myxls.save_xls(new_fpath)

    myxls.save_xls()

    pass

'''

4、文件保存

保存成xls文件,和txt文件,txt文件再转换成word文档打印出来。大概有7个大类,100+小类,12737道题。

5、导入题库软件

xls文件导入题库中。

6、大功告成


PS:某笔app更新后,加入了防抓取数据的功能,貌似安卓5.1以上的都不能抓取了。

据资深网友反应,使用安卓模拟器(系统版本4.4)还可以抓到明文数据,有兴趣的读者可以试一试。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342