专栏首页日常学python如何爬取asp动态网页?搞定可恶的动态参数,这一文告诉你!

如何爬取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),作者:sergiojune

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 用Python实现模拟登录正方教务系统抢课

    最近学校开始选课,但是如果选课时间与自己的事情冲突,这时候就可以使用Python脚本自助抢课,抢课的第一步即是模拟登录,需要模拟登录后保存登录信息然后再进行操作...

    sergiojune
  • 这次给大家带来复杂点的ajax请求该如何破?

    公众号由于私人原因差不多一个月没有更新了,首先还是得感谢没有你们,没有取关我,很开心。其次我会在以下的两个月时间为大家输出高质量的文章,让你们能学到东西的同时,...

    sergiojune
  • 一篇文章踩遍Python中的坑

    这个问题是变量作用域问题,在gen=(x for _ in xrange(10))中gen是一个generator,在generator中变量有自己的一套作用域...

    sergiojune
  • 前端学习(1)~html标签讲解(一)

    html全称为HyperText Markup Language,译为超文本标记语言,不是一种编程语言,是一种描述性的标记语言,用于描述超文本中内容的显示方式。

    Vincent-yuan
  • Python 技术篇-PyQt5动画功能演示,组件移动、尺寸改变动画演示

    我要改变listView组件的大小,在一定时间内让组件从设定的起始大小改变为设定的终止大小。 QRect(x, y, a, b)前两个是位置,后两个是宽和高。

    小蓝枣
  • 看“他”怎么折腾(一)

    OpenCV中Mat类是一个是一个用来存放视图像数据的结构,其中的数据可能是连续存储的,也可能是不连续存储的。

    视界音你而不同
  • css实现左右两个div等高

    现在有两个div,但是两个div里面内容多少不确定,可能左边多,可能右边多,css要如何设置可以保证左右两边的div等高呢?

    Daotin
  • 暗通道去雾的好文合集

    zy010101
  • 强行科普|买不起的专业级VR相机,看看还不行吗?

    VRPinea
  • (19)打鸡儿教你Vue.js

    模板语法 计算属性 Class,Style绑定 条件渲染 列表渲染 事件处理 表单输入绑定

    达达前端

扫码关注云+社区

领取腾讯云代金券