字体反爬之猫眼票房爬虫python

编译环境:win10+python3.6+pycharm2017

目标:获取猫眼票房的电影名称和票房数据

目标网址:https://piaofang.maoyan.com/?ver=normal

网址页面:

大概思路:猫眼票房获取完整HTML的话只需要添加user-agent即可,但是HTML中我们可以发现通过beautifulsoup库对HTML进行解析之后的得到的电影名称是对的但是里面的数据如上映总票房却并不是我们所看到的那样,而是用一些特定的字符代替的,这也就是猫眼票房的难点,所以我们首先要做的就是对这些字符进行解析,得到字符和数字的对应关系。

检察源代码我们可以看到数字对应的字符,因为猫眼电影的字体是有多套的,所以我们直接去记录数字和字符的对应关系是没有多大意义的。https://i-blog.csdnimg.cn/blog_migrate/ee97cbbf4011ae7963f019fe9645ffc9.png

在源代码里搜索font我们可以看到网页里的字体是通过base64编码的,我们可以通过正则获取这些编码,然后通过base64写入到本地文件,这样我们就可以获取当前网页的ttf字体文件。

https://i-blog.csdnimg.cn/blog_migrate/a94b0e3871042395d27e2508c45e19c9.png

s=re.findall(r'@font-face.*?base64,(.*?)\)',html)
# print(s[0])
b=base64.b64decode(s[0])
with open("e.ttf","wb") as f:
    f.write(b)

fontcreator下载地址:http://fastsoft.onlinedown.net/down/FontCreatorSetup_88758.zip直接点击链接即可下载

我们可以通过fontcreator来查看ttf字体文件中字符和数字的对应关系

https://i-blog.csdnimg.cn/blog_migrate/ce365801e795dcfc25cceb3f9fcc6ade.png

因为网页有多套字体文件所以我们单纯的记录这个对应关系是不能实现我们的目的的,这里就需要引入一个字体库fonttools,安装方法也很简单,直接pip install fonttools 即可,通过fonttools我们可以对字体文件做一些处理,我们首先可以通过fonttools把字体文件转化为XML格式,这样我们就可以通过浏览器查看里面的内容

from fontTools.ttLib import TTFont
font=TTFont("c.ttf")
font.saveXML("d.xml")

通过浏览器打开XML文件我们可以看到ttf字体里面的内容.

https://i-blog.csdnimg.cn/blog_migrate/38329bf5808bf9ac3e54ec155b085ca6.png

在XML中我们可以看到glyphorder里包含了对应的编码信息我们可以通过fonttools读取glyphorder即可获取对应的编码信息,往下翻到glyphname,我们可以看到每一个编码都有对应的x和y坐标仔细分析可以得出这些坐标应该就是用来绘制数字的形状的,那么这个对象就是唯一的,所以我们可以通过比对这个对象来辨别数字,具体思路是保存一个字体文件1读取其中的编码信息,创建一个编码和数字相对应的字典,读取对象信息作为比对,然后爬取网页的时候获取当前网页的字体文件,获取当前字体文件的编码信息和对象信息,通过比对对象信息找到这个对象对应字体2的编码和字典中对应的数字,然后调用str.replace方法把HTML中的编码转换成相对应的数字,然后就可以正常的对网页进行分析了。

源代码如下:

import base64
from fontTools.ttLib import TTFont
import re
import requests
from bs4 import BeautifulSoup


dict={"uniF839":"5",
      "uniE9DE":"9",
      "uniE03E":"8",
      "uniF541":"4",
      "uniE565":"2",
      "uniF51A":"3",
      "uniE099":"0",
      "uniF2B6":"6",
      "uniE4E2":"1",
      "uniED40":"7",
      }
font1=TTFont("c.ttf")
uni_list1=font1.getGlyphOrder()[2:]
obj_list1=font1.getGlyphNames()[1:-1]

def get_text(url):
    try:
        headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'}
        r=requests.get(url,headers=headers) 
        print(r.status_code)
        r.raise_for_status()
        r.encoding=r.apparent_encoding
        # print(r.text)
        return r.text
    except:
        return "11111"
def get_correct_html(html):

    s=re.findall(r'@font-face.*?base64,(.*?)\)',html)
    # print(s[0])
    b=base64.b64decode(s[0])
    with open("e.ttf","wb") as f:
        f.write(b)

    font2=TTFont("e.ttf")
    uni_list2=font2.getGlyphOrder()[2:]
    obj_list2=font2.getGlyphNames()[1:-1]
    for c2 in uni_list2:
        obj2=font2["glyf"][c2]
        for c1 in uni_list1:
            obj1=font1["glyf"][c1]
            if obj1==obj2:
                code_lower="&#x"+c2[3:].lower()+";"
                html=html.replace(code_lower,dict[c1])
                print(c2,dict[c1])
    return html
def get_info(html):
    soup = BeautifulSoup(html, "lxml")
    titles = soup.select("#ticket_tbody > ul> li.c1 > b")
    name = []
    for i in titles:
        name.append(i.string)
    nums = soup.select("#ticket_tbody > ul> li.c1 > em > i")
    pf = []
    for t in nums:
        pf.append(t.string)
    for ii in range(len(pf)):
        print(name[ii], pf[ii])




if __name__=="__main__":
    url="https://piaofang.maoyan.com/?ver=normal"
    html=get_text(url)
    html=get_correct_html(html)
    get_info(html)



 


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值