python实战:破解大众点评用CSS加密数字的反爬机制
**1、**此次我们以该站点:惠州粤菜推荐 为目标站点,来到站点后打开chrome的开发者工具,点击刷新页面,按下图操作你会看到点评数中部分数字被进行了加密,所显示的只有span标签和class 并没有数字信息。
点击其中的某个标签,通过查看css信息就会发现在里面有个网址(即上图中的【4】),点击打开该网址你会看到下图:
其实这些数字是SVG矢量图,SVG矢量图是基于可扩展标记语言,用于描述二维矢量图形的一种图形格式,通过使用不同的偏移量就能显示不同的字符。而在第一张图中我们可以看到rtsj0这个css class里面有一个background属性,其定义了背景图片偏移的位置,所以点评网上显示数字的原理就是通过设置不同的偏移位置,显示背景图片相应位置上的数字。
**2、**知道其原理后,我们需找到定义这些css的文件及相应的svg矢量图,按照第一张图的操作我们点击【3】,会跳转到下图:
从上图中我们就能知道各种css是如何定义偏移量的,且从backgro-image这个属性里能得到svg矢量图的地址,要想知道这个svg矢量图地址我们就得先知道这个css文件是如何请求到的。前期经过多次测试发现这个css文件的网址是会变化的,因此我们需让程序去找到这个css文件的地址而不是每次都手动寻找。我们先按下图进行操作
再切换到Elements中按下图操作进行搜索:
找到这个css文件后,我们就可以通过正则表达式将该地址提取出来(提取规则看最后源码),提取出来后请求这个URL地址会到下图这个页面:
在上图中就有包含svg矢量图的地址,我们再次用正则表达式提取(提取规则看最后源码)就能得到backgro-image这个属性的值后再去请求就得到svg矢量图。接下来就是该如何解密这个偏移量来找到对应的数字,我在这篇博客 https://blog.csdn.net/weixin_43796109/article/details/86506050 中的解密方法受到启发。
**3、**知道解密的方式后编写代码,以下是我的全部源码:
import re from lxml import etree from requests_html import HTMLSession class DaZhong(): def __init__(self): #此处以爬取第一页中的评论数为例 self.stat_url='http://www.dianping.com/huizhou/ch10/g103' def parse_url(self,url): session = HTMLSession() response = session.get(url) return response.content.decode() #在页面找到定义这些css的URL地址 def get_css_url(self): html = self.parse_url(self.stat_url) svgtextcss = re.search(r'href="([^"]+svgtextcss[^"]+)"', html, re.M) css_url = svgtextcss.group(1) return css_url #我们从定义偏移量的css文件里找到背景图片的路径,并获取SVG返回的数据 def get_svg(self): content = self.parse_url('https:'+self.get_css_url()) svg = re.search(r'span\[class\^="rt"\].*?background\-image: url\((.*?)\);', content) svg_url = svg.group(1) svg_html = self.parse_url('https:'+ svg_url) return svg_html # 获取定义偏移量的css文件后将结果以字典形式存储,以便我们传入页面中任意css名称来获取其对应的偏移量 def get_css_offset(self): css_html = self.parse_url('https:'+self.get_css_url()) offset_item=re.findall(r'(\.[a-zA-Z0-9-]+)\{background:-(\d+).0px -(\d+).0px',css_html) result={} for item in offset_item: css_class = item[0][1:] xoffset = item[1] yoffset = item[2] result[css_class] = [xoffset,yoffset] return result #根据偏移量找到对应的数字 def parse_comment_css(self,xoffset,yoffset): svg_html = self.get_svg() pattern = re.compile(r'y=.*?(\d+)">(\d+)</text>', re.S) items = re.findall(pattern, svg_html) svg_list=[] for item in items: svg={} svg['y_key']=int(item[0]) svg['text']=item[1] svg_list.append(svg) x,y=int(xoffset),int(yoffset) if y<=svg_list[0]['y_key']: # print('数字:',svg_list[0]['text'][x//12]) return svg_list[0]['text'][x//12] elif y<=svg_list[1]['y_key']: # print('数字:', svg_list[1]['text'][x// 12]) return svg_list[1]['text'][x// 12] else: # print('数字:', svg_list[2]['text'][x // 12]) return svg_list[2]['text'][x // 12] #获取点评数 def get_comment_num(self): content=self.parse_url(self.stat_url) html = etree.HTML(content) shops = html.xpath('.//div[@id="shop-all-list"]/ul/li')#获取到所有店面 css_class_dirt=self.get_css_offset()#获取定义偏移量的css文件后将结果以字典形式存储 for shop in shops: shop_name=shop.xpath('.//div[@class="tit"]/a/@title')[0]#获取店名 review_num = shop.xpath('.//div[@class="comment"]/a[contains(@class,"review-num")]/b')[0]#获取可见的数字 num = 0 if review_num.text: num =int(review_num.text) for review_node in review_num: css_class = review_node.attrib["class"]#获取css名称 #根据css名称获取其对应的偏移量 xoffset,yoffset=css_class_dirt[css_class][0],css_class_dirt[css_class][1] # 根据偏移量来找到对应的数字 new_num = self.parse_comment_css(xoffset,yoffset) num = num * 10 + int(new_num ) print("restaurant: {}, review_num: {}".format(shop_name, num)) if __name__ == '__main__': dazhong=DaZhong() dazhong.get_comment_num()
程序运行结果:
- 【Python3爬虫】大众点评爬虫(破解CSS反爬)
- [TensorFlow深度学习深入]实战二·使用CNN网络识别破解数字验证码
- python 反反爬虫策略之js动态加密url破解
- Python起点字体加密破解
- Python Opencv实战之数字识别之knn算法入门
- 关于采用消息钩子机制的透明加密的简单破解
- 反反爬技术,破解猫眼网加密数字
- 用Python破解有道翻译反爬虫机制
- 1048. 数字加密(20)--Python
- Python实战小程序——密码加密小工具(Crypto库)
- 使用python实现简单的加密解密机制
- .NET 实战SSL安全加密机制 [转]
- CrazyWing:Python自动化运维开发实战 七、Python数据类型之数字
- (python3)1048.数字加密(20分)
- Python---项目3-破解使用crypt方法加密(已加salt参数)的登录密码
- Python 网络爬虫反爬破解策略实战
- python破解zip加密文件的方法
- python之实战----朴素贝叶斯之手写数字位图
- python实现字符串加密成纯数字
- myeclipse9.X加密和破解机制