老婆大人每个月都要上一个网站上去查数据,然后做报表。

为了减轻老婆大人的工作压力,所以我决定做个小程序,减轻我老婆的工作量。

准备工作

1.tesseract-ocr

这个工具用来识别验证码,非常好用。

ubuntu上安装:

sudo apt-get install tesseract-ocr

非常简单。

2.pytesseract和PIL(pillow)

pytesseract用来在python中调用tesseract-ocr,PIL(pillow)用来加载图片,安装方法如下:

pip3 installpytesseract

pip3install pillow

也非常简单。

如果安装pillow的时候报如下错误:

ValueError: zlib is required unless explicitly disabled using --disable-zlib, aborting

那么我们更新一下pip即可

sudo pip3 install --upgrade pip

如果pip速度很慢,可以改用国内的源,在命令后面加上 -i http://pypi.douban.com/simple (百度一下一大把),但pillow好像国内镜像都没有,只能用蜗牛速度从自带的源下载咯...

一切准备就绪。

分析网站

我们的目标网址是:http://222.217.19.16:3512/Site/LzsfySite/Default.aspx

预览图:

看上去很low啊...心疼我老婆....看来我必须快点完成这个小程序了!

经过简单的分析可以得到关键信息:

1.表单的提交地址:http://222.217.19.16:3512/Site/LzsfySite/Default.aspx

2.验证码地址:http://222.217.19.16:3512/Main/AspCode/ZhuChengXu/AuthenImage.aspx

3.表单的格式:

1 {2 '__LASTFOCUS' : '',3 '__EVENTTARGET' : 'ctl00$ContentPlaceHolder1$Login1$btnLogin',4 '__EVENTARGUMENT' : '',5 '__VIEWSTATE': __VIEWSTATE,6 '__EVENTVALIDATION': __EVENTVALIDATION,7 'ctl00$ContentPlaceHolder1$Login1$txtUsr': 用户名,8 'ctl00$ContentPlaceHolder1$Login1$txtPwd': 用户密码,9 'ctl00$ContentPlaceHolder1$Login1$txtYZM': 验证码10 }

其中4、5、6行是访问首页的时候,在首页的源代码中返回的参数

但__EVENTARGUMENT常年为空,所以干脆直接写死空字符串即可;__VIEWSTATE和__EVENTVALIDATION则需要对html进行解析。

7、8、9则对应用户名、密码和验证码,用户名密码可以写死,验证码则需要用到tesseract-ocr进行识别。

4.表单提交的报文头

1 {2 'Accept' : b'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',3 'Accept-Encoding' : 'gzip, deflate, lzma',4 'Accept-Language' : 'zh-CN,zh;q=0.8',5 'Cache-Control' : 'max-age=0',6 'Connection' : 'keep-alive',7 'Content-Length': 表单内容长度,8 'Content-Type' : 'application/x-www-form-urlencoded',9 'Cookie': cookie内容,10 'Host' : '222.217.19.16:3512',11 'Origin' : 'http://222.217.19.16:3512',12 'Referer' : 'http://222.217.19.16:3512/Site/LzsfySite/Default.aspx',13 'Upgrade-Insecure-Requests' : '1',14 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36 OPR/38.0.2220.41}'

15 }

其中7行可以根据构造的表单报问题长度来计算,9行需要从cookie中获取。

主要技术

获取cookie

python3中获取cookie的方式很简单,用http.cookiejar。

importurllib.requestimporturllib.parseimporthttp.cookiejar#登录的主页面

hosturl = 'http://222.217.19.16:3512/Site/LzsfySite/Default.aspx'#设置一个cookie处理器,它负责从服务器下载cookie到本地,并且在发送请求时带上本地的cookie

cj=http.cookiejar.LWPCookieJar()

cookie_support=urllib.request.HTTPCookieProcessor(cj)

opener=urllib.request.build_opener(cookie_support, urllib.request.HTTPHandler)

urllib.request.install_opener(opener)#打开登录主页面(目的是从页面下载cookie,这样我们在再送post数据时就有cookie了,否则发送不成功)

hostOpen =urllib.request.urlopen(hosturl)#解析cookie

cookieText = ''

for item incj:

cookieText= cookieText + item.name + '=' + item.value + '&'cookieText= cookieText[0:-1]print(cookieText)

这样我们就可以得到cookie啦。

识别验证码

这个也简单,我们先把它下载到本地,然后用pytesseract来解析它:

importurllib.requestimportpytesseractfrom PIL importImage#验证码图片地址

checkCodeUrl = 'http://222.217.19.16:3512/Main/AspCode/ZhuChengXu/AuthenImage.aspx'

#下载验证码

checkCodeOpen =urllib.request.urlopen(checkCodeUrl)

data=checkCodeOpen.read()

local= open('image.gif', 'wb')

