我这个学期参加了微软校园品牌大使的项目,跟我想象的差的有点远,好在福利不错。 虽然是选的是技术组,但是做的还是调查问卷的活。 问题来了,微软的客户端做的令人发指的差。 所有的内容都得靠鼠标点选,而且必须是精确点击。

为了提高效率,看了下它的问卷存储方式,以.db3后缀存储,经搜索发现为sqlite的数据库格式,不过经过几次尝试,表示打开不能。 既然本地直接先数据库写数据的方式不行,那就模拟客户端发送调查问卷吧。 还是老办法,直接抓包。 显示是直接向http://211.100.47.85/Question/SurveyWebService.asmx传送一个xml。 问题就变得简单多了。根据多次抓包的格式,python代码如下:

import httplib2
import re
import os
import time

global UserID,UniversityID,CityID
UserID='13020602'#大使ID
UniversityID='163'#大学ID
CityID='2'#城市ID

def sendSurvey(xmlinfo):
    """
    传入xml正文,发送出去,如果提交成功则返回1,其他返回0
    """
    server=httplib2.Http()
    #设置头消息
    headers={'Content-Type': 'application/soap+xml; charset=utf-8',\
    'SOAPAction': '"http://tempuri.org/updateQuestionnaire"' ,\
    'Host': '211.100.47.85' ,\
    'User-agent':"XuGuofan's Python Client"}
    #xml提交地址
    surveyUrl="http://211.100.47.85/Question/SurveyWebService.asmx"
    #提交过程,返回回应和正文
    resp, content = server.request(surveyUrl, "POST", body=xmlinfo, headers=headers)
    print(content.decode())
    #获取状态提示
    respre=re.compile(r'(?<=updateQuestionnaireResult>).+?(?=</updateQuestionnaireResult>)')
    #从byte转换为string
    rsp=respre.findall(content.decode())
    if(len(rsp)):
        #返回成功
        if(rsp[0]=='success'):
            print('上传问卷成功')
            return 1
        elif(rsp[0]=='exist'):
            print('该问卷已存在')
            return 0
        else:
            print('上传问卷错误')
    #无任何返回
    else:
        print("未知错误!")
        return 0

def getUploadCounts(xmlinfo):
    """
    传入xml正文,发送出去
    """
    server=httplib2.Http()
    #设置头消息
    headers={'Content-Type': 'text/xml; charset=utf-8',\
    'SOAPAction': '"http://tempuri.org/getUploadCounts"' ,\
    'User-agent':"XuGuofan's Python Client"}
    #xml提交地址
    surveyUrl="http://211.100.47.85/Question/SurveyWebService.asmx"
    #提交过程,返回回应和正文
    resp, content = server.request(surveyUrl, "POST", body=xmlinfo, headers=headers)
    respre=re.compile(r'(?<=Result>).+?(?=</getUpload)')
    resp=respre.findall(content.decode())
    num=resp[0].split(",")
    # print(resp)
    myup=int(num[1])
    ourup=int(num[0])
    print("您已上传{}份调查问卷,还需上传{}份问卷".format(myup,138-myup))
    print("小组上传{}份调查问卷,还需上传{}份问卷".format(ourup,550-ourup))

def convert(str):
    """
    为了便于输入,各选项之间用/分开,多选用*分开
    这样是为了更好的利用小键盘输入
    """
    str=str.replace("/","\t")
    str=str.replace("*",",")
    return str;

def readSurvey(filename):
    """
    传入文件名,读取内容,返回一个二维的list
    代表每张问卷的每个答案
    """
    #读取文件内容
    try:
        infile=open(filename)
    except IOError:
        print ("错误: 无法读取文件!")
        input('任意键退出!')
        exit() 
    file_content=infile.read()
    infile.close()
    #将内容转换完成
    file_content=convert(file_content)
    #每一行都成为一个Survey
    Survey=file_content.split("\n")
    #先确定一个list
    SurveyDetial=[]
    #将每一行的内容再次转换为一个list
    for u in Survey:
        SurveyDetial.append(u.split("\t"))
    #返回的为list,各下标对应各个不同的调查对象
    #可以理解为二维数组
    return SurveyDetial

def createUpdateXML(Detial):
    """
    传入一个list,要求其各下标对应各调查题的选项
    返回一个正常的xml,byte型的吧
    """
    xmlhead='<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body>'\
    +'<updateQuestionnaire xmlns="http://tempuri.org/">'\
    +'<UserID>'+UserID+'</UserID>'\
    +'<UniversityID>'+UniversityID+'</UniversityID>'\
    +'<CityID>'+CityID+'</CityID>'
    xmlsurvey="<SurveyName>"+Detial[0]+"</SurveyName>"\
    +"<SurveyEmail>"+Detial[1]+"</SurveyEmail>"\
    +"<NowUseDevice>"+Detial[2]+"</NowUseDevice>"\
    +"<NowUseOtherDevice></NowUseOtherDevice>"\
    +"<NowUseSys>"+Detial[3]+"</NowUseSys>"\
    +"<Characters>"+Detial[6]+"</Characters>"\
    +"<BeforeNominateWin8>"+Detial[7]+"</BeforeNominateWin8>"\
    +"<AfterNominateWin8>"+Detial[8]+"</AfterNominateWin8>"\
    +"<BeforeWin8IsCreative>"+Detial[9]+"</BeforeWin8IsCreative>"\
    +"<AfterWin8IsCreative>"+Detial[10]+"</AfterWin8IsCreative>"\
    +"<BeforeWin8InOurLife>"+Detial[11]+"</BeforeWin8InOurLife>"\
    +"<AfterWin8InOurLife>"+Detial[12]+"</AfterWin8InOurLife>"\
    +"<BeforeSelectPlatform>"+Detial[13]+"</BeforeSelectPlatform>"\
    +"<AfterSelectPlatform>"+Detial[14]+"</AfterSelectPlatform>"\
    +"<BeforeSelectPad>"+Detial[15]+"</BeforeSelectPad>"\
    +"<AfterSelectPad>"+Detial[16]+"</AfterSelectPad>"\
    +"<BeforeImpression></BeforeImpression>"\
    +"<AfterImpression></AfterImpression>"\
    +"<BeforeNominateComputer></BeforeNominateComputer>"\
    +"<AfterNominateComputer></AfterNominateComputer>"\
    +"<BeforeNominateWinPhone>"+Detial[17]+"</BeforeNominateWinPhone>"\
    +"<AfterNominateWinPhone>"+Detial[18]+"</AfterNominateWinPhone>"\
    +"<BeforeSelectPhone>"+Detial[19]+"</BeforeSelectPhone>"\
    +"<AfterSelectPhone>"+Detial[20]+"</AfterSelectPhone>"\
    +"<AttendSurvey>"+Detial[21]+"</AttendSurvey>"\
    +"<EndXp>"+Detial[4]+"</EndXp>"\
    +"<WantUpdate>"+Detial[5]+"</WantUpdate>"
    xmllast="</updateQuestionnaire></soap12:Body></soap12:Envelope>"
    return ((xmlhead+xmlsurvey+xmllast).encode())

def createCountsXML(year,month):
    xmlinfo='<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>\
    <getUploadCounts xmlns="http://tempuri.org/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">\
    <userid>'+UserID+'</userid>\
    <universityid>'+UniversityID+'</universityid>\
    <year>'+year+'</year>\
    <month>'+month+'</month>\
    </getUploadCounts>\
    </s:Body></s:Envelope>'
    return xmlinfo

def Update():
    count=0
    inputfile=input('请输入文件名:')
    survey=readSurvey(inputfile)
    print('共有{}份调查问卷等待上传!'.format(len(survey)))
    print('问卷汇报:')
    for i in survey:
        print(i)
        # print(createUpdateXML(i))
        count=count+sendSurvey(createUpdateXML(i))
    print('共有{}份调查问卷上传成功!'.format(count))

def Counts():
    localtime=time.localtime(time.time())
    year=time.strftime('%Y',localtime)
    month=time.strftime('%m',localtime)
    getUploadCounts(createCountsXML(year,month))
    print()

def person():
    inputUser=input('请输入大使ID:')
    if(inputUser!=''):
        UserID=inputUser
    inputUni=input('请输入学校ID:')
    if(inputUni!=''):
        UniversityID=inputUni

def main():
    print('微软校园品牌大使调查问卷上传客户端')
    print('1.上传问卷')
    print('2.查询问卷')
    choose=input('请输入选项')

    if(choose=='1'):
        person()
        Update()
    elif(choose=='2'):
        person()
        Counts()
    input('任意键退出')

main()