前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >爬虫入门经典(二十一) | 破解CSS加密之爬取大众点评

爬虫入门经典(二十一) | 破解CSS加密之爬取大众点评

作者头像
不温卜火
发布于 2020-11-24 07:10:08
发布于 2020-11-24 07:10:08
2.1K00
代码可运行
举报
文章被收录于专栏:不温卜火不温卜火
运行总次数:0
代码可运行

  大家好,我是不温卜火,是一名计算机学院大数据专业大三的学生,昵称来源于成语—不温不火,本意是希望自己性情温和。作为一名互联网行业的小白,博主写博客一方面是为了记录自己的学习过程,另一方面是总结自己所犯的错误希望能够帮助到很多和自己一样处于起步阶段的萌新。但由于水平有限,博客中难免会有一些错误出现,有纰漏之处恳请各位大佬不吝赐教!暂时只在csdn这一个平台进行更新,博客主页:https://buwenbuhuo.blog.csdn.net/

PS:由于现在越来越多的人未经本人同意直接爬取博主本人文章,博主在此特别声明:未经本人允许,禁止转载!!!



在上篇文章中我们已经讲了js加密,这个需要使用者有基本的js阅读和调试能力。但是不一定都解决所有问题,不过可以提供这样的流程和思路。

那么接下来我们再来看一种加密,css加密,这里我们以大众点评为例。

推荐

  ♥各位如果想要交流的话,可以加下QQ交流群:974178910,里面有各种你想要的学习资料。♥

  ♥欢迎大家关注公众号【不温卜火】,关注公众号即可以提前阅读又可以获取各种干货哦,同时公众号每满1024及1024倍数则会抽奖赠送机械键盘一份+IT书籍1份哟~♥

一、分析网页

大众点评:https://www.dianping.com/

1.1 尝试获取网页内容

我们打开后随便输入个搜索内容,在此我们以洗浴为例。我们可以看到如下图

图中的导航栏我们看到最后的洗浴是中文。那么这个时候我们就要有作为一名爬虫爱好者的敏锐性,我们如果发现url中存在中文的话就需要立马想到url编码和解密。如果不进行解密的话,我们直接使用是无法的到结果的。如果不信的话,博主在此给出测试。

首先,我们先把URL复制出来

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://www.dianping.com/search/keyword/166/0_%E6%B4%97%E6%B5%B4

我们可以看到中文复制出来就是一堆乱码,然后我们测试看能不能把内容输出出来。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests
from urllib.parse import quote,unquote

url = "https://www.dianping.com/search/keyword/166/0_%E6%B4%97%E6%B5%B4"
headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
}
response = requests.get(url=url,headers=headers)
print(response.content.decode("utf-8"))

下面我们来看下结果,并查看是否存在有巴厘岛温泉洗浴

我们通过查看并没有得到我们所预想的内容,这就代表我们尝试打印内容失败了。这个时候我们就需要解析那堆乱码。想要解析在Python中很简单,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from urllib.parse import quote,unquote

wd = "洗浴"
print(quote(wd))
print(unquote("%E6%B4%97%E6%B5%B4"))

?,知道如此。下面我们就开始再次尝试获取页面内容。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests
from urllib.parse import quote,unquote

wd = "洗浴"
url = "https://www.dianping.com/search/keyword/166/0_{}".format(quote(wd))
headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
    "Cookie": "cy=166; cye=xinxiang; _lxsdk_cuid=1751ad609f6c8-0dcdc7e6277655-c781f38-1fa400-1751ad609f7c8; _lxsdk=1751ad609f6c8-0dcdc7e6277655-c781f38-1fa400-1751ad609f7c8; _hc.v=70a91160-e474-cf3e-0698-45733f3ee3c3.1602473037; s_ViewType=10; fspop=test; Hm_lvt_602b80cf8079ae6591966cc70a3940e7=1602473037,1602492673,1603287877,1603414224; _lx_utm=utm_source%3Dyoudao%26utm_medium%3Dorganic; Hm_lpvt_602b80cf8079ae6591966cc70a3940e7=1603415295; _lxsdk_s=175533f654a-5e4-832-9d2%7C%7CNaN"
}
response = requests.get(url=url,headers=headers)
print(response.content.decode("utf-8"))

下面看能不能获取到内容

我们可以看到,全部内容我们已经能够获取到了。

1.2 分析网页(调试界面发现问题)

我们既然已经能打印出网页的所有内容,那么接下来我们就可以分析网页了。 下面我们分别进行分析:

  • 1. 名称(无加密)
  • 2. 评价数(有加密)
  • 3. 人均消费(有加密)
  • 3. 类型(有加密)
  • 4. 区域地址(有加密)
  • 5. 详细地址(有加密)

通过上述的查看网页,我们发现这些信息中,有的是正常的汉字,而有的则是未知的符号。这个时候我们在响应内容中再找一下,看看到底是什么东西。

