zoukankan      html  css  js  c++  java
  • python爬虫 -- 浏览器的抓包编码可以绝对信任吗

    前言

     

    本次也是记录一个偶然发现的小问题,有关js逆向和app逆向的系列文章,放一放,有空再系统的整理成文发布了。

     

    这个问题就很骚了,废话不多说,直接情景再现

     

    目标网站:
    aHR0cHM6Ly93d3cubW5kLmdvdi50dy9QdWJsaXNoTVBCb29rLmFzcHg/JnRpdGxlPSVFOCVCQiU4RCVFNCVCQSU4QiVFNSU4OCU4QSVFNyU4OSVBOSZTZWxlY3RTdHlsZT0lRTglQkIlOEQlRTQlQkElOEIlRTYlOUMlOUYlRTUlODglOEE=

     

     

    复现问题

    我们的目标就是要下载这个网站的资源文件

     

    首先这个是一级页面,以下圈出的就是二级页面

     

     

     

     

    进入二级页面,我下面圈出的地方就是三级页面地址

     

     

     

     

    点击三级页面网址,三级页面其实就是在二级底部渲染出来的,下面圈出的什么什么下载的就是我们要的数据了

     

     

     

    是不是看着很简单

     

    好的,我们直接看他的请求接口:

     

    前面两个都是get请求,第三个是post请求,所以我们着重点就在第三个,先看链接:

     

     

    这里看下,有个值没有正常显示:

     

     

     

    没事,这个不打紧了,再看请求体:

     

     

    __EVENTTARGET: ctl00$ContentPlaceHolder1$RtList$ctl01$LkBt
    __EVENTARGUMENT: 
    __VIEWSTATE: i2jc3XTd0XMvdzkJDXcki1wScYnJdfCuOoUlDvgf4ql6TMq8g84WYO1rZ6MyTNjqdoSpUkPNx8VG53Qo2d8+bDEpAlN5bx9At8ApkxRBaAVEthimHSC2wu1pZWg37peXtm+oMKecNXW3cFST4OEGp5rmb3IIcJ4iRnn6v2B6W5VGo3SsBIh5LOA4nAtX0ut87EN
    __VIEWSTATEGENERATOR: 0361E37B
    __EVENTVALIDATION: 7pEeFbpkgYsGh94FYMVpb/V2HHBATMf46U6yW9OlMx9O55RRM1pySTFubl19vw1ec9F9mBMNS+UZ46T/osr9+s+tOZv4G8ecnT2UsKcl7Vf0vill/V2uqzoLHOiqzkTQIkiUFlK1lwBv89wcIa0zUBdlUZ5/t+YSEEg2GYP7hOL7RpaJM6LOlwKIFrRQY/QiRQ3tL1KPBQ9vEIw3+SUxC905LH8wKjFiCsJpskpThyAR4aySYRF2yZbzNFHWMWiAgZQUd/9O3MXvK6/RZa42d9I8t7xJwAw==
    TbSearch2: 
    TbSearch: 
    ctl00$ContentPlaceHolder1$txtSearch: 

     

     

    然后,看到这些值,搞过国内某某网站都懂,就是c#的web框架生成出来的值,然后这些值都是在网站源码里面能找到的,其他也不存在什么加密参数,所以,很简单啊,直接拿着代码一顿操作就完了

     

     

     

     

     

    import requests
    from lxml import etree
    
    url = 'https://www.xxxxxxxxx/PublishMPBook.aspx?&title=xxxx%A9&SelectStyle=xxxxx6%xxxxA'
    
    session = requests.session()
    
    headers = {
        
        'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
        'sec-ch-ua-mobile': '?0',
        'Sec-Fetch-Dest': 'document',
        'Sec-Fetch-Mode': 'navigate',
        'Sec-Fetch-Site': 'same-origin',
        'Sec-Fetch-User': '?1',
        'Upgrade-Insecure-Requests': '1',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
    }
    
    req = session.get(url, headers=headers)
    res = req.content.decode('utf-8')
    html = etree.HTML(res)
    req.close()
    data = html.xpath('//div[@class="thisPages"]/table/tr[position()>1]')
    for item in data:
        curr = dict()
        link = item.xpath('./td[1]/a/@href')
        link = ''.join(link) if link else ''
        kind = item.xpath('./td[1]/a/@title')
        kind = ''.join(kind) if kind else ''
        pub_date = item.xpath('./td[@headers="LastUpdate"]/text()')
        curr['pub_date'] = pub_date
        pub_date = ''.join(pub_date) if pub_date else ''
        name = item.xpath('./td[@headers="DepartmentName"]/text()')
        name = ''.join(name) if name else ''
        curr['name'] = name
        link = 'https://www.mnd.gov.tw/' + link
        sec_req = session.get(link, headers=headers)
        sec_res = sec_req.content.decode('utf-8')
        sec_req.close()
        sec_html = etree.HTML(sec_res)
        sec_data = sec_html.xpath('//table[@class="table-bordered"]/tr[position()>1]')
        __VIEWSTATE = sec_html.xpath('//input[@id="__VIEWSTATE"]/@value')
        __VIEWSTATE = ''.join(__VIEWSTATE) if __VIEWSTATE else ''
        __VIEWSTATEGENERATOR = sec_html.xpath('//input[@id="__VIEWSTATEGENERATOR"]/@value')
        __VIEWSTATEGENERATOR = ''.join(__VIEWSTATEGENERATOR) if __VIEWSTATEGENERATOR else ''
        __EVENTVALIDATION = sec_html.xpath('//input[@id="__EVENTVALIDATION"]/@value')
        __EVENTVALIDATION = ''.join(__EVENTVALIDATION) if __EVENTVALIDATION else ''
        # print(12312323,__EVENTVALIDATION,__VIEWSTATEGENERATOR,__VIEWSTATE)
        # print(123132123,sec_data)
        for sec_item in sec_data:
            date = sec_item.xpath('./td[@headers="dates"]/text()')
            date = ''.join(date) if date else ''
            curr['date'] = date
            __EVENTTARGET = sec_item.xpath('./td[@headers="MPTable"]/a/@href')
            __EVENTTARGET = ''.join(__EVENTTARGET) if __EVENTTARGET else ''
            __EVENTTARGET = __EVENTTARGET.replace("javascript:__doPostBack('", '').replace("','')", '')
            thr_link = sec_item.xpath('//form[@name="aspnetForm"]/@action')
            thr_link = ''.join(thr_link) if thr_link else ''
            if thr_link:
                thr_link = thr_link.replace('./', '')
                thr_link = 'https://www.xxxxxxx/' + thr_link
                formdata = {
                    '__EVENTTARGET': __EVENTTARGET,
                    '__EVENTARGUMENT': '',
                    '__VIEWSTATE': __VIEWSTATE,
                    '__VIEWSTATEGENERATOR': __VIEWSTATEGENERATOR,
                    '__EVENTVALIDATION': __EVENTVALIDATION,
                    'TbSearch2': '',
                    'TbSearch': '',
                    'ctl00$ContentPlaceHolder1$txtSearch': '',
                }
                new_headers = headers.copy()
                new_headers.update({
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'
                })
                thr_req = session.post(thr_link, headers=new_headers, data=formdata)
                thr_res = thr_req.content.decode('utf-8')
                thr_req.close()
                thr_html = etree.HTML(thr_res)
                thr_data = thr_html.xpath('//td[@id="Subject"]/../../tr[position()>1]')
                for thr_item in thr_data:
                    file_name = thr_item.xpath('./td[@headers="Subject"]/text()')
                    file_name = ''.join(file_name) if file_name else ''
                    curr['file_name'] = file_name
                    author = thr_item.xpath('./td[@headers="Publisher"]/text()')
                    author = ''.join(author) if author else ''
                    curr['author'] = author
                    file_link = thr_item.xpath('./td[@headers="Subject"]/input/@tile')
                    file_link = ''.join(file_link) if file_link else ''
                    curr['file_link'] = file_link
                    date_year_month = ' '
                    file_href = f'https://www.xxxxx/NewUpload/{date_year_month}/{file_link}'
                    curr['file_href'] = file_href
                    print(123123123213, curr) # 这里就是资源地址了,直接请求存储就行了

     

     

    反正都不难,这对于很多朋友来说,这????are you kidding  me?这么简单的东西值得你大费周章的解析?

     

    嘿嘿嘿,我要不是遇到这个坑,我还真的觉得不至于

     

    先不细说,调试运行看结果:

     

     

     

     

    看着状态码是200,觉得稳得一批对吧,接着看xpath解析部分:

     

     

     

     

    傻眼了吧,为什么会是空,按正常人逻辑,那多半是dom节点没取对是吧,好,看下返回的源码,一看就出问题了,网站平台的结果如下:

     

     

     

     

    在结果里搜,问题大了,根本就没有啊

     

     

     

     

    也就是,第三次请求本身就出问题了,根本没有返回正常结果,很奇怪了。

     

    那我第一个想到的就是,估计那几个请求参数出问题了,排查了几个小时,就是没问题啊,我后面用postman单独测试最后一次请求:

     

     

     

     

    就是有啊,我单独的把第三级的拿出来请求:

     

     

    它就是没有正常的获取数据,很骚啊,而且不是一点半点的骚。

     

     

    最后,我想到一个前端的概念,既然它是submit,看下源码有没有什么猫腻:

     

     

    发现确实没有啊,url也就是它这里给的地址,也不存在什么csrf-token之类的,这是为啥啊,一时之间把我整不会了,貌似搞了几年的爬虫跟没搞过一样,这么个问题愣是没整出来,也不涉及js混淆,也不涉及接口加密,所有字段都摆在那,都能拿到,但是就是请求失败,这说实话多多少少有点伤自尊了

     

    找到关键点

    那如果真没有解决的话,我也就不会发这篇博客了,跟着分析了一波,既然是所谓的submit,好,那action其实不指定的话就是源地址,而源地址就是第二级链接的,我把第二级和第三级链接复制出来对比:

     

     

     

     

    发现,也就title的值不一样,其他都是一样的,而刚才我特别做了截图,第三级的时候,url的params在浏览器里没有被正常解析:

     

     

     

     

    突发奇想,我就用第二级的链接请求呢?有朋友估计有疑惑了,不对啊,你怎么能用第二级的链接作为第三级访问呢?你拿到这个网站分析了就知道了,从二级到三级的时候,其实网站上部分是没有任何变化,变化的是底部突然就多了资源下载列表:

     

    回顾一下,二级页面:

     

     三级页面:

     

     

     

    如果您稍微懂一点前端知识的话就大概知道我在说什么了,不太理解的可以查下form表单标签的原理就懂了,好的,继续,这次直接用二级链接请求看看:

     

     

    正常拿到结果,果然就是这个问题了

    把最后的代码改成如下:

    import requests
    from lxml import etree
    
    url = 'https://wxxxxxxStyle=xxxxx%E8%BB%8D%E4%BA%8B%E6%9C%9F%E5%88%8A'
    
    session = requests.session()
    
    headers = {
        'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
        'sec-ch-ua-mobile': '?0',
        'Sec-Fetch-Dest': 'document',
        'Sec-Fetch-Mode': 'navigate',
        'Sec-Fetch-Site': 'same-origin',
        'Sec-Fetch-User': '?1',
        'Upgrade-Insecure-Requests': '1',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
    }
    
    req = session.get(url, headers=headers)
    res = req.content.decode('utf-8')
    html = etree.HTML(res)
    req.close()
    data = html.xpath('//div[@class="thisPages"]/table/tr[position()>1]')
    for item in data:
        curr = dict()
        link = item.xpath('./td[1]/a/@href')
        link = ''.join(link) if link else ''
        kind = item.xpath('./td[1]/a/@title')
        kind = ''.join(kind) if kind else ''
        pub_date = item.xpath('./td[@headers="LastUpdate"]/text()')
        curr['pub_date'] = pub_date
        pub_date = ''.join(pub_date) if pub_date else ''
        name = item.xpath('./td[@headers="DepartmentName"]/text()')
        name = ''.join(name) if name else ''
        curr['name'] = name
        link = 'https://wxxxxxxv.tw/' + link
        sec_req = session.get(link, headers=headers)
        sec_res = sec_req.content.decode('utf-8')
        sec_req.close()
        sec_html = etree.HTML(sec_res)
        sec_data = sec_html.xpath('//table[@class="table-bordered"]/tr[position()>1]')
        __VIEWSTATE = sec_html.xpath('//input[@id="__VIEWSTATE"]/@value')
        __VIEWSTATE = ''.join(__VIEWSTATE) if __VIEWSTATE else ''
        __VIEWSTATEGENERATOR = sec_html.xpath('//input[@id="__VIEWSTATEGENERATOR"]/@value')
        __VIEWSTATEGENERATOR = ''.join(__VIEWSTATEGENERATOR) if __VIEWSTATEGENERATOR else ''
        __EVENTVALIDATION = sec_html.xpath('//input[@id="__EVENTVALIDATION"]/@value')
        __EVENTVALIDATION = ''.join(__EVENTVALIDATION) if __EVENTVALIDATION else ''
        # print(12312323,__EVENTVALIDATION,__VIEWSTATEGENERATOR,__VIEWSTATE)
        # print(123132123,sec_data)
        for sec_item in sec_data:
            date = sec_item.xpath('./td[@headers="dates"]/text()')
            date = ''.join(date) if date else ''
            curr['date'] = date
            __EVENTTARGET = sec_item.xpath('./td[@headers="MPTable"]/a/@href')
            __EVENTTARGET = ''.join(__EVENTTARGET) if __EVENTTARGET else ''
            __EVENTTARGET = __EVENTTARGET.replace("javascript:__doPostBack('", '').replace("','')", '')
            thr_link = sec_item.xpath('//form[@name="aspnetForm"]/@action')
            thr_link = ''.join(thr_link) if thr_link else ''
            if thr_link:
                thr_link = thr_link.replace('./', '')
                thr_link = 'https://wxxxxxw/' + thr_link
                formdata = {
                    '__EVENTTARGET': __EVENTTARGET,
                    '__EVENTARGUMENT': '',
                    '__VIEWSTATE': __VIEWSTATE,
                    '__VIEWSTATEGENERATOR': __VIEWSTATEGENERATOR,
                    '__EVENTVALIDATION': __EVENTVALIDATION,
                    'TbSearch2': '',
                    'TbSearch': '',
                    'ctl00$ContentPlaceHolder1$txtSearch': '',
                }
                new_headers = headers.copy()
                new_headers.update({
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'
                })
                # thr_req = session.post(thr_link, headers=new_headers, data=formdata)
                thr_req = session.post(link, headers=new_headers, data=formdata)
                thr_res = thr_req.content.decode('utf-8')
                thr_req.close()
                thr_html = etree.HTML(thr_res)
                thr_data = thr_html.xpath('//td[@id="Subject"]/../../tr[position()>1]')
                for thr_item in thr_data:
                    file_name = thr_item.xpath('./td[@headers="Subject"]/text()')
                    file_name = ''.join(file_name) if file_name else ''
                    curr['file_name'] = file_name
                    author = thr_item.xpath('./td[@headers="Publisher"]/text()')
                    author = ''.join(author) if author else ''
                    curr['author'] = author
                    file_link = thr_item.xpath('./td[@headers="Subject"]/input/@tile')
                    file_link = ''.join(file_link) if file_link else ''
                    curr['file_link'] = file_link
                    date_year_month = ' '
                    file_href = f'https://www.xxxxx/xxxx/{date_year_month}/{file_link}'
                    curr['file_href'] = file_href
                    print(123123123213, curr)

    运行结果肯定是有的,就不费篇幅展示了 

    疑问

    那细心的老哥估计要问了,为啥用postman和谷歌浏览器时,用的那个看到的三级链接就可以,在打码里得用二级链接才行?

     

    卧槽,老哥,你问的这个问题,非常的专业,请看如下:

     

    注意,上图右边的是python2环境下的,有没有发现,这可太对应了,也就【】被替换成了【%】,那果然是这个编码的问题了,右边不难看出,就是unicode编码,而谷歌浏览器能解析的默认是url编码的,所以显示的unable decode,

    而为啥python里不行,我想应该是python你给什么url它就是什么,而postman和谷歌会把url做一定编码处理吧,但是具体我没有去仔细研究了,反正就是这个问题了,over

    对了,补一个python3里的unicode编码:

     结语

     所以啊,浏览器的抓包还是不能绝对相信啊,这可是个大坑啊,搞了几个小时搞出来的,心累。。。。

  • 相关阅读:
    寒假第七天
    寒假第六天
    寒假第五天
    寒假第四天
    leetcode 105 从前序与中序遍历序列构造二叉树
    leetcode 268 丢失的数字
    leetcode 141 环形链表
    判断顶点是否在三角形内部
    java 基本数据类型
    leetcode 20 有效的括号
  • 原文地址:https://www.cnblogs.com/Eeyhan/p/15233841.html
Copyright © 2011-2022 走看看