爬虫网络请求之JS解密二(大众点评)

- 前言

之前在做大众点评网数据的时候,发现数据在前端显示是用标签来替换。这样爬虫采集到的就是一堆标签加一点内容所混杂的脏数据,同时发现标签中的值也是随时改变的。所以这次也是花了一点时间来整理关于大众点评JS加密的内容,给大家简单讲解一下,以此来学习借鉴如何有效安全的防范爬虫。仅供学习参考,切勿用于商业用途

一、介绍

首先随便打开大众点评网一家店,看到数据都是正常状态如图1-1,然后我们用开发者工具定位到元素上会发现如图1-2所示:


图1-1 正常数据显示
图1-2 获取元素显示

我们可以看到数据都是用<bb>标签给替换了,同时我们还发现如图1-3 、1-4所示:


图1-3 电话号码显示

图1-4 评论

店面基础信息用<bb>标签表示、数字用<cc>表示、评论用<span>标签表示。并且这些被替换的文字也不是固定的,可能过一会被替换的文字被还原,其余未被替换的文字被替换。而且标签值也会随时间发生改变,这样即使每个标签都人工标记,过一段时间数据还是会乱。

二、页面分析

我们随便查看一个被替换了的标签元素,发现它对应了一个文件如图2-1所示:


图2-1 替换的标签所对应的链接

可以看到标签一些基本信息,长度高度还有和它相关的一个链接,打开这个链接,我们可以发现是一个乱序的中文数据表格。如图2-2所示:


图2-2 被替换数据的表格

基本上我们就可以推测出来,数据被隐藏替换的大概原理,通过标签来对应表格文字,其中class的值我们可以理解为被替换数据内容的key,标签类型就好比对应的数据表,这里有三种类别标签就是对应三张不同的数据表,这样我们还需要解决的问题是:
  • (1)不同种类的标签如何对应不同的表;
  • (2)如何通过标签的class值去对应被替换的数据。
    所以到这一步,我们还少一些关键的线索,我们继续看到之前页面,发现图表链接包含在一个css表中 如图2-3所示:


    图2-3 隐藏的css文件

    可以看到有一个css文件,我们在元素中搜索这个表 如图2-4


    图2-4 css文件所在位置

    这样我们便可以从网页中找到指定的文件链接,关于如何根据key值找到对应的参照表。我们打开此链接如图2-5、2-6所示:
    图2-5 key值对照表
图2-6key值对照表