我们这里以查找洗浴/汗蒸为例

1.3 分析字体

我们通过开发者选项看到的特殊符号其实是一种字体,是大众点评专门加密的一种CSS字体。

我们先把此部分的CSS复制出来!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@font-face {
    font-family: "PingFangSC-Regular-reviewTag";
    src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/f9935be8.eot");
    src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/f9935be8.eot?#iefix") format("embedded-opentype"),url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/f9935be8.woff");
}

.reviewTag {
    font-family: 'PingFangSC-Regular-reviewTag';
}

@font-face {
    font-family: "PingFangSC-Regular-shopNum";
    src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/c884993d.eot");
    src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/c884993d.eot?#iefix") format("embedded-opentype"),url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/c884993d.woff");
}

.shopNum {
    font-family: 'PingFangSC-Regular-shopNum';
}

@font-face {
    font-family: "PingFangSC-Regular-address";
    src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/c884993d.eot");
    src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/c884993d.eot?#iefix") format("embedded-opentype"),url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/c884993d.woff");
}

.address {
    font-family: 'PingFangSC-Regular-address';
}

@font-face {
    font-family: "PingFangSC-Regular-tagName";
    src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/f58a3e31.eot");
    src: url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/f58a3e31.eot?#iefix") format("embedded-opentype"),url("//s3plus.meituan.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/f58a3e31.woff");
}

.tagName {
    font-family: 'PingFangSC-Regular-tagName';
}

通过上述源码与图片对比,我们可以看到虽然有四个woff文件(woff文件是字体文件),但是有两个是重复的,所以大众点评的自定义字体初步判断为三个。

1.4 下载字体

  • 1. 我们先把css复制下来
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
url = "https://s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/b75a2a536f46287f7538c3a0b09f7e9d.css"
  • 2. 尝试打印下
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests

url = "https://s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/b75a2a536f46287f7538c3a0b09f7e9d.css"
headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
}
response = requests.get(url=url, headers=headers)
content = response.content.decode("utf-8")
print(content)
  • 3. 正则解析并打印
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
woff_url_list = re.findall(r'url\("(//s3plus\.meituan\.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/\w+?\.woff)"\)',
                           content)
print(woff_url_list)
for i in woff_url_list:
    print(i)
  • 4. 拼接字符串并打印
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
woff_url_list = map(lambda x: "https:" + x, woff_url_list)
for woff_url in woff_url_list:
    response = requests.get(url=woff_url, headers=headers)
    content = response.content
    filepath = woff_url.split("/")[-1]
    with open(filepath,"wb") as file:
        file.write(content)

二、如何查看woff文件

如何打开woff文件呢?之前百度提供了字体接口可以打开woff,但是现在暂时不能使用了,那可以使用fontcreator工具打开,先下载fontcreator,然后打开woff。

2.1 下载

下载地址:http://www.32r.com/soft/42836.html 注意:此下载链接并非官网,如果对此有疑惑的同学,可以自行下载其他,学长用的是这个。

如果不会使用可以查看帮助文档。

2.2 打开woff文件

我们首先需要找到我们下载woff文件的目录。

然后file—>open—>下载存储文件夹—>选中woff文件—>打开

打开之后的样子如下图:

下面我们通过动图来看一下三个文件的区别:

打开这个3个woff文件发现文字内容和顺序是一样的,只是上面的uni符号不同。

首先我们先来确定一下这个加密字体所对应的文件名称

通过上图我们可以看到此部分对应的文件名为:f58a3e31

woff文件可以理解为键值对,键是uni+16进制的字符,值就是字体。复制响应内容中的字体,然后去woff,ctrl+f寻找,下面我们就来看一下。

三、python读取woff

现在思路就是爬取网页中的信息,然后去对应的wolf文件中去找对应的字体,那现在有个问题,woff文件怎么转键值对,目前没有好的办法,只能自己将字体一个一个复制出来,这里给大家准备一个复制出来整理之后的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
word_string='1234567890店中美家馆小车大市公酒行国品发电金心业商司超生装园场食有新限天面工服海华水房饰城乐汽香部利子老艺花专东肉菜学福饭人百餐茶务通味所山区门药银农龙停尚安广鑫一容动南具源兴鲜记时机烤文康信果阳理锅宝达地儿衣特产西批坊州牛佳化五米修爱北养卖建材三会鸡室红站德王光名丽油院堂烧江社合星货型村自科快便日民营和活童明器烟育宾精屋经居庄石顺林尔县手厅销用好客火雅盛体旅之鞋辣作粉包楼校鱼平彩上吧保永万物教吃设医正造丰健点汤网庆技斯洗料配汇木缘加麻联卫川泰色世方寓风幼羊烫来高厂兰阿贝皮全女拉成云维贸道术运都口博河瑞宏京际路祥青镇厨培力惠连马鸿钢训影甲助窗布富牌头四多妆吉苑沙恒隆春干饼氏里二管诚制售嘉长轩杂副清计黄讯太鸭号街交与叉附近层旁对巷栋环省桥湖段乡厦府铺内侧元购前幢滨处向座下臬凤港开关景泉塘放昌线湾政步宁解白田町溪十八古双胜本单同九迎第台玉锦底后七斜期武岭松角纪朝峰六振珠局岗洲横边济井办汉代临弄团外塔杨铁浦字年岛陵原梅进荣友虹央桂沿事津凯莲丁秀柳集紫旗张谷的是不了很还个也这我就在以可到错没去过感次要比觉看得说常真们但最喜哈么别位能较境非为欢然他挺着价那意种想出员两推做排实分间甜度起满给热完格荐喝等其再几只现朋候样直而买于般豆量选奶打每评少算又因情找些份置适什蛋师气你姐棒试总定啊足级整带虾如态且尝主话强当更板知己无酸让入啦式笑赞片酱差像提队走嫩才刚午接重串回晚微周值费性桌拍跟块调糕'

这里将所有的文字按照顺序复制组合成了一个字符串,怎么确定顺序呢?可以通过python读取woff,找到&#xe909对应的字体的顺序数字,这样拿这个数字去字符串中通过下标获取就可以了。

  • 1. python读取woff,需要安装fonttools
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pip install fonttools
  • 2. 使用fonttools读取woff
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from fontTools.ttLib import TTFont

tagName = TTFont("f58a3e31.woff")
print(tagName.getGlyphOrder())

接下来利用tagName.getGlyphOrder()结果为键和word_string为值,组成对应的字典:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from fontTools.ttLib import TTFont

tagName = TTFont("f58a3e31.woff")
print(tagName.getGlyphOrder())
tag_name_list = tagName.getGlyphOrder()
word_string ='1234567890店中美家馆小车大市公酒行国品发电金心业商司超生装园场食有新限天面工服海华水房饰城乐汽香部利子老艺花专东肉菜学福饭人百餐茶务通味所山区门药银农龙停尚安广鑫一容动南具源兴鲜记时机烤文康信果阳理锅宝达地儿衣特产西批坊州牛佳化五米修爱北养卖建材三会鸡室红站德王光名丽油院堂烧江社合星货型村自科快便日民营和活童明器烟育宾精屋经居庄石顺林尔县手厅销用好客火雅盛体旅之鞋辣作粉包楼校鱼平彩上吧保永万物教吃设医正造丰健点汤网庆技斯洗料配汇木缘加麻联卫川泰色世方寓风幼羊烫来高厂兰阿贝皮全女拉成云维贸道术运都口博河瑞宏京际路祥青镇厨培力惠连马鸿钢训影甲助窗布富牌头四多妆吉苑沙恒隆春干饼氏里二管诚制售嘉长轩杂副清计黄讯太鸭号街交与叉附近层旁对巷栋环省桥湖段乡厦府铺内侧元购前幢滨处向座下臬凤港开关景泉塘放昌线湾政步宁解白田町溪十八古双胜本单同九迎第台玉锦底后七斜期武岭松角纪朝峰六振珠局岗洲横边济井办汉代临弄团外塔杨铁浦字年岛陵原梅进荣友虹央桂沿事津凯莲丁秀柳集紫旗张谷的是不了很还个也这我就在以可到错没去过感次要比觉看得说常真们但最喜哈么别位能较境非为欢然他挺着价那意种想出员两推做排实分间甜度起满给热完格荐喝等其再几只现朋候样直而买于般豆量选奶打每评少算又因情找些份置适什蛋师气你姐棒试总定啊足级整带虾如态且尝主话强当更板知己无酸让入啦式笑赞片酱差像提队走嫩才刚午接重串回晚微周值费性桌拍跟块调糕'

print(len(tag_name_list))
print(len(word_string))

tag_name_dict = {
    tag_name_list[0]:"",
    tag_name_list[1]:".",
}
for index,value in enumerate(word_string):
    tag_name_dict[tag_name_list[index+2][3:]]=value

print(tag_name_dict)
print(tag_name_dict.get("e909"))

那接下来就可以找到响应数据中的符号去字典中找到文字就可以了。

四、解析数据

?,前面我们已经把字体分析并下载下载下来了。不仅如此,我们还发现我们想要爬取的数据包括加密和未加密。那么接下来我们就需要分别进行判定。

首先我们先分析下网页的整体结构。

在进行解析之前,我们先对加密的内容进行字符的替换,这样是为了避免解析css加密数据获取后是unicode字符串。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    html = parse_url(data_url).decode("utf-8")
    html = re.sub(r"&#x(\w+?);", r"*\1*", html) 

至于为什么使用"&#x(\w+?);",我们可以看下图:

那么现在,我们就可以通过xpath进行尝试解析下,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    xpath_obj = parse_html(html)
    li_list = xpath_obj.xpath('//*[@id="shop-all-list"]/ul/li')
    print(li_list)
    print(len(li_list))

我们先来打印下所有的li_list以及其长度

通过打印,我们发现一页共有15个数据,我们现在查看下网页是不是有15个商品信息。

我们发现是对应的,那么接下来。我们就可以进行xpath解析了。

4.1 无加密数据解析

1. 店铺名称、URL及图片

  • 1. 查看图片

根据上图,我们可以看到这些都是没有加密的,那么这些都可以直接获取的。

  • 2. xpath解析
  • 3. 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    for li in li_list:
        item = {}
        item["shop_url"] = li.xpath("./div[1]/a/@href")[0]  # 店铺的url
        item["shop_img_url"] = li.xpath("./div[1]/a/img/@src")[0]  # 店铺图片的url
        item["shop_name"] = li.xpath("./div[1]/a/img/@title")[0]  # 店铺名称
        print(item)
  • 4. 查看结果

2. 星级

  • 1. 分析 我们首先先来看下网页:

接下来我们看一下star的网页源码

光看一个明白不了什么,那么接下来继续查看下一个star

?,我们这就知道了,数字对应的是星级,10个数为一个星。

  • 2. 代码实现

经过上述的分析,我们不难发现此部分只需截取数字即可

下面直接代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        star_class = li.xpath('.//*[@class="star_icon"]/span[1]/@class')[0]
        item["shop_star"] = star_class.split(" ")[1].split("_")[-1]  # 店铺评分
        print(item)

4.2 加密数据解析

在讲解加密数据解析之前,我们要先来说一下我们刚开始替换的特殊字符,也就是下面的这行代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
html = re.sub(r"&#x(\w+?);", r"*\1*", html)  # 替换特殊字符,避免解析css加密数据获取后是unicode字符串

我们刚开始替换的本意只是为了避免解析css加密数据获取后是unicode字符串,但是这个时候我们需要的正好是unicode,那么我们就需要对其进行解密。

解密的方式也很简单,那就是对添加的*进行删除。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 如果i是以*开头和结尾的那么要把*去掉并加上uni
get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[2]/a[1]/b//text()')

通过上述代码完成解密工作

1. 评论数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        class_name = li.xpath('./div[2]/div[2]/a[1]/b/svgmtsi/@class')
        if class_name:  # 有加密
            class_name = class_name[0]
            item["shop_comment_num"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[2]/a[1]/b//text()')])
        else:  # 没有加密
            item["shop_comment_num"] = "".join(li.xpath('./div[2]/div[2]/a[1]/b//text()'))#评论数
        print(item)

2. 人均消费

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        class_name = li.xpath('./div[2]/div[2]/a[2]/b/svgmtsi/@class')
        if class_name:  # 有加密
            class_name = class_name[0]
            item["shop_avg_money"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[2]/a[2]/b//text()')])
        else:  # 没有加密
            item["shop_avg_money"] = "".join(li.xpath('./div[2]/div[2]/a[2]/b//text()'))#人均消费

3. 商品类型

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        class_name = li.xpath('./div[2]/div[3]/a[1]/span/svgmtsi/@class')
        if class_name:
            class_name = class_name[0]
            item["shop_type"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[3]/a[1]/span//text()')])
        else:
            item["shop_type"] = "".join(li.xpath('./div[2]/div[3]/a[1]/span//text()'))

4. 区域地址

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        class_name = li.xpath('./div[2]/div[3]/a[2]/span/svgmtsi/@class')
        if class_name:
            class_name = class_name[0]
            item["shop_address1"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[3]/a[2]/span//text()')])#区域地址
        else:
            item["shop_address1"] = "".join(li.xpath('./div[2]/div[3]/a[2]/span//text()'))

5. 详细地址

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        class_name = li.xpath('./div[2]/div[3]/span[1]/svgmtsi/@class')
        if class_name:
            class_name = class_name[0]
            item["shop_address2"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[3]/span[1]//text()')])
        else:
            item["shop_address2"] = "".join(li.xpath('./div[2]/div[3]/span[1]//text()'))#详细地址

五、完整代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# encoding: utf-8
'''
  @author 李华鑫
  @create 2020-10-21 18:06
  Mycsdn:https://buwenbuhuo.blog.csdn.net/
  @contact: 459804692@qq.com
  @software: Pycharm
  @file: test.py
  @Version:1.0
  
'''
import requests
import re
import csv
from urllib.parse import quote, unquote
from fontTools.ttLib import TTFont
from lxml import etree

kw = "大虾"
page = 3
data_url = "https://www.dianping.com/search/keyword/166/0_{}/p{}".format(quote(kw),page)
css_url = "https://s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/c98b2eff300998c5ead0806616392718.css"

headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
    #这里使用的是登录成功后的cookie值,完成翻页
    "cookie":"cy=166; cye=xinxiang; _lxsdk_cuid=1751ad609f6c8-0dcdc7e6277655-c781f38-1fa400-1751ad609f7c8; _lxsdk=1751ad609f6c8-0dcdc7e6277655-c781f38-1fa400-1751ad609f7c8; _hc.v=70a91160-e474-cf3e-0698-45733f3ee3c3.1602473037; s_ViewType=10; fspop=test; _lx_utm=utm_source%3Dyoudao%26utm_medium%3Dorganic; thirdtoken=5aa19437-0035-4674-9190-c70e96879040; _thirdu.c=59d3f0429670580a7dcc7ec862021251; dplet=4808119962e3031ed4a6fd4245c9168d; dper=ca44d7e7084b3d21408f5d00fb216294c5c5f5a1ddf194a2463f8dabdc7d33697aaf6c4716cf66ad59f619083f368f4749284d8abaea2c63ed11302fb7b39543683c95c9742debc6e3d573faa6c809f007f8d43a9fc8ad7062daca33618146a8; ll=7fd06e815b796be3df069dec7836c3df; ua=dpuser_1347248252; ctu=920dfc17d3681bdbfe4ae1e91aa8c930f5fceac5db954e051167aafa53f3e29d; Hm_lvt_602b80cf8079ae6591966cc70a3940e7=1603440682,1603452564,1603454915,1603454940; Hm_lpvt_602b80cf8079ae6591966cc70a3940e7=1603454947; _lxsdk_s=1755556bdd3-ec-524-20f%7C%7C48"
}


def read_word_string():
    with open("./word_string.txt", "r", encoding="utf-8") as file:
        return file.read()



def parse_url(url):
    """解析url得到字节"""
    response = requests.get(url=url, headers=headers)
    return response.content


def parse_html(html):
    """使用xpath解析html,返回xpath对象"""
    etree_obj = etree.HTML(html)
    return etree_obj


def save_woff():
    """保存woff文件"""
    content = parse_url(css_url).decode("utf-8")
    woff_url_list = re.findall(
        r'url\("(//s3plus\.meituan\.net/v1/mss_73a511b8f91f43d0bdae92584ea6330b/font/\w+?\.woff)"\)', content)
    woff_url_list = map(lambda x: "https:" + x, woff_url_list)
    for woff_url in woff_url_list:
        content = parse_url(woff_url)
        filepath = woff_url.split("/")[-1]
        with open(filepath, "wb") as file:
            file.write(content)
    print("保存成功!")


def get_word(name, key):
    """读取指定的woff得到字体"""
    word = None
    if name == "tagName" or name == "shopNum":
        woff_name = "f58a3e31.woff"
    elif name == "address":
        woff_name = "b88ff555.woff"
    tag = TTFont(woff_name)
    order_list = tag.getGlyphOrder()
    index = order_list.index(key)
    word = word_string[index - 2]

    return word


def get_data():
    """获取数据"""
    html = parse_url(data_url).decode("utf-8")
    html = re.sub(r"&#x(\w+?);", r"*\1*", html)  # 替换特殊字符,避免解析css加密数据获取后是unicode字符串
    xpath_obj = parse_html(html)
    li_list = xpath_obj.xpath('//*[@id="shop-all-list"]/ul/li')

    for li in li_list:
        item = {}
        item["shop_url"] = li.xpath("./div[1]/a/@href")[0]  # 店铺的url
        item["shop_img_url"] = li.xpath("./div[1]/a/img/@src")[0]  # 店铺图片的url
        item["shop_name"] = li.xpath("./div[1]/a/img/@title")[0]  # 店铺名称

        star_class = li.xpath('.//*[@class="star_icon"]/span[1]/@class')[0]
        item["shop_star"] = star_class.split(" ")[1].split("_")[-1]  # 店铺评分



        class_name = li.xpath('./div[2]/div[2]/a[1]/b/svgmtsi/@class')
        if class_name:  # 有加密
            class_name = class_name[0]
            item["shop_comment_num"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[2]/a[1]/b//text()')])
        else:  # 没有加密
            item["shop_comment_num"] = "".join(li.xpath('./div[2]/div[2]/a[1]/b//text()'))#评论数


        class_name = li.xpath('./div[2]/div[2]/a[2]/b/svgmtsi/@class')
        if class_name:  # 有加密
            class_name = class_name[0]
            item["shop_avg_money"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[2]/a[2]/b//text()')])
        else:  # 没有加密
            item["shop_avg_money"] = "".join(li.xpath('./div[2]/div[2]/a[2]/b//text()'))#人均消费

        class_name = li.xpath('./div[2]/div[3]/a[1]/span/svgmtsi/@class')
        if class_name:
            class_name = class_name[0]
            item["shop_type"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[3]/a[1]/span//text()')])
        else:
            item["shop_type"] = "".join(li.xpath('./div[2]/div[3]/a[1]/span//text()'))

        class_name = li.xpath('./div[2]/div[3]/a[2]/span/svgmtsi/@class')
        if class_name:
            class_name = class_name[0]
            item["shop_address1"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[3]/a[2]/span//text()')])#区域地址
        else:
            item["shop_address1"] = "".join(li.xpath('./div[2]/div[3]/a[2]/span//text()'))


        class_name = li.xpath('./div[2]/div[3]/span[1]/svgmtsi/@class')
        if class_name:
            class_name = class_name[0]
            item["shop_address2"] = "".join(
                [get_word(class_name, "uni" + i.strip("*")) if (i.startswith("*") and i.endswith("*")) else i for i in
                 li.xpath('./div[2]/div[3]/span[1]//text()')])
        else:
            item["shop_address2"] = "".join(li.xpath('./div[2]/div[3]/span[1]//text()'))#详细地址
        print(item)
        save(item)

def save(item):
    """将数据保存到csv中"""
    with open("./大众点评-{}.csv".format(kw), "a", encoding="utf-8") as file:
        writer = csv.writer(file)
        writer.writerow(item.values())


if __name__ == '__main__':
    # save_woff()
    word_string = read_word_string()
    get_data()

六、运行结果

美好的日子总是短暂的,虽然还想继续与大家畅谈,但是本篇博文到此已经结束了,如果还嫌不够过瘾,不用担心,我们下篇见!


  好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。   如果我的博客对你有帮助、如果你喜欢我的博客内容,请“点赞” “评论”“收藏”一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。   码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/11/18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
安全研究者的自我修养
在上篇文章《推荐今年C3黑客大会上的几个议题》中提到”Attacking Chrome IPC“这个议题,我觉得该议题最大的亮点是在前半场,作者nedwill是之前在hack2win大赛上因攻破Chrome浏览器而一战成名,他讲了如何训练漏洞研究能力的过程,讲述自己这几年在漏洞研究上的历程和心得,很励志,其建议也非常具有可操作性,值得效仿学习。我反复看了多遍,对其作了一些总结和补充。
泉哥
2019/07/17
6840
【漏洞预警】Chrome PDF文件解析 0day漏洞预警
2019年2月28日,国外安全公司发现谷歌Chrome浏览器存在0day漏洞,可导致用户使用Chrome打开恶意PDF文件时发生信息泄露。根据监测,已在野外发现多个利用该漏洞的样本。
绿盟科技安全情报
2019/10/24
1.1K0
【漏洞预警】Chrome PDF文件解析 0day漏洞预警
安全研究的价值思考
最近的Black Hat大会议题ppt已提供下载,里面有两个非技术议题,其视角比较有趣,一些问题值得思考,因此才有本文。
泉哥
2019/08/20
4260
安全研究的价值思考
从研究者的视角看Fuzzing技术发展30年
1988年,在威斯康星大学Barton Miller教授的计算机实验课上(http://pages.cs.wisc.edu/~bart/fuzz/CS736-Projects-f1988.pdf),首次提出Fuzz生成器(Fuzz Generator)的概念,用于测试Unix程序的健壮性,即用随机数据来测试程序直至崩溃。因此,Barton Miller教授也被多数人尊称为"模糊测试之父"。但是,当时更多是为了验证代码质量和程序的稳定性,而非专门用于挖掘安全漏洞,真正用于软件安全漏洞挖掘的开端要从下面两件事说起。
泉哥
2020/02/14
2.5K0
针对小白到“大白”的黑盒CNVD挖掘经验
曾经作为一名想黑盒出CNVD的小白,我几乎看遍了所有公开的关于挖CNVD的文章与视频,什么CNVD收录条件啊,利用搜索引擎啊,刷弱口令啊,复现三例凑足十个案例啊......
红队蓝军
2024/05/01
1.2K1
针对小白到“大白”的黑盒CNVD挖掘经验
雪人行动:利用IE10 0day漏洞的APT攻击剑指美国军方情报
二月十一日,FireEye捕获了一次基于0day漏洞的攻击,这次攻击针对美国的一个退伍兵网站(bfw.org)。 我们确信这次攻击是针对美国高层军方人员的一次预谋已久的APT攻击,因为在这一天美国国会正巧因为暴风雪放假一天。因为攻击手法的相似性,我们认为它与不久之前的两次APT攻击有着一定的联系,这两次攻击是Operation DeputyDog 和 Operation Ephemeral Hydra. 这篇文章介绍了这次攻击所利用的漏洞和相关的攻击手法,并赋予了这次攻击一个代号“雪人行动”(Operat
FB客服
2018/02/02
7170
雪人行动:利用IE10 0day漏洞的APT攻击剑指美国军方情报
BlackHat USA 2021 洞察(三):议题技术解读
CHERI(Capability Hardware Enhanced RISC Instructions,功能硬件增强的RISC指令)利用新的体系结构功能扩展了常规的硬件指令集体系结构(ISA),从而实现了细粒度的内存保护和高度可扩展的软件分区。CHERI内存保护功能允许将历史上内存不安全的编程语言(例如C和C ++)进行修改,以针对许多当前被广泛利用的漏洞提供强大,兼容和有效的保护。它是在2020年11月由剑桥大学联合ARM公司发布的,基于Morello开源硬件平台设计的。
泉哥
2021/09/15
1.3K0
微软对外披露两个0day漏洞详情
微软近日对外披露了两个0day漏洞详情,其中一个漏洞存在Adobe阅读器中,可被利用导致任意代码执行;另一个漏洞则允许任意代码在Windows kernel内存中提权执行。
FB客服
2018/07/31
6420
微软对外披露两个0day漏洞详情
一步一步拿到学校图书馆, 资产管理,教务系统,学工系统权限的过程
(还有一些没有拿到管理员权限的系统这里就不写了),还有就是这些漏洞现在均以上交给学校。
黑战士
2021/04/05
2.3K0
一步一步拿到学校图书馆, 资产管理,教务系统,学工系统权限的过程
漏洞丨CVE20102883
此漏洞编号CVE-2010-2883,看着是一个很简单的栈溢出漏洞,但是也要看怎么玩了。这个漏洞是Adobe Acrobat Reader软件中CoolType.dll在解析字体文件SING表中的uniqueName字段的调用了strcat函数,但是对参数没有做出判断,没有检查uniqueName字段长度,导致了栈溢出漏洞。此漏洞影响版本如下: Adobe Acrobat 8.0 Adobe Acrobat 8.1 Adobe Acrobat 8.1.1 Adobe Acrobat 8.1.2 Adobe Acrobat 8.1.3 Adobe Acrobat 8.1.4 Adobe Acrobat 8.1.5 Adobe Acrobat 8.1.6 Adobe Acrobat 8.1.7 Adobe Acrobat 8.2 Adobe Acrobat 8.2.1 Adobe Acrobat 8.2.2 Adobe Acrobat 8.2.4 Adobe Acrobat 9.0 Adobe Acrobat 9.1 Adobe Acrobat 9.1.1 Adobe Acrobat 9.1.2 Adobe Acrobat 9.1.3 Adobe Acrobat 9.2 Adobe Acrobat 9.3 Adobe Acrobat 9.3.1 Adobe Acrobat 9.3.2 Adobe Acrobat 9.3.3 Adobe Acrobat Apple Mac_Os_X Microsoft Windows Adobe Acrobat_Reader 8.0 Adobe Acrobat_Reader 8.1 Adobe Acrobat_Reader 8.1.1 Adobe Acrobat_Reader 8.1.2 Adobe Acrobat_Reader 8.1.4 Adobe Acrobat_Reader 8.1.5 Adobe Acrobat_Reader 8.1.6 Adobe Acrobat_Reader 8.1.7 Adobe Acrobat_Reader 8.2.1 Adobe Acrobat_Reader 8.2.2 Adobe Acrobat_Reader 8.2.3 Adobe Acrobat_Reader 8.2.4 Adobe Acrobat_Reader 9.0 Adobe Acrobat_Reader 9.1 Adobe Acrobat_Reader 9.1.1 Adobe Acrobat_Reader 9.1.2 Adobe Acrobat_Reader 9.1.3 Adobe Acrobat_Reader 9.2 Adobe Acrobat_Reader 9.3 Adobe Acrobat_Reader 9.3.1 Adobe Acrobat_Reader 9.3.2 Adobe Acrobat_Reader 9.3.3 这次我用的是9.0版本。
极安御信安全研究院
2023/03/31
3840
漏洞丨CVE20102883
Adobe Reader 缓冲区溢出漏洞 (CVE-2010-2883)漏洞分析报告
Adobe Reader(也被称为Acrobat Reader)是美国Adobe公司开发的一款优秀的PDF文件阅读软件。文档的撰写者可以向任何人分发自己制作(通过Adobe Acrobat制作)的PDF文档而不用担心被恶意篡改。
极安御信安全研究院
2022/01/20
5750
Adobe Reader 缓冲区溢出漏洞 (CVE-2010-2883)漏洞分析报告
腾讯御见捕获Flash 0day漏洞(CVE-2018-5002)野外攻击
腾讯御见威胁情报中心近日监控到一例使用Adobe Flash 0day漏洞(CVE-2018-5002)的APT攻击,攻击者疑通过即时聊天工具和邮箱等把恶意Excel文档发送给目标人员,诱骗目标人员打开文档。实际上,该恶意Excel文档经过特别构造,被嵌入了flash对象,用户一旦打开文档电脑就会中毒。
FB客服
2018/07/30
9500
腾讯御见捕获Flash 0day漏洞(CVE-2018-5002)野外攻击
CVE-2013-3346-Adobe Reader ToolButton 释放重引用漏洞
ftp://ftp.adobe.com/pub/adobe/reader/win/11.x/11.0.00/zh_CN/AdbeRdr11000_zh_CN.exe
用户1423082
2024/12/31
1290
CVE-2013-3346-Adobe Reader ToolButton 释放重引用漏洞
SRC漏洞挖掘经验+技巧篇
很多人挖洞的时候说不知道如何入手,其实挖洞就是信息收集+常规owasp top 10+逻辑漏洞(重要的可能就是思路猥琐一点),这些漏洞的测试方法本身不是特别复杂,一般混迹在安全圈子的人都能复现漏洞。接下来我就着重说一下我在信息收集方面的心得。
HACK学习
2019/08/06
10K0
SRC漏洞挖掘经验+技巧篇
实战|我的SRC挖掘-如何一个洞拿下百分QAQ
在goby乱扫的开始,我也是菜弟弟一样,看到什么都没感觉,直到有个师傅提醒了我:这不是Sprint boot框架么,洞这么多还拿不下?
F12sec
2022/09/29
9340
实战|我的SRC挖掘-如何一个洞拿下百分QAQ
SRC混子的漏洞挖掘之道
还是那句老话,渗透测试的本质是信息收集,对于没有0day的弱鸡选手来说,挖SRC感觉更像是对企业的资产梳理,我们往往需要花很长的时间去做信息收集,收集与此公司相关的信息,包括企业的分公司,全资子公司,网站域名、手机app,微信小程序,企业专利品牌信息,企业邮箱,电话等等,对于很多万人挖的src来说,你收集到了别人没有收集过的资产,往往离挖到漏洞就不远了。
Power7089
2021/01/11
3.3K0
学习下 BlackHat Asia 2021 大会议题
BlackHat Asia 2021会议已经结束,相关议题资料也放出,刚好这两天周末抽空学习下,共39个议题,覆盖范围还是比较广的,虽然议题质量不如USA主会场,但多少还是有一些值得学习的内容,我只挑了一些感兴趣的议题做些介绍,更多内容可以上官方下载(https://www.blackhat.com/asia-21/briefings/schedule/index.html)。
泉哥
2021/05/20
1.6K0
BlackHat USA 2021 洞察(二):议题技术解读
发现看议题材料也不容易啊,有些议题挺有技术深度的,而且内容还特长,长就算了,有些ppt其实只讲了不到一半的内容,另一半都得靠作者演讲才能知道,剩下的只能靠自己脑补或搜索资料了,我只能说真的费脑费时间。
泉哥
2021/08/20
9380
回顾 2021 年在野利用的 0day 漏洞
作者:Maddie Stone@Google Project Zero 译者:知道创宇404实验室翻译组 原文链接:https://googleprojectzero.blogspot.com/2022/04/the-more-you-know-more-you-know-you.html 这是我们回顾在野利用 0day 漏洞的第三个年度。 2019年: https://googleprojectzero.blogspot.com/2020/07/detection-deficit-year-in-revi
Seebug漏洞平台
2022/04/25
2.6K0
回顾 2021 年在野利用的 0day 漏洞
异常中的异常:借助系统异常处理特例实现匪夷所思的漏洞利用
本文介绍了在Windows系统漏洞挖掘过程中,利用系统异常处理流程中的ATL thunk emulation,绕过DEP保护,达到控制内存、执行任意代码的目的。通过漏洞利用技术,可以绕过一些安全措施,使得攻击者可以执行恶意代码。
腾讯玄武实验室
2017/08/08
1.1K0
异常中的异常:借助系统异常处理特例实现匪夷所思的漏洞利用
推荐阅读
相关推荐
安全研究者的自我修养
更多 >
LV.0
腾讯高级工程师
目录
  • 推荐
  • 一、分析网页
    • 1.1 尝试获取网页内容
    • 1.2 分析网页(调试界面发现问题)
    • 1.3 分析字体
    • 1.4 下载字体
  • 二、如何查看woff文件
    • 2.1 下载
    • 2.2 打开woff文件
  • 三、python读取woff
  • 四、解析数据
    • 4.1 无加密数据解析
      • 1. 店铺名称、URL及图片
      • 2. 星级
    • 4.2 加密数据解析
      • 1. 评论数
      • 2. 人均消费
      • 3. 商品类型
      • 4. 区域地址
      • 5. 详细地址
  • 五、完整代码
  • 六、运行结果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档