local.write(data)

local.close()#pytesseract解析

img = Image.open('image.gif')

checkCode=pytesseract.image_to_string(img)print(checkCode)

哈哈哈哈就这么简单暴力~

诶等等!好像有点不对。我们多执行几次,然后对比一下输出和图片

                ...出现了英文,什么鬼...再来

        ...这次是正确的。再试试...

                 又不对了。

多试几次,发现验证码的识别率不太高。

在识别率不高的情况下,那么我们只有开个循环,多识别几次验证码,然后多提交几次表单即可。——总有一次会正确滴~~

#以下是伪代码

def提交方法():

识别验证码

构造表单

提交表单

解析服务器返回报文if登录成功:returntrueelse:returnfalsewhile not提交方法():

等待1000秒print('登录成功啦')

解析html

我这里用的是python自带的HTMLParser,这种简单暴力的办法非常好用。   ^_^

from html.parser importHTMLParserimporturllib.request#主页面

hosturl = 'http://222.217.19.16:3512/Site/LzsfySite/Default.aspx'

#打开登录主页面

hostOpen =urllib.request.urlopen(hosturl)#解析__VIEWSTATE和__EVENTVALIDATION#这里用了HTMLParser的库。#自定义的DefaultHTMLParser继承了HTMLParser#在调用此类型对象的feed方法对二进制字节流解析时,#若遇到tag的开始标签则会触发handle_starttag方法,#若遇到tag中的内容时则会触发handle_data方法

classDefaultHTMLParser(HTMLParser):def __init__(self):

HTMLParser.__init__(self)

self.hasLogin=False#如果是input标签,则判断其id属性是否是__VIEWSTATE或__EVENTVALIDATION

#如果是二者之一,则在对象.xxxx属性中存入对应值

#这里假定一定能够从中读取到__VIEWSTATE和__EVENTVALIDATION

#没有做错误处理

defhandle_starttag(self, tag, attrs):

iid= ''value= ''

if tag == 'input':for attr inattrs:if attr[0] == 'id':

iid= attr[1]break;

#用exec来设置属性值,节省代码量^_^if iid in ('__VIEWSTATE', '__EVENTVALIDATION'):for attr inattrs:if attr[0] == 'value':exec('self.' + iid + "= attr[1]")defhandle_data(self, data):#根据能否找到跳转语句判断是否登陆

if data.find('window.location=\'../../Main/AspCode/ZhuChengXu/ShowSelect.aspx\'') != -1:

self.hasLogin=True#get方法,用来获取属性值。

#这里偷懒用了eval——eval的效率不太高,但非常省代码量。

#如果对执行速度要求比较高建议不要用这个方法喔。

defget(self, attr):

result= eval('self.' +attr)returnresult

p=DefaultHTMLParser()

p.feed(hostOpen.read().decode('GB2312'))print(p.get('__VIEWSTATE'))print(p.get('__EVENTVALIDATION'))

提交表单

根据之前的内容,我们已经获取了提交登录表单所需要的一切信息。

所以我们可以开始构造一个表单并提交

1 importzlib2 importurllib.request3 importurllib.parse4

5 #表单提交的url

6 hosturl = 'http://222.217.19.16:3512/Site/LzsfySite/Default.aspx'

7

8 #构造表单

9 formData ={10 '__LASTFOCUS' : '',11 '__EVENTTARGET' : 'ctl00$ContentPlaceHolder1$Login1$btnLogin',12 '__EVENTARGUMENT' : '',13 '__VIEWSTATE' : '__VIEWSTATE',14 '__EVENTVALIDATION' : '__EVENTVALIDATION',15 'ctl00$ContentPlaceHolder1$Login1$txtUsr' : '用户名',16 'ctl00$ContentPlaceHolder1$Login1$txtPwd' : '密码',17 'ctl00$ContentPlaceHolder1$Login1$txtYZM' : 'xxxx'

18 }19 #对formData进行url编码

20 formData =urllib.parse.urlencode(formData)21

22 #构造登陆用header

23 headers ={24 'Accept' : b'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',25 'Accept-Encoding' : 'gzip, deflate, lzma',26 'Accept-Language' : 'zh-CN,zh;q=0.8',27 'Cache-Control' : 'max-age=0',28 'Connection' : 'keep-alive',29 'Content-Length' : len(formData.encode('GB2312')),30 'Content-Type' : 'application/x-www-form-urlencoded',31 'Cookie' : 'cookieText',32 'Host' : '222.217.19.16:3512',33 'Origin' : 'http://222.217.19.16:3512',34 'Referer' : 'http://222.217.19.16:3512/Site/LzsfySite/Default.aspx',35 'Upgrade-Insecure-Requests' : '1',36 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36 OPR/38.0.2220.41}'

37 }38

39 #开始登陆

40 loginRequest = urllib.request.Request(hosturl, formData.encode('GB2312'), headers)41 loginResponse =urllib.request.urlopen(loginRequest)42 #返回的数据是压缩过的,所以要用zlib进行解码

43 loginResponseData = zlib.decompress( loginResponse.read(), 16+zlib.MAX_WBITS).decode('GB2312')44

45 print(loginResponseData)

需要注意的是,12-17行以及31行这里要填入前几节说明的解析的内容。否则服务器会返回500的响应码喔。

上述内容基本上涵盖了做一个爬虫所需要的知识。

扩展内容

但我的工作还没完,我还得给我老婆生成一个excel,并发送到她邮箱!

所以,下面是关于写excel和发送email的扩展内容,不感兴趣的同学可以跳过啦。

快捷写入excel

我们可以先手动做一个有标题,但内容为空的excel模板,像这样:

注意,这里是第四个sheet。然后将其保存为empty.xls

先安装。

sudo pip3 install xlutils

简单示例:

1 from xlutils.copy importcopy2 importxlrd3 importxlwt4 from xlwt.Style importeasyxf5

6

7 #打开文件,formatting_info=true表示读入单元格style信息

8 file = xlrd.open_workbook('empty.xls',formatting_info=True)9 #用xlutils.copy的copy方法获取一个报表对象

10 w =copy(file)11

12 #定义居中对齐格式示例

13 alignment =xlwt.Alignment()14 alignment.horz =xlwt.Alignment.HORZ_CENTER15 style =xlwt.XFStyle()16 style.alignment =alignment17

18 #write方法的第一个参数对应要写入的行数,第二个参数对应要写入的列数,二者都是从0开始计算的

19 #用居中对齐格式写入第3张sheet的3行7列单元格

20 w.get_sheet(3).write(2,6, '2016 年 7 月 21 日至2016 年 8 月 20 日', style)21 #用居中对齐格式写入第3张sheet的16行3列单元格

22 w.get_sheet(3).write(15,2, '2016 年 8 月 21 日', style)23

24 #定义边框示例

25 borders =xlwt.Borders()26 borders.left = 1

27 borders.right = 1

28 borders.top = 1

29 borders.bottom = 1

30 style =xlwt.XFStyle()31 style.borders =borders32 style.alignment =alignment33

34 #填充数据

35 for i in range(1, 18):36 w.get_sheet(3).write(9,i,int(100), style)37 w.get_sheet(3).write(10,i,int(100), style)38

39

40 #写入公式示例

41 for i in range(1,18):42 column = chr(ord('A')+i)43 w.get_sheet(3).write(13, i, xlwt.Formula('SUM(' + column + '10:' + column + '13)'),style)44

45 #保存为新文件

46 w.save('报表.xls')

然后我们就可以得到如下表格啦~~    python真的是非常简单又暴力...

发送带有附件的email

这个更简单...smtplib在ubuntu下的python是自带的。

示例如下:

importsmtplibfrom email.mime.multipart importMIMEMultipartfrom email.mime.text importMIMETextfrom email.mime.application importMIMEApplicationprint('准备邮件....')#qq邮箱用户名和密码,自带星号屏蔽#必须在账户设置开启smtp服务才能登录

_user = "27*****68@qq.com"_pwd= "***********"_to= "10*****09@qq.com"

#初始化消息

msg =MIMEMultipart()

msg["Subject"] = "2016年9月份统计报表"msg["From"]=_user

msg["To"] =_to#这是文字部分

part = MIMEText("详见附件...")

msg.attach(part)#这是附件部分

part = MIMEApplication(open('报表.xls','rb').read())#filename最好设置成英文,否则容易出乱码

part.add_header('Content-Disposition', 'attachment', filename="baobiao.xls")

msg.attach(part)#开始发送

print('from' + _user + 'to' + _to + '...')#必须要用SSL方式加密

smtp = smtplib.SMTP_SSL('smtp.qq.com')

smtp.login(_user, _pwd)

smtp.sendmail(_user, _to, msg.as_string())

smtp.quit()print('发送完毕')

所做的一切都非常简单!所以python是世界上最好的语言!     笑....

综合上述技术,删删改改增增减减,最后成果展示

最后,感谢我老婆,让我有学习python的动力。

本章完。

