起点 字数 反 反爬虫
如何 获取这5个数字呢???
字数对应的源代码如下:
说明一下:
这是起点的一种反爬措施,起点有自己的数字库,在每次打开网页或刷新网页时,这一串数字都会改变,想要去和数字一 一对应都不可能,但是这一串数字和与之解析的数字库是对应的,只要找到对应的数字库,解析一下,就可以形成映射关系:
提取 5串 字符串和对应的数字库
注意:不要用解析器去解析,直接用正则表达式去提取:
response = requests.get(url).text
pattern = re.compile('</style><span.*?>(.*?)</span>',re.S)
# 获取当前页面所有被字数字符
numberlist = re.findall(pattern, response)
# 获取当前包含字体文件链接的文本
reg = re.compile('<style>(.*?)\s*</style>',re.S)
fonturl = re.findall(reg,response)[0]
# 通过正则获取当前页面字体数字库的链接
url = re.search('woff.*?url.*?\'(.+?)\'.*?truetype', fonturl).group(1)
numberlist :得到5个数字对应的字符列表
url :得到数字库的链接
解析数字库:
ontTools是一个用Python编写的用于操作字体的库。该项目包括TTX工具,可以将TrueType和OpenType字体转换为XML文本格式,也称为TTX。它支持TrueType,OpenType,AFM以及Type 1和某些Mac特定格式。
from fontTools.ttLib import TTFont
from io import BytesIO #StringIO就是在内存中创建的file-like Object,常用作临时缓冲
def get_font(url):
time.sleep(1)
response = requests.get(url)
font = TTFont(BytesIO(response.content))
cmap = font.getBestCmap() #返回unicode cmap字典可用的字体
font.close()
return cmap
可以得到一串数字和英文单词相对应的字典:
cmap: { 100543: ‘seven’, 100545: ‘period’, 100546: ‘nine’, 100547: ‘zero’,
100548: ‘five’, 100549: ‘one’, 100550: ‘six’, 100551: ‘eight’,
100552: ‘four’, 100553: ‘two’, 100554: ‘three’
}
只要新建一个新的英语与数字对应的字典,:
WORD_MAP = {‘zero’: ‘0’, ‘one’: ‘1’, ‘two’: ‘2’, ‘three’: ‘3’,
‘four’: ‘4’, ‘five’: ‘5’, ‘six’: ‘6’, ‘seven’: ‘7’,
‘eight’: ‘8’, ‘nine’: ‘9’, ‘period’: ‘.’}
形成映射:就可以轻松解决字数问题
附加代码:
import requests, json, time, re
from pyquery import PyQuery as pq
from fontTools.ttLib import TTFont
from io import BytesIO
import random
import time
def get_font(url):
time.sleep(1)
response = requests.get(url)
font = TTFont(BytesIO(response.content))
cmap = font.getBestCmap()
font.close()
return cmap
def get_encode(cmap, values):
WORD_MAP = {'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5', 'six': '6', 'seven': '7',
'eight': '8', 'nine': '9', 'period': '.'}
word_count = ''
list = values.split(';')
list.pop(-1)
for value in list:
value = value[2:]
key = cmap[int(value)]
word_count += WORD_MAP[key]
return word_count
def get_nums(url):
# 获取当前页面的html
time.sleep(1)
response = requests.get(url).text
#doc = pq(response)
pattern = re.compile('</style><span.*?>(.*?)</span>',re.S)
# 获取当前页面所有被字数字符
numberlist = re.findall(pattern, response)
# 获取当前包含字体文件链接的文本
reg = re.compile('<style>(.*?)\s*</style>',re.S)
fonturl = re.findall(reg,response)[0]
# 通过正则获取当前页面字体文件链接
url = re.search('woff.*?url.*?\'(.+?)\'.*?truetype', fonturl).group(1)
cmap = get_font(url)
print('cmap:',cmap)
num_list = []
for a in numberlist:
num_list.append(get_encode(cmap, a))
return num_list
def main(url): # 为外界提供一可以调取的接口
num_list = get_nums(url)
return num_list
if __name__=='__main__':
url='https://book.qidian.com/info/1115277'
num_list = main(url)
print(num_list)
结果: