记录爬取猫眼电影票价遇到的数字加密问题

萌新爬虫笔记1:

爬取复联4在猫眼的电影票价,但是打开开发者工具查看数据发现,这是个啥??见图1-1
记录爬取猫眼电影票价遇到的数字加密问题_第1张图片
于是走上了谷歌百度的查询之路,发现这是猫眼的一种反爬机制,把数字加密了,参考给后人种树的大神的文章,我找到了源代码中字体文件的url,见图1-2
记录爬取猫眼电影票价遇到的数字加密问题_第2张图片
大神的文章一开始看不懂,只有按照文章一步步来操作,一边操作一边(试图)理解,下面就将理解步骤写下来:

1.下载font文件,建立编码与数字的对应关系

如,url 是http://vfile.meituan.net/colorstone/0c8275bcb0958d2c1e831048f0f0c7562088.woff
浏览器打开地址下载文件,我是直接保存至pycharm的project文件中的,这样使用fontTools.ttLib 的 TTFont 将.woff 文件保存成.xml文件时就直接写文件名了,代码贴图如下,保存为.xml文件主要是为了能够先手动对比出Unicode编码和数字的对应关系
保存xml文件
记录爬取猫眼电影票价遇到的数字加密问题_第3张图片
那么怎么看哪个编码对应数字几呢,这里需要用到字体编辑器,我是用的在线http://fontstore.baidu.com/static/editor/index.html
导入之前下载的.woff,会得到
记录爬取猫眼电影票价遇到的数字加密问题_第4张图片
但是因为猫眼这个页面每次刷新不止加密后的数据会变,字体文件中的Unicode编码也会变,所以只能通过建立字体文件中Unicode编码对应的x y 字体坐标(不专业的说法,具体在.xml中是下图)与数字的对应关系,通过字体x y组成来对比出数字
记录爬取猫眼电影票价遇到的数字加密问题_第5张图片
下面就来建立编码与数字的对应关系:
记录爬取猫眼电影票价遇到的数字加密问题_第6张图片

2.重新获取带爬取页面字体文件,通过字体组成对比出数字,还原源代码的本真,保存在本地,就能继续爬数据啦

这里就直接帖代码了:

from fontTools.ttLib import TTFont
import requests
import re

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 \
(KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}
response = requests.get("https://maoyan.com/cinemas?movieId=248172", headers=headers)

response.raise_for_status()
response.encoding = response.apparent_encoding
html = response.text

# 使用正则表达式找到文字字体文件地址
file_re = re.findall(r'//vfile.meituan.net/colorstone/\w+?.woff', html)
file_url = "http:" + file_re[0]
print(file_url)

# 保存下载的字体文件
get_font_content = requests.get(file_url).content
with open("maoyan.woff","wb") as maoyan:
    maoyan.write(get_font_content)
font2 = TTFont("maoyan.woff")

# 用自己之前保存的字体文件对比
font1 = TTFont("./0c8275bcb0958d2c1e831048f0f0c7562088.woff")
values = list(" .1869023457")
keys = font1['glyf'].keys()
print(keys)
dict1 =dict((k, v)for k, v in zip(keys, values))
print(dict1)

# 空字典,保存新的替换映射关系
dict2 = {}
for key in font2["glyf"].keys():
    for k, v in dict1.items():
# 通过比较 字形定义 填充新的name和num映射关系
        if font1["glyf"][k] == font2["glyf"][key]:
            dict2[key] = v.strip()
            break
print(dict2)

# 将获取到的网页数据中的&#x替换成uni
for i in dict2:
    gly = i.replace('uni', '&#x').lower() + ';'
    if gly in html:
        html = html.replace(gly, dict2[i])

with open("new.txt", "w") as new:
    new.write(html)

大神文章指路:https://www.jianshu.com/p/df9247bc95b4
因为对TTFont不了解,开始实在是看不懂,我是直接把大神字体处理相关的代码复制过来,一步步执行调试理解,此文章只是一篇小白理解后的笔记,希望大家多多包涵。(后续会进行专业术语的完善)

你可能感兴趣的:(爬虫)