一次Python爬虫实战,解决反爬问题!
共 3588字,需浏览 8分钟
·
2022-06-25 09:54
人生苦短,快学Python!
随着互联网的发展,Python的崛起,很多网站经常被外面的爬虫程序骚扰,有什么方法可以阻止爬虫吗?
阻止爬虫也就称之为反爬虫,反爬虫涉及到的技术比较综合,说简单也简单,说复杂也复杂,看具体要做到哪种保护程度了。
![](https://filescdn.proginn.com/d83c02d9f56ac629c002562687324cf0/1ac59504adf35bae5f2b47d316eba81a.webp)
针对于不同的网站,它的反爬措施不一样,常见的反爬有User-Agent、ip代理、cookie认证,js加密等等,与之对应所保护的数据也不一样。比如某宝某猫等电商网站,那么店铺信息用户信息就比较重要了,像是某眼电影网站,它对于电影评分,票房等信息做了反爬处理。
我们今天的采集目标网站是某论坛,当对其文章的文本数据进行采集时,但是发现有字体反爬措施,就是有的文本数据被替换了。
一、需求分析
我们是需要爬取论坛文本数据,如下图所示:
![](https://filescdn.proginn.com/c67c8f2e50aa47db89bcf635f502633b/398ad0de712916e4eb13f30505c3619b.webp)
部分网页源码展示:
![](https://filescdn.proginn.com/7eb6f91cc2fecb117c38ef9d628ae20e/a855019942dbbbea0528bc622f898a8b.webp)
我们发现文本数据是在网页源码里面的。
二、发起请求
import requests
url = "https://club.autohome.com.cn/bbs/thread/665330b6c7146767/80787515-1.html"
header = {"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=header)
html = etree.HTML(r.text)
content = html.xpath("//div[@class='tz-paragraph']//text()")
print(content)
然后得到如下数据(部分数据截图):
![](https://filescdn.proginn.com/e132c3c3f63fe67e77da2609cb0517bd/1b9084cf91580ee6ae25506ef8fadc01.webp)
虽然在网页源码里面存在目标数据,但是通过requests简单请求之后发现有的文字被特殊字符替换掉了,此时再次查看Elenments对应的标签里的数据,如下图所示:
![](https://filescdn.proginn.com/83d592918247f7011adc841912facd40/6456c921102d639d0a3f3f1dae0b6f81.webp)
由图可以发现有的字被替换掉了,所以我们需要找到汉字被替换的方式,然后替换回去。
三、字体替换
我们知道系统字体一般都是xxxx.ttf的文件形式,如下图所示:
![](https://filescdn.proginn.com/7a834ed2cbaa97a7cfd544ca58e8a728/77d0632903d9b4e378ffc55e498cc96d.webp)
通过检查发现该网站中使用的字体对应的是myfont,这个很明显是网站为了反爬设置的自定义的字体:
![](https://filescdn.proginn.com/b7d51a83dfa64e390f508be27618c04a/b7a6afbd858c31bfccc6e967f7927d93.webp)
了解css的伙计应该知道,网页的字体样式放在了style标签里面,如下图所示:
![](https://filescdn.proginn.com/2dae2584785a95eb348481fbfd7d0289/76d15b5f4e4482097a8508c2b7ca6c5c.webp)
然后拿到url对应属性(xxx57..ttf),
//k3.autoimg.cn/g1/M02/D0/99/wKgHFVsUz1eAH_VRAABj9PS-ubk57..ttf
查看后发现是一个字体文件:
![](https://filescdn.proginn.com/64f873af71c698ccadb3a845dea11f08/4f9c90bd23e465460105f96f9fe20dfc.webp)
然后打开字体查看文件,把字体文件拖拽进去,如下图所示:(使用软件为FontCreator,可以查看字体的软件)
如果不想使用软件,可以打开百度字体平台网站,对应页面和软件打开是一样的
![](https://filescdn.proginn.com/3bab21e549f0a3b87374b0590e81acbf/356fd36037bd854e31f3fee989bd72b3.webp)
粗略一看其实发现不了什么,所以我们需要使用fontTools第三方库查看字体文件:
from fontTools.ttLib import TTFont
font = TTFont('./wKgHFVsUz1eAH_VRAABj9PS-ubk57..ttf')
print(font.getGlyphOrder())
结果如下图所示:
![](https://filescdn.proginn.com/43cf3b65a6e788b2ec23cf5d2a634b60/c766e42928d270abffe8e9f1391611dd.webp)
然后我们发现比如在先前的特殊字符表中,
![](https://filescdn.proginn.com/f997553c28cd0da5670a79eac705f7f5/3be400403c96b4fa237075c1ffecc514.webp)
这三个字应该分别对应于,大 、的、一,首先大对应的后缀为edb8,在字体文件的输出的列表中中有一个uniEDB8,对应于第六个,然后再FontCreator软件中刚好对应第六个汉字大,如下图所示:
![](https://filescdn.proginn.com/83f726130227cd08ebbe4156da7cb25d/8406b88fafe39c6bec50d23d7edda9f2.webp)
所以规律就是这样的。
四、数据抓取
1、先把对应的汉字打出来储存在一个列表中;
word_list = ['很', '五', '多', '远', '大', '十', '更', '了', '的', '矮', '不', '少', '九', '三', '八', '一', '右', '坏', '近', '着', '呢','左', '是', '长', '六', '上', '短', '七', '高', '二', '得', '好', '下', '和', '四', '地', '小', '低']
2、把字体文件对应的特殊字符保存到另一个列表中,边进行处理;
font = TTFont('wKgHFVsUz1eAH_VRAABj9PS-ubk57..ttf')
unilist = font.getGlyphOrder()
uni_list = []
for i in unilist[1:]:
s = r'\u' + i[3:]
uni_list.append(s)
print(uni_list)
但是问题出现了,结果如下:
![](https://filescdn.proginn.com/02fdf7c2a5aa82811cbea44b25668ab0/c7d54807e85f3a502d3baf8e118c15c9.webp)
我们发现出现了两个反斜线,所以需要使用eval函数简单修改:
font = TTFont('wKgHFVsUz1eAH_VRAABj9PS-ubk57..ttf')
unilist = font.getGlyphOrder()
# print(unilist)
uni_list = []
for i in unilist[1:]:
# print(i)
s = eval(r"'\u" + i[3:] + "'")
# print(s)
uni_list.append(s)
3、由于之前得到的不完整的文章数据是以一个列表的形式,所以需要把他拼接为字符串,然后使用replace(old,new),进行替换:
# ....前面代码省略
html = etree.HTML(result) # result为请求网页源码
content = html.xpath("//div[@class='tz-paragraph']//text()")
contents = ''.join(content)
4、最后进行替换:
for i in range(len(uni_list)):
contents = contents.replace(uni_list[i], word_list[i])
print(contents)
结果如下,文字替换成功:
![](https://filescdn.proginn.com/381aeb2647871ea63dcb0347059e66b1/ac6448f900ba5129b4559948e3d29f02.webp)
五、小结
通常在爬取一些网站的信息时,偶尔会碰到这样一种情况:网页浏览显示是正常的,用 Python 爬取下来是乱码,F12用开发者模式查看网页源代码也是乱码。这种一般是网站设置了字体反爬。
字体反爬是一种比较常见的反爬方式,因为很多网站的文字信息是比较重要的,像是前面提到的猫眼电影电影票房评分等数据,非常重要,网站维护者当然会把这种数据进行反爬处理,只要好好分析,还是能够抓取到目标数据。
![](https://filescdn.proginn.com/7149ab40f7d7c75bab768f45dd029a8a/5df7ab25f1b761c5e90a66825996f6b4.webp)
![](https://filescdn.proginn.com/2547e06a89fbab6c384b434ef6cd76c5/b3fe91f460123d9750b38bf660bc2b5a.webp)