58同城的其中一个反爬措施是字体反爬,如下图:
在租房详情页里面的大部分数字信息都设置了不同的字体。
1.解析出网页的字体文件
在网页中查找@font-face的部分,如下图:
使用以下代码将字体文件写入本地:
import base64
font_face = ""
b = base64.b64decode(font_face)
with open('ft.ttf', 'wb') as f:
f.write(b)
在将字体文件解析为xml:
from fontTools.ttLib import TTFont
font = TTFont('ft.ttf')
font.saveXML('ft.xml')
xml内容结构如下:
非Unicode显示
这是下载下的html文件中价格部分,其中价格被我标记了实际数字价格。
查找xml文件:
在xml的部分中,name与code对应,name与code对应与数字的关系是name的最后一位-1=实际数字----->网页中的code。
先将解析的文字使用Unicode加密,在对应解析出的xml文件就可以得到实际的数字了。
代码如下:
import base64
from lxml import etree
from fontTools.ttLib import TTFont
import requests
import re
import functools
# 综合思想是
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3573.0 Safari/537.36"
}
response = requests.get(url="https://bj.58.com/zufang/36724645212057x.shtml", headers=headers)
text = response.text
# print(text)
price = etree.HTML(text)
price = price.xpath('//*[@class="f36 strongbox"]/text()')[0]
# 将网页中的乱码字符变为Unicode
data = str(price.encode('unicode_escape')).strip("'").split(r'\\u')[1:]
html = re.search(r'.*?<style>@font-face.*?base64,(.*?) format.*</style>.*', text, re.S)
html = html.group(1).replace("')", '')
b = base64.b64decode(html)
with open('ft.ttf', 'wb') as f:
f.write(b)
font = TTFont('ft.ttf')
font.saveXML('ft.xml')
with open('ft.xml', 'rb') as f:
x = f.read()
xml = etree.XML(x)
codes = []
names = []
for i in xml.xpath('//cmap/cmap_format_4[1]/map'):
code = i.xpath("@code")[0][2:]
name = i.xpath("@name")[0][-2:]
codes.append(code)
names.append(int(name)-1)
# 将xml中的code与name连接为一个字典型
dic_data = dict(zip(codes, names))
result_list = [dic_data[i] for i in data]
# 将列表中的数字变为一个整数字
result = functools.reduce(lambda x, y: x * 10 + y, result_list)
print(result)
评论列表
已有0条评论