爬取某公考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,提琴手抢手机APP的网络请求。

Fiddler是一个非常流行和实用的“计算机连接”,然后点击“确定”按钮。(提示:您可以将下拉框设置为...仅在HTTPS标签中来自远程客户端,该标签似乎仅接收来自远程终端的网络请求。)

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

(4)在手机端,打开安卓设备的“设置”->;“WLAN”,找到要连接的网络,按住不放,然后选择“修改网络”弹出网络设置对话框,再勾选“显示高级选项”。(其实苹果手机也差不多。)

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

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

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

你在手机上打开一个公考软件后,可以在Fiddler的左栏看到很多请求链接。

点击上面黄色区域的链接,查看右边的详细数据。

在右边的详细数据栏,我们可以看到请求的网址:POST /android/sydw/exercises?& amp平台= android22 & amp版本= 6 . 4 . 3 & amp;供应商=腾讯& ampapp = gwy & ampdevice id = F4J/k8kxx 6+c 24 yqfuzaia = = & amp;av = 8 & ampkav=3 HTTP/1.1

post请求的参数key point id = 621638 &;type = 3 & amp极限=15

返回的数据是Json格式的。从返回的数据中,我们可以找出对应于questionIds的题号,比如2084744。

点击上图(Fiddler network request response)红框中的链接地址,我们可以看到右边详细数据一栏中的数据。

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

分析基本结束了,这个手机app的应用模式基本如下:先请求15题的id,再根据美道提的id请求题目相关数据。随后的测试表明,当您请求questionIds时,通过修改参数,您可以一次请求多达100个问题的id。

另外,可以从左边的请求链接中找出对应的章节分类请求链接,然后根据分类号找到对应的questionids,这样就可以抓取所有的题目了。

3、xls控件

我将基于xlrd模块编写自己的模块。

源代码在这里,格式可能有问题。需要分类。

“”python

#!/usr/bin/env python3

# -*-编码:utf-8 -*-

"""

创建于2018-05-14 12:48:07

@作者:王政

sys _ Env:Windows _ AMD64 python 3 . 5 . 2

微信:hrcl2015(微信)

文件名:MyXls.py

描述:xls文件操作类MyXls

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

"""

从xlrd导入open_workbook

从xlutils.copy导入副本

导入操作系统,shutil

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 #工作簿

Self.ws = None #工作表

自我。header = 0 #开始时受保护的行数。

if (fpath不是None)和(modelfpath不是None):

self.open_copy_xls(modelfpath,fpath,True)

elif fpath不是None:self.open_xls(fpath)

如果sheetindex不为None:self.get_sheet(sheetindex)

如果protectrow不为None:self.headrow=protectrow

def open_xls(self,fpath):

path=fpath

尝试:

rb = open_workbook(路径)

例外为err:

print("文件不存在:"+str(err))

返回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

返回True

def get_sheet(self,sheet_index=0):

工作表=工作表索引

#通过get_sheet()获取的工作表有一个write()方法。

self.ws = self.wb.get_sheet(工作表)

self.sheetindex=sheets

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

行,列,数据=行索引,列索引,数据字符串

#写入数据

Self.ws.write (row,col,data) # write (row,column,content),索引从0开始。

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

column _ index = self . colname _ to _ num(column _ name)

行,列,数据=行索引,列索引,数据字符串

#写入数据

Self.ws.write (row,col,data) # write (row,column,content),索引从0开始。

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

''将数据'''写入指定工作表的指定行和列表中。

if self.sheetindex!= sheet index:self . get _ sheet(sheet index)

self . write _ xls _ by colname(row _ index,column_name,data_str)

def save_xls(self,fpath=None):

如果fpath为None:

self.wb.save(self.openxlspath)

print('saved '+self.openxlspath)

否则:

path=fpath

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

打印('已保存'+路径)

返回True

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

''复制并打开引用模板文件的xls文件'''

如果os.path .存在(model_fpath):

new _ fpath = self . auto _ mkdir(new _ fpath)

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

#print('将[%s]复制到[%s]'%(model_fpath,new_fpath))

shutil.copy(模型路径,新路径)

return self.open_xls(new_fpath)

Else:print('新文件已经存在,请修改新文件名!');返回False

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

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

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

if type(col_index)!= int:

返回列索引

如果start==0:

x=col_index+1

elif start==1:

x =列索引

s= ' '

Flag=False#借用标志

而x & gt26:

Y=x%26#余数0-25

如果y = = 0:y = 26;flag = True

D=chr(y+64)#低

s=d+s

X=x//26#整除商

if标志:x = x-1;flag = False#如果借座位,必须先-1。

G=chr(x+64)#高位

s=g+s

返回s

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

#列名到列索引A-> 0,B-& gt;1,起始基数start为0。

如果类型(列名)不是字符串:

返回列名

Colname=colname.upper()#转换为大写。

col = 0

权力?= 1

#print(len(colname))#位数

对于范围内的I(len(colname)- 1,-1,-1):#range(start=0,stop,step=1)

Ch = colname[i] #以相反的顺序取字母

在#print(ch)#位置的字母

col += (ord(ch) - ord('A') +?1 ) *功率

幂*= 26

#打印(col-1)

如果start==0:返回col-1

如果start==1:返回col

def auto_mkdir(self,fpath):

''自动完成目录,如果目录不存在,则创建目录'''

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

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

如果不是os.path.exists(fpath):

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

路径= ' '

如果不是fpath . ends with('/'):plst = plst[:-1]

对于plst中的p:

path=path+p+'/'

如果不是OS . path . exists(path):OS . mkdir(path)

返回路径

if __name__=='__main__ ':

model _ fpath = ' D:\ \ my python \ \ model . xls '

new _ fpath = ' D:\ \ my python \ \ 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()

及格

'''

4、文件保存

保存为xls文件和txt文件,然后将txt文件转换为word文档并打印出来。大概有7大类,100+小类,12737题。

5.导入题库软件

Xls文件导入到题库中。

6.你完了

PS:某app更新后,增加了防止数据被抓取的功能。好像安卓5.1及以上都爬不了。

根据资深网友的回应,使用Android模拟器(系统版本4.4)也可以抓取明文数据,有兴趣的读者可以试一试。