菜鸡学 js 逆向感悟(针对小白,也请各位大佬指点一下)

菜鸡入门 js 逆向一点小经验

本火箭最近因为要做个项目(不是我自己做,是让大佬带),大佬让我先多看一些论文。
于是,小火箭我就去了学校购买的 某方数据知识服务平台 搜索论文,因为每次都点下载太麻烦,即使有批量下载我也觉得好麻烦。
(我这是怎么了,都懒成这个样子了,😔,又与大佬们拉开差距了)


于是我就又想写个爬虫,输入关键词 ,然后自动下载指定目录,到时候只要输入关键词,再给出 保存路径 ,就无忧咯o( ̄▽ ̄)ブ
说冲就冲


开冲


第一步,还是轻车熟路地打开 F12,点击网络
注:

  • 如果需要先登录校园网的话,一定要先登录哦

以关键词 无人驾驶大数据 为例,输入关键词后,点击回车…


好像有哪里不太对,我的主题是 js 逆向,emmm,换碟!


很容易可以找到其中一个 下载按钮 所对应的元素,呐,就在这里
在这里插入图片描述(如果不会的话,你可真得好好补补课了 U•ェ•*U, 如下图所示)
在这里插入图片描述
右键 点击 下载按钮(想要查看的任何元素都可以这样),然后点击 检查元素,就 o98k 啦~


可以看到,这个按钮所对应的链接是通过 js(emmm,用什么词好呢?加载?emmm,就是让一个 js 文件对按钮加一个事件,然后当我们点击了这个按钮,可以跳转到想要的页面
要按往常,我还真的一点头绪也没有,因为那时候的我 不会 js ,但现在,经过简(艰)单(苦)自学后,我大致了解了 js 逆向的过程。

js 逆向过程

  1. 找到 这个事件所对应的 js 语句
  2. 分析
  3. 去除不必要的变量
  4. 然后 模拟 得到应该得到的值
  5. 最后 执行 一下就万事大吉了

(屏幕前的你似乎还是有点懵,那正常,因为我也还是有点懵,つ﹏⊂)
啥也不说了,直接实践,世间唯一真理,实践出真知!
奥里给,造就完了!!!


(其实以前我也大概知道了 js 逆向的过程,但我很愚蠢的一直找不到别人所说的 全局搜索 ,つ﹏⊂,不过昨天我终于找到了,(ಥ _ ಥ),我用的火狐,而全局搜索就在如下图所示的地方)

在这里插入图片描述
你们可以尝试一下,点一下就会发现新大陆!!!!!
这个全局搜索是真的好用,我感觉我下边都不用讲了(つ﹏⊂)


说实话,这个逆向比较简单一点,因为这个事件执行的 js 代码和传递的参数都在标签中有,如下图所示

在这里插入图片描述
看起来是不是有点熟悉,因为这就是在下载按钮那个标签里有
🤦‍(说实话,我也不知道他为什么要放的这么明显,虽然我们也可以通过点击 event 按钮 也能查看到。
但这样放在标签属性中的话

  • 直接 xpath 就得到了
  • 再 re 一下就得到了传递的参数值了
  • 为什么我这么说呢,因为我就用的这种方法哈哈,U•ェ•*U


我们可以看到它使用的是函数 downLoadPermissions ,通过全局搜索,我们能够找到这个函数所在位置

在这里插入图片描述
下面就换碟福尔摩斯 (开始分析)
在这个函数的下面还有个函数名差不多的函数,他们的作用差不多,可以看出来
这两个函数传递的参数名为 page_cnt,language,resourceType,source,id,title,isoa,isfirst
函数的功能是

  • 首先用变量 operationPermiss 链接到相应的标签
  • 判断这个变量的值是否为 false ,如果是,就调用函数 download
  • 否则,就调用函数 getloginurl ,显而易见,这个是要跳转到登陆链接

我们肯定是要选择 download 呀!
再次使用全局搜索,搜索函数 download ,很(不太)容易就找到了这个函数所在的位置

在这里插入图片描述

看看左边密密麻麻的搜索结果,我可是费了好大的劲才找到真正的函数定义
/(ㄒoㄒ)/~~
看这个函数的功能,应该是

  • 先判断 isfirst 的值,如果未定义(应该是这个意思吧),就置为空
  • 然后不看 title,直接看最后一行
  • 我不太清楚 windows.open 这个函数的功能,但我看到了括号里是在拼接链接地址,(和我平常拼接网址好像啊哈哈),所以我就找到了这个 下载按钮 所对应的网址
  • 注:
    • 因为传递的函数值不一样,所以下载地址都不一样(我猜你们肯定知道😁)
      那现在我们就可以愉快的拼接文件下载的网址咯!!!

代码实现

我的代码如下

    def get_download_list(self, index_content):
        '''
        本函数用来得到文章下载的 url
        :return download_url_list:
        '''
        # 首先得到包含 下载按钮 的论文所对应的 div 标签
        c_list = index_content.xpath('//div[@class="ResultList "]//span[text()="下载"]/../../a/@onclick')
        # 遍历列表
        for i, c in enumerate(c_list):
            try:
            	# 首先得到函数调用的语句,因为有的会还含有其他语句,影响提取参数值
                c = re.findall('downLoadPermissions\((.*?)\)', c)[0]
            # 这个错误是我没有想到的,因为有的调用的函数是 downLoad,使用上边的正则表达式会报错,超出列表范围
            except IndexError:
                c = re.findall('downLoad\((.*?)\)', c)[0]
            # 用逗号 , 分隔各个参数值
            list1 = c.split(',')
            info_list = []
            # 得到的是参数值,带着引号,所以提取中间的值,我没有尝试 eval 函数,直接用的 re,你可以尝试一下,然后告诉我可行性,嘻嘻,我就是白嫖怪!
            for info in list1:
                try:
                    info = re.findall("'(.*)'", info)[0]
                # 这个报错我也是没有想到的,因为有的文章来源不仅仅是 'WF',如果有其他来源的话,这个参数值就是如 '[WF,]'
                # 这时候会导致使用逗号分隔会得到两个空字符串,本来得到的列表有 7 个参数值,但列表中有 8 个元素,所以需要去除一个,否则会影响传递值
                # 在尝试以后,我发现 source 字段直接设置为 'WF' 同样可以得到结果,所以传递值时 source 字段直接使用的 'WF'
                except IndexError:
                    info = ''
                info_list.append(info)
            if len(info_list) == 8:
                del info_list[3]
            data = {
                'page_cnt': info_list[0],
                'language': info_list[1],
                'resourceType': info_list[2],
                'source': 'WF',
                'resourceId': info_list[4],
                'resourceTitle': info_list[5],
                'isoa': info_list[6],
                'type': info_list[2],
                'first': ''
            }
            # 拼接网址
            index_url = major_url2 + up.urlencode(data)
            self.download_url_list.append(index_url)

我将提取信息的过程写成了一个类,最终代码如下

# -*- coding=utf-8 -*-

import requests
import urllib.parse as up
import lxml.etree as le
import re

headers = {【这里就加上你们自己的 headers 即可】}

major_url = 'http://g.wanfangdata.com.cn'
major_url2 = 'http://g.wanfangdata.com.cn/search/downLoad.do?'

class wanfang_spider_tools():

    def __init__(self, kw):
        self.kw = kw
        self.index_content = []
        self.title_list = []
        self.download_url_list = []
        self.title_list = []
        self.result_dict = {}

    def search_kw_result(self, page):
        '''
        得到关键词的搜索结果
        :return index_content <xml>:
        '''
        data = {
            'beetlansyId': 'aysnsearch',
            'searchType': 'all',
            'pageSize': '20',
            'page': str(page),
            'searchWord': self.kw,
            'order': 'correlation',
            'showType': 'detail',
            'isCheck': 'check',
            'isHit': '',
            'isHitUnit': '',
            'firstAuthor': 'false',
            'corePerio': 'false',
            'alreadyBuyResource': 'true',
            'rangeParame': '',
            'navSearchType': 'all'
        }
        index_url = major_url + '/search/searchList.do?' + up.urlencode(data)
        self.index_content.append(le.HTML(requests.get(url=index_url, headers=headers).text))

    def get_content_list(self, index_content):
        '''
        查看搜索结果总页数
        :return:
        '''
        num_list = [int(num) for num in index_content.xpath('//div[@id="laypage_0"]/a[text()!="下一页"]/text()')]
        try:
            max_num = max(num_list)
            for page in range(2, max_num):
                self.search_kw_result(page)
        except:
            pass

    def get_title_list(self, index_content):
        '''
        本函数用来得到论文题目和类型
        :return title_list <list>:
        '''
        xpath_list = index_content.xpath('//div[@class="ResultList "]//span[text()="下载"]/../../../../../../..//div[@class="title"]')
        for title_x in xpath_list:
            char = ''
            title_l = title_x.xpath('./a[@target="_blank"]//text()')
            if title_l == []:
                continue
            content_type = title_x.xpath('./../../div[@class="ResultCheck"]/input/@exporttype')[0]
            for title_c in title_l:
                char += title_c
            char = re.sub('[\r]*[\t]*[\n]*', '', char)
            if char != '':
                self.result_dict[char] = {}
                self.result_dict[char]['type'] = content_type


    def get_download_list(self, index_content):
        '''
        本函数用来得到文章下载的 url
        :return download_url_list:
        '''
        c_list = index_content.xpath('//div[@class="ResultList "]//span[text()="下载"]/../../a/@onclick')
        for i, c in enumerate(c_list):
            try:
                c = re.findall('downLoadPermissions\((.*?)\)', c)[0]
            except IndexError:
                c = re.findall('downLoad\((.*?)\)', c)[0]
            list1 = c.split(',')
            info_list = []
            for info in list1:
                try:
                    info = re.findall("'(.*)'", info)[0]
                except IndexError:
                    info = ''
                info_list.append(info)
            if len(info_list) == 8:
                del info_list[3]
            data = {
                'page_cnt': info_list[0],
                'language': info_list[1],
                'resourceType': info_list[2],
                'source': 'WF',
                'resourceId': info_list[4],
                'resourceTitle': info_list[5],
                'isoa': info_list[6],
                'type': info_list[2],
                'first': ''
            }
            index_url = major_url2 + up.urlencode(data)
            self.download_url_list.append(index_url)

    def return_info(self):
        '''
        整合信息
        :return info_dict <dict>:
        '''
        self.search_kw_result(1)
        self.get_content_list(self.index_content[0])
        for index_content in self.index_content:
            self.get_title_list(index_content)
            self.get_download_list(index_content)
            for i, title in enumerate(self.result_dict.keys()):
                self.result_dict[title]['url'] = self.download_url_list[i]
        return self.result_dict

有了下载的网址,后续的下载就靠你们自己了
我是使用的 webdriver 打开浏览器后自动下载,你们可以选择其他的方法,方法不唯一


其实再看看,好像我这又不太像 js 逆向,准确来说,我现在还没有对 js 逆向有个深刻的理解,烦请各位大佬指点




以上就是我要分享的内容,因为学识尚浅,会有不足,还请各位大佬指正。
有什么问题也可在评论区留言。
在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值