最近需要抓取知网的文献资料,但是在打开文章时,会重定向到一个验证网址,并弹出一个滑块,让你进行验证。
打开控制台,抓取两个接口
获取滑块信息
https://kns.cnki.net/verify-api/get
这个接口会返回滑块图片信息(jigsawImageBase64、originalImageBase64),以及token、secretKey
base64 就是两张图片,一张是大图,一张是小图。
token 需要提交给验证接口
secretKey 参与坐标加密
验证滑块信息
https://kns.cnki.net/verify-api/web/check
这个接口需要提交一些参数,最重要的是 pointJson
这个是由坐标信息:{"x":0,"y":5} 和 secretKey 进行加密之后的结果
识别小图在大图中的位置
可以使用 opencv-python
包, 附带函数:
''' 识别滑块位置 '''
def find_template_position(self,big_img_base64, small_img_base64):
# 将 Base64 字符串解码为图像数据
def base64_to_image(base64_str):
# 去掉可能的头部信息(如 "data:image/png;base64,")
if "," in base64_str:
base64_str = base64_str.split(",")[1]
# 解码为字节数据
img_bytes = base64.b64decode(base64_str)
# 转换为 numpy 数组
img_array = np.frombuffer(img_bytes, dtype=np.uint8)
# 用 OpenCV 解码图像
img = cv2.imdecode(img_array, cv2.IMREAD_GRAYSCALE)
return img
# 解码 Base64 并转为灰度图
big_img = base64_to_image(big_img_base64)
small_img = base64_to_image(small_img_base64)
# Canny边缘检测
edges_big = cv2.Canny(big_img, 50, 150)
edges_small = cv2.Canny(small_img, 50, 150)
# 轮廓匹配
res = cv2.matchTemplate(edges_big, edges_small, cv2.TM_CCOEFF_NORMED)
_, _, _, max_loc = cv2.minMaxLoc(res)
return max_loc
生成客户端ID
在获取滑块信息时,要提交一个 clientUid
参数,但是好像使用固定的也没关系
''' 生成客户端ID '''
def generate_clientUid(self):
hex_digits = '0123456789abcdef'
uuid_chars = []
# 生成 32 个随机十六进制字符(无分隔符)
for _ in range(32):
uuid_chars.append(random.choice(hex_digits))
# 固定版本号和变体标识位(符合 UUID v4 规范)
uuid_chars[12] = '4' # UUID 版本位
uuid_chars[16] = hex_digits[(int(uuid_chars[16], 16) & 0x3 | 0x8)] # 变体位
return ''.join(uuid_chars)
pointJson 加密方式
point = {"x": x + 3, "y": 5} # x轴+3 y轴固定为5
# 转为json格式并进行加密
json_str = json.dumps(point, separators=(',', ':'))
pointJson = self.encrypt_point_json(json_str, verify_data['secretKey'])
print(f"识别滑块坐标:{point} 坐标加密:{pointJson}")
pointJson 加密函数
验证成功
在滑块验证成功后,需要携带 captchaId
访问文章,就可以免验证了。
returnUrl = check_reslut_data.get("returnUrl")
returnUrl = f"{returnUrl}&captchaId={check_reslut_data['captchaId']}"
行为异常
如果出现行为异常,也需要进行滑块验证,但是这个滑块是单机的,也就是说可以忽略。
抓取页面的v-value ,访问下面这个地址,就会返回一个可以访问的文章地址。
本文仅学习研究记录。
支持一下