爬取某公考app公基题库的操作
鼓捣了两天,终于搞定了,然后更新了文章!
涉及几个要点。
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)也可以抓取明文数据,有兴趣的读者可以试一试。