网站链接:http://www.porters.vip/confusion/movie.html
本文涉及
import requests
import re
import hashlib
from parsel import Selector
from fontTools.ttLib import TTFont
网站的关键数据由其他字符替代
F12里面无法显示可以从网页源码里找,如图
先把其他常规内容搞上,
url = 'http://www.porters.vip/confusion/movie.html'
resp = requests.get(url)
sel = Selector(resp.text)
# 获取其他未加密的电影介绍
movie_data = sel.css("div.movie-brief-container").css("::text").extract()
for i in movie_data:
if "".join(i.split()):
print("".join(i.split()))
在试过css,xpath和bs4后,
发现"\u"型的数据只能用re才能提取
code_re = re.compile('<span class="stonefont">(.*?)</span>')
font_data = code_re.findall(resp.text)
# ['.',
# '.万',
# '.']
接就是解决 字体映射问题
在network里面找到一个font类型数据,
woff(Web Open Font Format)文件
目前最主要的几种网络字体(web font)格式包括WOFF,SVG,EOT,OTF/TTF。
从启动器里看,要先获取movie.css文件,才能提取woff文件
url = 'http://www.porters.vip/confusion/movie.html'
resp = requests.get(url)
sel = Selector(resp.text)
# 提取页面加载的所有css文件路径
css_path = sel.css('link[rel=stylesheet]::attr(href)').extract()
woffs = []
# 拼接movie.css链接,请求获取、拼接woff链接
for c in css_path:
# 拼接css链接
css_url = parse.urljoin(url, c)
css_resp = requests.get(css_url)
# 匹配需要的woff链接
woff_path = re.findall("src:url\('..(.*.woff)'\) format\('woff'\);", css_resp.text)
# 路径存在则执行
if woff_path:
woffs += woff_path
# 请求、下载woff文件
woff_url = 'http://www.porters.vip/confusion' + woffs.pop()
woff = requests.get(woff_url)
with open('movie.woff', 'wb') as f:
f.write(woff.content)
woff文件在线打开方式:FontEditor
使用fontTools库在py中打开
'.'
可以发现字体编码和woff文件的区别 :" &#x",其它字母为大写
安装方式: pip install fontTools
from fontTools.ttLib import TTFont
# 加载字体文件
font = TTFont('movie.woff')
# 转换文件格式为:xml格式(可以通过浏览器打开)
font.saveXML('maoyan.xml')
# 通过字体编码获取字形数据
font['glyf'].glyphs.get(uni_name).data
通过FontEditor手动构建字体编码和所知字体的映射,通过fontTools获取字形数据并md5加密(方便对比,是否为相同字体)
words = font['glyf'].glyphs.get(uni_name).data
md5_code = hashlib.md5(words).hexdigest()
data_dict['hex'] = md5_code
# 效果
base_font = [{"name": "uniEE76", "value": "0", "hex": "fc170db1563e66547e9100cf7784951f"},
{"name": "uniF57B", "value": "1", "hex": "251357942c5160a003eec31c68a06f64"},
{"name": "uniE7DF", "value": "2", "hex": "8a3ab2e9ca7db2b13ce198521010bde4"},
{"name": "uniF19A", "value": "3", "hex": "712e4b5abd0ba2b09aff19be89e75146"},
{"name": "uniF593", "value": "4", "hex": "e5764c45cf9de7f0a4ada6b0370b81a1"},
{"name": "uniEA16", "value": "5", "hex": "c631abb5e408146eb1a17db4113f878f"},
{"name": "uniE339", "value": "6", "hex": "0833d3b4f61f02258217421b4e4bde24"},
{"name": "uniE9C7", "value": "7", "hex": "4aa5ac9a6741107dca4c5dd05176ec4c"},
{"name": "uniEFD4", "value": "8", "hex": "c37e95c05e0dd147b47f3cb1e5ac60d7"},
{"name": "uniE624", "value": "9", "hex": "704362b6e0feb6cd0b1303f10c000f95"}]
代码如下
font_list = []
# 将字体编码串分离,并替换为woff文件一样的字体名称
for i in range(len(font_data)):
# 用字符串将分离的文字重新链接
words = ''
for x in font_data[i].upper().split("&#X"):
for y in x.split("."):
if y:
if chi_re.search(y):
# translate()自定义的解密函数
words+=translate("uni"+y[:-1])
else:
words+=translate("uni"+y)
# 将解密后的字体添加进列表
font_list.append(words)
解密函数的代码
# 解密函数
def translate(code):
for i in base_font:
# 获取字形数据
code_glyf = font["glyf"].glyphs.get(code).data
# 使用hashlib进行md5加密
code_md5 = hashlib.md5(code_glyf).hexdigest()
if code == i.get("name") and code_md5 == i.get("hex"):
return i.get("value")
最终结果
还可以参考这篇文章的思路,
使用selenium截取指定标签位置的数据,配合OCR来识别提取内容
源码: