如何爬取asp动态网页?搞定可恶的动态参数,这一文告诉你!

这个asp网站是我的学校的电费查询系统,需要学校的内网才能查询,所以这文说下思路和我遇到的一些坑。我搞这个网站主要是为了方便查电费而已,其实也方便不了多少。而且这个asp网站还不是很容易爬,因为里面有两个可变的参数,会根据页面来变化。好了,先看看页面

这个网站需要先登陆进自己的宿舍才能进去,还有很烂的验证码,不过我实现到验证码写入的时候发现这个验证码是可以随便填的,这个就感觉有点垃圾。

这个登陆页面有很多坑,下面说下

1.

上面右边所指的就是两个动态变化的参数,怎么来的呢?是根据上一个页面来的,每个页面都会带有这两个参数,所以我们需要每次访问一次都需要匹配下这两个值就行动态更换,如果不跟换的话,会得不到数据,还会出现下面这个错误。

'236|error|500|回发或回调参数无效。在配置中使用 <pages enableEventValidation="true"/> 或在页面中使用 <%@ Page EnableEventValidation="true" %> 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。|'

这个就说明你没有更换好上面所说的两个参数

注意:第一次访问这个网站是不会有宿舍楼层宿舍号这些数据的,需要进行匹配上面的两个可变参数再进行post才会有数据。

2.

在你选好你的宿舍楼层号之后表单数据就会出现变化

可以看到表单的参数顺序和上面的不一样了,所以在选好宿舍楼层之后我们需要把变单顺序改变后再把参数post出去,要不还会出现上面那个坑,就是回调参数无效

第一个箭头所指的参数也需要改变,不过第二个参数是txtname2,也就是每层楼的默认宿舍值,这个固定也没事,不会出错,时间的话还是需要根据自己访问时间来进行变化的,要不也会出现错误,还是同样的错误,也就是下面的这个错误,可想而知asp网站对这些参数是有很挑剔的要求。

236|error|500|回发或回调参数无效。在配置中使用 <pages enableEventValidation="true"/> 或在页面中使用 <%@ Page EnableEventValidation="true" %> 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。|

3.

这个电费查询按钮,不是ajax,会有新的请求,而且是对同一个网址的不同请求方式,第一次请求时get请求,用于获取asp网页的那两个动态参数,第二次是将动态参数就行post发送出去,这样就会有数据了,如果你是第一次就post的话,会没有数据,网页还是会报错误,同样还是那个错误哈。下面是表单数据

self.data = {
            '__EVENTTARGET': 'RegionPanel2$Region1$Toolbar1$ContentPanel1$btnSelect',
            '__EVENTARGUMENT': '',
            '__VIEWSTATE': self.data['__VIEWSTATE'],
            '__EVENTVALIDATION': self.data['__EVENTVALIDATION'],
            'hidJZ': 'jz'+name,
            'RegionPanel2$Region1$Toolbar1$ContentPanel1$TextBox1': (datetime.now()-timedelta(days=30)).strftime('%Y-%m-%d'),
            'RegionPanel2$Region1$Toolbar1$ContentPanel1$TextBox2': datetime.now().strftime('%Y-%m-%d'),
            'RegionPanel2$Region1$Toolbar1$ContentPanel1$txtDBBH': '',
            'RegionPanel2$Region1$Toolbar1$ContentPanel1$ddlCZFS': '----全部----',
            'RegionPanel2$Region1$toolbarButtom$pagesize': '1',
            '__box_page_state_changed': 'false',
            '__2_collapsed': 'false',
            '__6_selectedRows': '',
            '__box_disabled_control_before_postbac': '__10',
            '__box_ajax_mark': 'true'
        }

坑说完了,说说部分代码的作用吧

def __get_value(self, html):  # 获取表单的两个参数__VIEWSTATE和__EVENTVALIDATION
        try:
            soup = BeautifulSoup(html, 'lxml')
            value = soup.select('input[type="hidden"]')
            values = [v for v in value if '/w' in str(v)]
            state = values[0]['value']
            action = values[1]['value']
            self.data['__VIEWSTATE'] = state
            self.data['__EVENTVALIDATION'] = action
        except IndexError as e:  # 证明这个不是首页,需要另外的规则
            match = re.search('__VIEWSTATE\|(.*?)\|.*?__EVENTVALIDATION\|(.*?)\|', html)
            self.data['__VIEWSTATE'] = match.group(1)
            self.data['__EVENTVALIDATION'] = match.group(2)
        except Exception as e:
            print('get_value', e)

这个就是获取两个动态参数的方法,每次根据html元素来获取

def __get_name(self, jz, html=None):  # 输入宿舍号
        if html:
            # 表单顺序需要改变
            self.data = {
                'ScriptManager1': 'UpdatePanel1|txtjz2',
                'hidtime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'Radio1': '1',
                'txtjz2': jz,
                'txtname2': '001001001001001',  # 这个初始化值可以随意,但不能为空
                'txtpwd2': '',
                'txtyzm2': '',
                '__EVENTTARGET': 'txtjz2',
                '__EVENTARGUMENT': '',
                '__LASTFOCUS': '',
                '__VIEWSTATE': '',
                '__EVENTVALIDATION': '',
                '__ASYNCPOST': 'true'
            }
            self.__get_value(html)  # 换下参数
            html = self.__get_html()
            if html:
                soup = BeautifulSoup(html, 'lxml')
                dormitory_num = soup.select('select[name="txtname2"] option')
                dormitory_num = [(p.text, p['value']) for p in dormitory_num]
                for index, p in enumerate(dormitory_num):
                    print(index, '宿舍号:', p[0])
                self.__get_value(html)
        while True:
            num = input('请输入你的宿舍,输入左边的编号即可')
            num = re.match('\d+', num)
            if num and int(num.group()) < len(dormitory_num):
                num = int(num.group())
                break
            print('请输入正确的宿舍编号')
        return dormitory_num[num][1]

这个是获取宿舍号,表单顺序需要改变

def __get_chapter(self):
        # 获取验证码
        url = 'http://172.18.2.42:8000/ValidateCode.aspx'
        response = requests.get(url, headers=self.headers)
        with open('code.jpg', 'wb') as f:
            f.write(response.content)
        image = Image.open('code.jpg')
        image.show()
        code = input('请输入验证码')
        return code

这个是获取验证码的方法,获取验证码是很简单的,就是找到请求的url进行请求就可以了。至于识别,我这里是手动输入,你也可以选择接入打码平台或者用深度学习模型来识别。

其他的就不多说了。

需要源码的可以在我的GitHub上找:https://github.com/SergioJune/gongzhonghao_code/blob/master/python_play/query.py

推荐文章:

我爬取了37000条球迷评论,知道了这场比赛的重要信息爬取《The Hitchhiker’s Guide to Python!》python进阶书并制成pdf

原文发布于微信公众号 - 日常学python(daily_learn)

原文发表时间:2018-06-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术小讲堂

Singal Page App:使用Knockout和RequireJS创建高度模块化的单页应用引擎背景知识文档结构服务端API准备Require配置与系统配置模块中的工作模块间的工作烂图赏鉴代码送上

开篇扯淡 距离上一篇文章已经有好几个月,也不是没有时间记录点东西,主要是换了新的工作,在一家外资工作,目前的工作内容大多都是前端开发,新接触的东西因为时间原因,...

3046
来自专栏小樱的经验随笔

CTF---Web入门第五题 貌似有点难

貌似有点难分值:20 来源: 西普学院 难度:难 参与人数:7249人 Get Flag:2519人 答题人数:2690人 解题通过率:94% 不多说,去看题目...

3086
来自专栏从零开始学自动化测试

python接口自动化21-规范的API接口文档示例

前言 接口文档到底长啥样?做接口测试最大的障碍在于没有接口文档,很多公司不注重接口文档的编写,导致测试小伙伴没见过接口文档。 运气好一点的测试小伙伴可能厚着脸皮...

1.3K8
来自专栏菩提树下的杨过

thrift中的超时(timeout)坑

最近在项目中采用thrift作为后台服务rpc框架,总体用下来性能还不错,跨语言特性使用起来也还行,但是也遇到了一些坑,其中之一就是超时问题(timeout),...

6289
来自专栏程序员的SOD蜜

单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测试

最近公司的项目准备优化一下系统的性能,希望在数据库方面看有没有提升的空间,目前压力测试发现数据库服务器压力还不够大,Web服务器压力也不是很大的情况下,前台页面...

24410
来自专栏比原链

剥开比原看代码17:比原是如何显示交易的详细信息的?

Gitee地址:https://gitee.com/BytomBlockchain/bytom

821
来自专栏NetCore

一个让人遗忘的角落—Exception(三)

最近有点事,把这个系列给落下了,给大家道个歉,这里还要感谢我的老婆,谢谢她一直对我的支持:) 系列回顾: 1.一个被人遗忘的角落—Exception(一) 2...

2126
来自专栏tkokof 的技术,小趣及杂念

“疑难杂症”二记

  今日开发遇到些许问题,大抵都很琐碎,但却又颇为扰人,在此随便一记,提醒自己的同时,也可以方便方便遇到类似情况的朋友~

672
来自专栏FreeBuf

Struts2 s2-032远程代码执行分析

1. 介绍 Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。其全新的Str...

1956
来自专栏ml

acm系统开发笔记

时间:     2016/2/29   遇到的困难:  数据库配置的mysql和java(Date)不一致,出现下面错误 1 Date date = new D...

4028

扫码关注云+社区

领取腾讯云代金券