前面两节我们对猫眼网站进行了爬取,中间,我们会遇到各种反爬虫,包括滑动验证和字体加密等等,今天,我们就对这些反爬虫进行一一破解,实现猫眼网站的全信息爬取!
1、滑动验证:滑动验证类似于极验证(滑块验证,电脑的B站登陆要滑动的哪个),但是原理不一样,目前来说,12306的相关抢票的脚本已经实现了自动加载滑块滑动,但大多数情况还得手动,在这里也是。
破解流程:
1、先尝试着获取数据,如果遇到爬取链接与实际链接不一致,如下图:
即爬取的链接和实际链接不一致时,尤其是出现了类似于:
https://verify.meituan.com/v2/web/general_page?action=spiderindefence&requestCode=350941fd3ea345bd99f8e17f7f99f2f5&platform=1000&adaptor=auto&succCallbackUrl=https%3A%2F%2Foptimus-mtsi.meituan.com%2Foptimus%2FverifyResult%3ForiginUrl%3Dhttp%253A%252F%252Fmaoyan.com%252Ffilms%252F224973
这样的链接,那么就是被反爬虫了,不需要慌,只要点击该链接,
人工拖动该滑块,使之验证成功,那么ip就通过了验证,后面就可以成功爬取了。如下图:
下面是出现滑动验证的操作示意gif
上面,我们将滑动验证说清楚了,下面我们开始对字体加密进行分析:点开猫眼电影的详情,我们在 检查 中发现:
他的评分人数,评分,票房等相关信息都是无法显示的,在源代码中也是类似,那么,我们应该怎么获取相关的数据呢?百度相关的信息,我们发现:
他采用了一种字体加密方式,且是动态的,每次刷新,都要重新载入一种新的字体,如下图:
因此,我们不能再采取网上的那种固定的识别文字的方式,必须采取动态识别方式!这里,我们用到的是OCR本地文字识别,主要通过 tesseract 来识别保存在本地的数字符号。
ocr:光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程
ocr识别流程:
1、先配置好tesseract的环境和训练库,导入相关的包。
2、下载网页的字体文件,保存在本地文件夹。
3、将本地的字体坐标进行读取,并转化成黑白图片。
4、进行ocr识别,并将结果进行转化,将每个坐标对应数字识别代码,如下图
5、找到对应的识别代码之后,我们就可以在源代码中进行替换操作了:
将识别出来的数字与字体代码进行转换。
6、转换成功后进行数据的获取就可以了。
OCR识别的缺点:
1、对训练库的要求比较高,否则识别很容易出错,不准确。
2、识别时间较长,时间花费较大。
但就目前来说,我的识别训练库的精度和速度都还可以。
知道了爬虫步骤与方法,我们就可以编写代码了,代码流程与前两节类似,这里主要讲解一下怎么把字体文件等转化成图片识别。
1、首先,导入下面这些库:
import pytesseract
from PIL import Image
from fontTools.ttLib import TTFont
from matplotlib import pyplot as plt
在OCR识别之前,记得先下好字体文件,再进行后面操作。
2、导入字体文件,获取到数字的坐标表示区:
font = TTFont(woff_file)
font_name = font.getGlyphOrder()[2:] #获取到字符的uni码
zb = [font['glyf'][i].coordinates for i in font_name
获取到每个字体的坐标信息,后面我们就可以根据字体坐标进行绘图,并将字体编码与具体数字对应上;部分代码如下:
def deal_font(font):
font_name = font.getGlyphOrder()[2:]
zb = [font['glyf'][i].coordinates for i in font_name]
fig, ax = plt.subplots()
for index, one in enumerate(zb):
x, y = [i[0] for i in one], [i[1] for i in one]
plt.plot(x, y)
x_n = [i + np.max(x) + 100 for i in x]
plt.plot(x_n, y)
plt.fill(x, y, 'black')
plt.fill(x_n, y, 'black')
# 去边框
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
# 去刻度
plt.axis('off')
plt.fill(x, y, 'black')
plt.savefig('images/%s.png' % index)
plt.close()
path = 'images/'
num = []
# 灰度、二值化
for one in os.listdir(path):
img = Image.open(path + one)
imgry = img.convert("L")
threshold = 140
table = []
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
out = imgry.point(table, '1')
out.save(path + one)
text = pytesseract.image_to_string(out, lang="amt")
num.append(text[0])
# 字名与数字
name_num = {font_name[i]: num[i] for i in range(len(font_name))}
return name_num
全部代码在我的公众号里,回复 猫眼 就可以获取到,我的公众号名字是:
python学习号
当然,也可以在这里 下载 ,只是要c币。
欢迎大家关注。一个python学习者,将其学到的分享出来。