为了找到物美价廉的房子,连夜爬了某租房网站1W多条租房信息
本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理
以下文章来源于python数据分析之禅, 作者:小dull鸟
文章插图
前言最近要租房子了 , 为了找到物美价廉的房子 , 我昨天连夜爬了某租房网站7000多条租房信息 , 爬取结果如下:
文章插图
本次爬取难点在于数字解密 , 好在最后都解决了 , 下面把爬取过程分享给大家
一、分析网页 , 获取原始数据网址为:
文章插图
此网页有2类数据:
文章插图
第一种是嵌在网页内的数据第二种是axja获取的json数据 , 解析后插入网页
对于第一种 , 由于数据在网页中 , 我们只需模拟请求网页 , 解析网页数据 , 把我们需要的数据保存即可:
文章插图
由上图可以发现 , 原始网页中 , 户型、价格等数字信息显示不对 , 已被加密 。 这里先不管 , 后面再讲解密 , 爬虫代码如下:
import requestsfrom bs4 import BeautifulSoups = requests.Session()s.headers = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8','accept-language': 'en-US,zh;q=0.8,zh-CN;q=0.7,zh-TW;q=0.5,zh-HK;q=0.3,en;q=0.2','referer': '','upgrade-insecure-requests': '1','user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',}s.get(url='')response=s.get('pn1/?PGTID=0d300008-0000-1e0f-27d7-0238e53f2f24 --tt-darkmode-color: #9B9B9B;">对于第二种 , 需要抓包获取数据接口:
文章插图
文章插图
通过抓包 , 很容易获取数据接口 , 该接口通过pageNum参数控制页码 , 总共有54页 , 返回的是json格式数据 , 代码如下:
import requests,jsonfor page in range(54):url=';basequery=room:j|cityId:1|areaId:1|cateId:8 --tt-darkmode-color: #9B9B9B;">可以发现 , 这部分数据没有加密
二、对第一部分数据进行解码网上有一种方法是找出加密后的文字与数字的对应关系 , 然后进行解密 , 这种方法是不对的 , 因为网页每刷新1次 , 这种对应关系就会重新改变 。
这类问题属于字体加密 , 字体加密一般是网页修改了默认的字符编码集 , 在网页上加载的他们自己定义的字体文件作为字体的样式 , 可以正确地显示数字 , 但是在源码上同样的二进制数由于未加载自定义的字体文件就由计算机默认编码成了乱码 。
文章插图
一般来说 , 通用的解决办法是找到字体文件 , 分析文件中的映射关系 。 一般来说 , 字体文件都是作为样式加在加密字体的部位 。
通过测试 , 当取消font-family前面的勾选后 , 网页中的数据开始加密
文章插图
所以可以确定 , fangchan-secret最可能是字体加密文件
在源码中Ctrl+F搜索fangchan-secret 寻找字体加密文件
文章插图
字体文件是通过base64加密之后放在js里面
下面开始写代码进行解密:
1.用正则将加密部分提取出来 , 然后用base64解码 , 转化成为二进制形式bs64Str = re.findall("charset=utf-8;base64,(.*?)\'\)", response.text)[0]binData = http://kandian.youth.cn/index/base64.decodebytes(bs64Str.encode())
2.写入otf字体文件filePath01 = r'\jiemi.otf'with open(filePath01, 'wb') as f:f.write(binData)f.close()
3.解析字体库font01 = TTFont(filePath01)utfList = font01['cmap'].tables[0].ttFont.tables['cmap'].tables[0].cmap# c = font.getBestCmap()retList = []for i in getText:if ord(i) in utfList:text = int(utfList[ord(i)][-2:]) - 1else:text = i
4.构造解密函数 , 传入加密后的文字 , 返回解析后的数字def convert(getText):bs64Str = re.findall("charset=utf-8;base64,(.*?)\'\)", response.text)[0]binData = http://kandian.youth.cn/index/base64.decodebytes(bs64Str.encode())# 写入otf字体文件filePath01 = r'\jiemi.otf'with open(filePath01, 'wb') as f:f.write(binData)f.close()# 解析字体库font01 = TTFont(filePath01)utfList = font01['cmap'].tables[0].ttFont.tables['cmap'].tables[0].cmap# c = font.getBestCmap()retList = []for i in getText:# ord()以字符作为参数 , 返回对应的Unicode数值if ord(i) in utfList:text = int(utfList[ord(i)][-2:]) - 1else:text = iretList.append(text)return(''.join([str(j) for j in retList]).split('\n'))
- 手机基带|为了5G降低4G网速?中国移动回应来了:罪魁祸首不是运营商
- 芯片制造|美围堵计划再次破产,华为找到“新帮手”,供货商:无需美国许可
- 中国移动高管再放狠话!不会为了5G网降低4G网速:可以放心了
- 史上最短命旗舰!为了华为P50:Mate40部分机型疑似停产
- 为了赚钱费尽心思,iPhone12的3个小心思,你看懂了吗?
- 老板为了挣钱心真黑!主板没坏却说坏了,客户:幸亏我跑得快
- 听说iPhone 12涨价了?苹果:都是为了环保
- 华为荣耀出售,也许为了生存找个新东家代管是最好选择
- 华为公司将子品牌荣耀寻求出售是断尾求生,还是为了突破困境?
- 为了德玛西亚 OPPO发布Find X2英雄联盟S10限定版:售价4999元