前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何爬取asp动态网页?搞定可恶的动态参数,这一文告诉你!

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

作者头像
sergiojune
发布2018-07-25 17:03:48
2.1K0
发布2018-07-25 17:03:48
举报
文章被收录于专栏:日常学python

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

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

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

1.

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

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

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

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

2.

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

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

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

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

3.

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

代码语言:javascript
复制
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'
        }

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

代码语言:javascript
复制
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元素来获取

代码语言:javascript
复制
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]

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

代码语言:javascript
复制
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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-06-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 日常学python 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档