python自动登录并提交表单_用python模拟登录(解析cookie + 解析html + 表单提交 + 验证码识别 + excel读写 + 发送邮件)...相关推荐

  1. python自动抢微信红包源码_用Python实现微信自动化抢红包,再也不用担心抢不到红包了...

    1. 概述 刚刚收到了两个消息,一个好消息,一个坏消息. 先说好消息,好消息就是微信群里有人要发红包,开心~ 不过转念一想,前几次的红包一个都没抢到,这次???不由自主的叹了一口气 ... 过了一会, ...

  2. python自动聊天机器人设置回复延迟_用Python 写一个聊天机器人陪你聊天(文尾有彩蛋)...

    一.工具简介 1--Python.写代码的工具: 2--itchat库.第三方库,用来登录微信,接收并回复微信好友信息: 3--图灵机器人.第三方接口,我们本次使用的机器人: 二.代码解析 1.准备 ...

  3. Python Selenium.WebDriver 对Cookies的处理及应用『模拟登录』

    Python Selenium.WebDriver 对Cookies的处理及用途『模拟登录』 文章目录 Python Selenium.WebDriver 对Cookies的处理及用途『模拟登录』 一 ...

  4. python模拟登录qq获取好友信息_使用Python模拟登录QQ邮箱获取QQ好友列表

    最近因开发项目的需要,有一个需求,就是很多SNS网站都有的通过 Email地址 导入好友列表,不过这次要导入的不是Email 列表,而是QQ的好友列表. 实现方式: 通过google一搜,实现的方式大 ...

  5. 查看ie保存的表单_无代码搭建系统(一)——流程表单搭建

    迎着2020疫情带来的线上办公.远程协同办公,把无代码带上风口浪尖,众多无代码厂商迅速发展起来,推出自己的无代码产品.实现全民开发,是无代码发展的愿景和目标.数字化和网络化使各行各业的客户对应用开发的 ...

  6. 用python写一个手机app签到脚本_利用Python实现App自动签到领取积分

    要自动签到,最简单的是打开页面分析请求,然后我们用脚本实现请求的自动化.但是发现食行没有页面,只有 APP,这不是一个好消息,这意味着需要抓包处理了. 有需要Python学习资料的小伙伴吗?小编整理[ ...

  7. 获取form表单_【第1535期】前端 Form 的表单的一个通用解决方案

    前言 今日早读文章由阿里@布达投稿分享. @布达,Alibaba Fusion项目组的.花名潕量.主要专注在设计系统.组件.可视化搭建这个领域 正文从这开始-- Fusion Next - Form ...

  8. 自学python接单_用Python在网上接单,兼职也可以月薪过万

    前言 Python在近几年越来越受追捧,很多童鞋或者职场小伙伴想要提升技能-学习Python. 这是非常好的事情,但问题在于很多人不知道学Python做什么,所以什么零碎细末.艰难晦涩.长篇大论的都去 ...

  9. python简单代码运用到桌面壁纸_五行Python代码自动换你的电脑桌面壁纸(内附源码和exe)...

    很多行友问行哥,Python能不能自动更换电脑壁纸呀,今天它来了 只需要一行代码,指定图片地址即可更换电脑桌面.加上壁纸文件夹路径,让你随机更换电脑桌面,带来不期而遇的新鲜.使用爬虫技术,自动下载壁纸 ...

最新文章

  1. #define list_entry(ptr, type, member) \   container_of(ptr, type, member)
  2. Apache配置--用户认证(针对目录访问)-update2015-05-02
  3. 字母出现位置c语言,【c语言】实现strrchr(查找该字符串最后一次出现的位置)
  4. 用CSS Filter 可以实现相同的效果
  5. linux下动态链接问题(so文件的编写与调用)
  6. exists的用法 python_10 个 Python 开发技巧
  7. 【Java程序设计】类与对象的基本概念(下)
  8. Python之路(一)初识Python
  9. python2.7没有pip_python2.7无法使用pip怎么办
  10. java 包含字符串 个数_java查找字符串中的包含子字符串的个数实现代码
  11. Java图书管理系统(控制台程序)
  12. 如何设计会员体系中心
  13. llinux默认ip修改方法
  14. python对gif图压缩
  15. 百度关键词排名查询源码_推荐4个Google关键词排名查询工具
  16. html页面中文本框的光标控制
  17. 端口输出报错**Error** test5.ASM(60) Constant too large
  18. Linux云计算学习笔记day56
  19. 掌握Android图像显示原理(上)
  20. 贝塞尔曲线 弯曲动画ios_用贝塞尔曲线弯曲

热门文章

  1. 转载:关于Vivado综合选项——Out of context per IP和Gobal
  2. Spark程序使用Scala进行单元测试
  3. SQLyog数据库列表(对象浏览器)字体大小设置方法,不是普通字体大小设置
  4. java for class_Class forClass
  5. 洋哥线下见面会,小姐姐都问了什么?
  6. android 自定义 snackbar,Android Study Material Design 五 之:自定义Toast以及玩转SnackBar...
  7. Kubernetes - 一键安装Kubernetes集群
  8. 【023】Springboot+vue+mysql员工考勤管理系统(多角色登录、请假、打卡)(含源码、数据库、运行教程)
  9. delphi 讲的比较详细的多线程(推荐)
  10. 如何用手机给视频变速