人生苦短,快学Python!
大家在使用Python爬虫时,经常会遇到各种反爬问题。今天就以猫眼电影为例,看看如何解决其中的 字体反爬 !
由于对于一部电影来说,它的票房和评分数据是非常重要的,所以网站开发人员对它进行了保护,也就是字体反爬,今天的目标是破解猫眼电影网站的字体反爬。
一、需求分析
我们是需要爬取论坛文本数据,如下图所示:
部分网页源码展示:
我们发现数据是不在网页源码里面,而是以一种特殊的字符存在的。
二、发起请求
import requests
url = "https://maoyan.com/films/1298542"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"
}
r = requests.get(url,headers=headers)
print(r.text)
然后得到如下数据(部分数据截图):
和网页源码里面的数据一样,通过requests简单请求之后发现评分,票房数据被特殊字符替换掉了,此时再次查看Elenments对应的标签里的数据,如下图所示:
由图可以发现有的字被替换掉了,所以我们需要找到数字被替换的方式(规律),然后替换回去。
三、替换规律
通过上面分可知,该网站中使用的字体对应的是stonefont,它是该网站为了反爬设置的自定义字体,它一定存在于style(样式)标签里面:
然后拿到url对应属性(xxx57..woff),它是不同于.ttf的字体文件,但是同样可以使用FontCreator打开:
//k3.autoimg.cn/g1/M02/D0/99/wKgHFVsUz1eAH_VRAABj9PS-ubk57..ttf
注意:如果该属性打不开文件,可以在属性前加上 https://maoyan.com
查看后发现是一个字体文件:
然后打开字体查看文件,把字体文件拖拽进去,如下图所示:(使用软件为FontCreator,可以查看字体的软件)
如果不想使用软件,可以打开百度字体平台网站,对应页面和软件打开是一样的
粗略一看其实发现不了什么,所以我们需要使用fontTools第三方库
查看字体文件:
from fontTools.ttLib import TTFont
font = TTFont('./f0a30a4dda64b4f8f344858115f54fc92296 (1).woff')
print(font.getGlyphOrder())
结果如下图所示:
['glyph00000', 'x', 'uniF4EF', 'uniF848', 'uniF88A', 'uniE7A1', 'uniE343', 'uniE137', 'uniF489', 'uniE5E2', 'uniF19B', 'uniE8CD']
然后我们发现比如在先前的网页源码中发现的,
. # 对应网页中的9.2
然后由此查看后缀,9----e7a1,在上图中
四、数据抓取
1、导包,我们使用re第三方库解析
import requests
import re
from fontTools.ttLib import TTFont
2、定制一个类(Maoyan),以及初始化属性设置:
class MaoYan(object):
def __init__(self):
self.url = 'https://maoyan.com/films/1298542'
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"
}
self.font = TTFont('./f0a30a4dda64b4f8f344858115f54fc92296 (1).woff')
self.numList = ['6', '3', '7', '9', '8', '0', '4', '2', '5']
3、相关方法设置
发送请求获取相应
def get_html(self, url):
response = requests.get(url, headers=self.headers)
return response.content
处理字体文件
def getNewList(self):
newList = []
glyList = self.font.getGlyphOrder()[2:] # 前两个数据是没有用的,剔除
for gly in glyList:
m = gly.replace('uni', '&#x').lower() + ';' # replace字符替换
newList.append(m)
return newList
解析数据
def parseData(self, data):
for i in self.getNewList():
if i in data:
print(self.numList[self.getNewList().index(i)])
data = data.replace(i, self.numList[self.getNewList().index(i)])
return data
正则匹配以及最终输出
def start_crawl(self):
html = self.get_html(self.url).decode('utf-8')
# 正则匹配星级
star = re.findall(r'<span class="index-left info-num ">\s+<span class="stonefont">(.*?)</span>\s+</span>', html)[0]
print(star)
star = self.parseData(star)
print('用户评分: %s 星' % star)
4、最后运行:
if __name__ == '__main__':
maoyan = MaoYan()
maoyan.start_crawl()
结果如下,文字替换成功:
由于票房数据和这个评分有着异曲同工之妙,所以这里不再赘述,感兴趣的小伙伴可以去试一下。
五、小结
通常在2爬取一些网站的信息时,偶尔会碰到这样一种情况:网页浏览显示是正常的,用 Python 爬取下来是乱码,F12用开发者模式查看网页源代码也是乱码。这种一般是网站设置了字体反爬。字体反爬是一种比较常见的反爬方式,因为很多网站的文字信息是比较重要的,像是前面提到的猫眼电影电影票房评分等数据,非常重要,网站维护者当然会把这种数据进行反爬处理,只要好好分析,还是能够抓取到目标数据。
注意点:
- 字符匹配以及替换,还有正则表达式的书写规范
- 猫眼验证,当用户频繁的发起请求时,他会有一个验证,滑块验证,这个时候最好使用selenium手动操作一下,然后就可以正常的请求数据。
我们的文章到此就结束啦,如果你喜欢今天的Python 实战教程,请持续关注Python实用宝典。
原创不易,希望你能在下面点个赞支持我继续创作,谢谢!
Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典