我们可以从图2-5、图2-6看到cc标签、span标签、bb标签每个下面都有一个url。我们打开可以发现就是之前那种格式的对应表,我们稍后再看。我们先看到我们的key值(标签class属性对应的值),后面都接着一个坐标,格式统一都是.(标签class值){background: (横坐标)px(纵坐标) px;这样我们就已经获得key值所对应的坐标,到这里我们基本可以确定,我们找到key值和所对应的坐标就可以根据标签相对应的表,利用坐标就可以找到利用标签所替换的数据。

三、JS解密

接下来,我们就需要知道如何利用获取到的坐标来获取正确被替换的数据。我们首先根据那张表格依次打开链接,查看它们元素会发现有两种格式,一种格式有元素defs标签,另一种没有。如图3-1、图3-2、图3-3所示:


图3-1 含有defs标签格式数据表
图3-2 无defs标签格式数据表
图3-3 含有defs标签格式数据表

总共三张表对应三个不同标签,分两种格式,我分成有defs标签和无defs标签两类。注意,这里我并没有根据标签种类去划分表类别,因为每一次获取到的格式都是随机的。也就是说今天span标签是对应有defs标签数据表,可能明天就对应不含有defs标签类的数据表。数据表格式是随机变化的。

(1)含有defs标签类别数据表解密

以地址中的bb标签为例,看地址所对应的标签值为pzgoz,如图3-4所示:,以及bb标签所对应的svg数据表,如图3-6所示:


图3-4 朝所对应标签key

根据css表找到它的对应坐标x=-294,y=-113.0,如图3-5所示:


图3-5 找到对应坐标

最后根据标签类别找到对应svg数据表链接,打开链接,如图3-6所示:
图3-6 对应的svg数据表

将坐标转为正,先从y坐标看到defs标签d属性上,y=113应该排序在d=M0 90 H600与d=M0 128 H600之间,所以id应该为4,再看textPath标签xlink:href属性为#4的就是我们所要找的行,如果之前有注意看标签width的话,就知道每一个字长为14px,x=294去除以14,等于21,这一行做list的话,list[21]应该就是朝字。代码如下:

hight = html.xpath('//defs//path/@d')
      hight = [i.replace('M0','').replace('H600','').strip() for i in hight]
      hight.append(y)
      hight = sorted(hight, key=lambda i: int(i))
      y = hight.index(y)
      #若纵坐标与标签y相等相等时,取同行的高度
      if y != len(hight) - 1 and hight[y] == hight[y + 1]:
          y = y + 1
      content = html.xpath('//textpath/text()')[y]
      content = ''.join(content).strip()
      x = int(int(x) / 14)
      return content[x]
(2)不含有defs标签类别数据表解密

之前步骤一样,直接跳到找到对应的svg数据表,如图3-7所示:


图3-7 不含有defs标签类别数据表

比如数字3,x=-232.0px y=-140.0px,先全部取正数,y=140 对应在标签text属性y=118和y=163之间,同样排序在第四位,所以取第四行为list,同样232/14=16,list[16]=3;同时也可以数标签text属性x中232排在224-238之间,也就是16-17位之间,但要取16为下标。代码如下:

hight = html.xpath('//text/@y')
        hight.append(y)
        hight = sorted(hight, key=lambda i: int(i))
        y = hight.index(y)
        # 若纵坐标与标签y相等相等时,取同行的高度
        if y != len(hight) - 1 and hight[y] == hight[y + 1]:
            y = y + 1
        content = html.xpath('//text/text()')[y]
        content = ''.join(content).strip()
        x = int(int(x) / 14)
        return content[x]

四、代码实现

这里附上我测试的代码,仅供学习参考,切勿用于商业用途。直接使用前,请带上自己浏览器的请求头参数。

#coding=utf-8
import requests
import lxml.html
import re
from decimal import Decimal
#获取svg表格中被替换的数据
def get_hide_char(x,y,type,url):
    response = requests_middler(url)
    html = lxml.html.fromstring(response.content)
    #网页格式是否有defs元素
    if len(html.xpath('//defs//path/@d'))<1:#如果没有defs标签
        hight = html.xpath('//text/@y')
        hight.append(y)
        hight = sorted(hight, key=lambda i: int(i))
        y = hight.index(y)
        # 若纵坐标与标签y相等相等时,取同行的高度
        if y != len(hight) - 1 and hight[y] == hight[y + 1]:
            y = y + 1
        content = html.xpath('//text/text()')[y]
        content = ''.join(content).strip()
        x = int(int(x) / 14)
        return content[x]
    else:#如果含有defs标签
        hight = html.xpath('//defs//path/@d')
        hight = [i.replace('M0','').replace('H600','').strip() for i in hight]
        hight.append(y)
        hight = sorted(hight, key=lambda i: int(i))
        y = hight.index(y)
        #若hight相等时,取同行的高度
        if y != len(hight) - 1 and hight[y] == hight[y + 1]:
            y = y + 1
        content = html.xpath('//textpath/text()')[y]
        content = ''.join(content).strip()
        x = int(int(x) / 14)
        return content[x]

#请求url统一方式
def requests_middler(url):
    headers={'User-Agent':''}#加入自己的User-Agent
    html = requests.get(url, headers=headers)
    return html
#获取css表中key值对应的坐标,以及标签对应svg表链接
def get_position_xy(html,password,type,url):
    #获取key值对应的坐标
    rule = re.compile(password + '{background:-(.*?).0px -(.*?).0px;')
    result = re.findall(rule, html)[0]
    x = result[0]
    y = result[1]
    #获取标签所对应的svg表格
    rule = re.compile(type + '\[class\^="\w+"\]\{(.*?)}', re.S)
    result = re.findall(rule,html)[0]
    rule = re.compile('url\((.*?)\)')
    href = re.findall(rule, result)
    url = 'http:' + href[0]
    hide_char=get_hide_char(x,y,type,url)
    return hide_char

#解密前数据做好清洗,清洗成标签与文字组成的list,保证还原字符串顺序
def get_hide_string(s,url):
    result=[]
    a_list = re.split('</\S+>',s)
   # print(a_list)
    b=[]
    for i in a_list:
        try:
            dex = i.index('<')
        except ValueError:
            b.append(i)
            continue
        if dex!=0:
            b.append(i[:dex])
        rule = re.compile('<(.*?) class="(.*?)"')
        tag = re.findall(rule,i[dex:])[0]
        b.append(tag)
    try:
        b.remove('')
    except ValueError:
        pass
    print(b)#b为已清洗好的list,接下来分别还原标签替换数据
    html = requests_middler(url)
    html = html.text
    for tag in b:
        #遇到类别标签则分类进行筛选
        if tag[0]=='span'or tag[0]== 'cc' or tag[0]=='bb':
            hide_char=get_position_xy(html,tag[1],tag[0],url)
            result.append(hide_char)
        #防止被其它标签干扰
        elif tag[0]==''or tag[0]=='p'or tag[0]=='div':
            continue
        #遇到中文及不含标签则直接加入list
        else:
            result.append(tag)
    return ''.join(result).strip('\n').strip()
if __name__=='__main__':
    url ='https://www.dianping.com/shop/507576/review_all'
    cookies={}#自己加入当时访问的cookies
    headers = {'User-Agent': ''}#加入自己的User-Agent
    response=requests.get(url,headers=headers,cookies=cookies)
    html = lxml.html.fromstring(response.content)
    #找到标签数据,必须要保留标签,这里以商店地址为例
    rule = re.compile('<div class="address-info">(.*?)</div>', re.S)
    address=re.findall(rule,response.text)[0]
    address = address.strip().replace('\n','').replace('&nbsp','')
    #找到css表,css表链接存放位置固定,所以直接获取
    css = html.xpath('//link[@rel="stylesheet"]/@href')[1]
    url ='http:'+css.strip()
    result = get_hide_string(address,url)
    result=result.replace(' ','')
    print('解密前数据:'+address)
    print('解密后数据:'+result)
代码运行结果 如图4-1所示:
图4-1 运行结果图
六、总结

总结一下,就是先找到被替换数据标签,发现替换时对应的css表,找到css表,根据标签属性class值作key值去找到对应的坐标,同时找到标签类别所对应的svg数据表链接,最后参照数据表坐标得到被隐藏的数据。
大众点评前端JS加密方法与平时遇到的都不太一样,所以花了一些时间来讲,之后遇到不一样的JS加密也会给大家一起学习探讨,同样如果发现文章的不足,欢迎指出。

注意:由于大众点评数据表和替换内容一直在变化,所以你们看到的内容将可能与我写的不一样,但是原理和方法还是一样。
如果您喜欢我的文章,请关注或点击喜欢,您的支持是我最大的动力 ^ ^~!
仅供学习参考,切勿用于商业用途
转载请注明作者及其出处

黑羊的皇冠 简书主页

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,422评论 1 45
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,176评论 0 9
  • HTML标签解释大全 一、HTML标记 标签:!DOCTYPE 说明:指定了 HTML 文档遵循的文档类型定义(D...
    米塔塔阅读 3,224评论 1 41
  • EXCEL小白的进阶之路 从16年3月申请的小号,到现在发表的微文,屈指可数,纠结于想要好的内容,好的页面排版,然...
    Rachelhaha阅读 928评论 0 0
  • 暑假刚过,前段时间,一篇热文刷爆了朋友圈《中产阶级的焦虑:月薪三万撑不起孩子的一个暑假》,这篇文章说的是一个中产阶...
    纸匠情挑阅读 650评论 0 4