大家好,关于怎么把所有网站的源码分享脱落很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于怎么把网站源码扒下来的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!
这几天爬取58租房信息的时候意外发现了它是一个字体反爬的网站,所谓的字体反爬就是网站将一些关键字替换为网站自己的字体,这样在网页上字体会正常显示,但是当爬取下来的时候,经过字体加密的字符都是乱码的,根本无法查看
如图所示:
可以看到,2390元/月在页面上是正常显示的,但是,当我们打开查看器查看的时候……
好端端的2390就变成了不知道什么字符…….
这就是网站使用了字体反爬机制,网站有自己的一套字体,只有在它的页面上才会正常显示,否则就是一串乱码,毫无价值。那么遇到这种问题该怎么解决,在经历几天的摸索之后终于将正确的信息抓取了下来。
首先,我们查看网页的源码,就是下面这样的
这是网页源码中一串base64的字符串,它就是网站的字体文件,很难想象一串base64的字符串就是它的字体文件。
我们将这一串base64的字符串复制下来,将它解码并保存成一个字体文件
importbase64
font_face=”AAEAAAALAIAAAwAwR1NVQiCLJXoAAAE4AAAAVE9TLzL4XQjtAAABjAAAAFZjbWFwq8N/ZAAAAhAAAAIuZ2x5ZuWIN0cAAARYAAADdGhlYWQTcnjtAAAA4AAAADZoaGVhCtADIwAAALwAAAAkaG10eC7qAAAAAAHkAAAALGxvY2ED7gSyAAAEQAAAABhtYXhwARgANgAAARgAAAAgbmFtZTd6VP8AAAfMAAACanBvc3QFRAYqAAAKOAAAAEUAAQAABmb+ZgAABLEAAAAABGgAAQAAAAAAAAAAAAAAAAAAAAsAAQAAAAEAAOv6p7JfDzz1AAsIAAAAAADX9ZbuAAAAANf1lu4AAP/mBGgGLgAAAAgAAgAAAAAAAAABAAAACwAqAAMAAAAAAAIAAAAKAAoAAAD/AAAAAAAAAAEAAAAKADAAPgACREZMVAAObGF0bgAaAAQAAAAAAAAAAQAAAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAEERAGQAAUAAAUTBZkAAAEeBRMFmQAAA9cAZAIQAAACAAUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBmRWQAQJR2n6UGZv5mALgGZgGaAAAAAQAAAAAAAAAAAAAEsQAABLEAAASxAAAEsQAABLEAAASxAAAEsQAABLEAAASxAAAEsQA”
font.saveXML(‘test.xml’)
print(font.keys())
a=font[‘cmap’].tables[2].ttFont.getGlyphOrder()
b=font[‘cmap’].tables[2].ttFont.getReverseGlyphMap()
c=font[‘cmap’].tables[2].ttFont.tables[‘cmap’].tables[1].cmap
print(“ppp:::::”,a)
print(“ddd:::::”,b)
print(“ddd:::::”,c)
输出的结果
这里最后一行输出的就是网页上显示的字符串与camp标签中的name值的对应关系。那么网页上显示的0x958f这种字符串究竟是什么意思呢,它其实是一个十六进制的数字,将这个十六进制的数字转换成十进制(int(“0x985f”,16)),得到的值就是最后一行输出的键,那么这个键对应的值就是第二行输出的键,第二行的值就是本来的数据,这样一来,在抓取每一页之前,先抓取到它这一页的字体文件,进行分析,得到对应关系,不就能获取到原始的数据了嘛。
ps:需要注意的是,使用fontCreator解析时发现数字对应关系前面有一个空值,所以实际解析到的对应的数字需要减1才能得到正确的值。
代码思路:1.在爬取每一页数据之前,先获取到源码中的base64的字符串,解码,保存成字体文件2.生成对应关系的字典3.抓取到页面的乱码文字,解码成16进制的数字3.将十六进制的数字转为十进制,判断字典中是否有这个键,如果有,则解析为原本的数字,如果没有,则说明这个文字没有进行机密处理,保存原来的文字即可。4.完成全部加密文字的替换得到正确的数据。
实际代码:
importre
importlxml.html
importbase64
fromfontTools.ttLibimportTTFont
importrequests
importrandom
importsqlite3
db=sqlite3.connect(“58.db”)
cursor=db.cursor()
UA=[
“Mozilla/5.0(Macintosh;U;IntelMacOSX10_6_8;en-us)AppleWebKit/534.50(KHTML,likeGecko)Version/5.1Safari/534.50”,
“Mozilla/5.0(Windows;U;WindowsNT6.1;en-us)AppleWebKit/534.50(KHTML,likeGecko)Version/5.1Safari/534.50”,
“Mozilla/5.0(Macintosh;IntelMacOSX10.6;rv:2.0.1)Gecko/20100101Firefox/4.0.1”,
“Mozilla/5.0(WindowsNT6.1;rv:2.0.1)Gecko/20100101Firefox/4.0.1”
]
headers={
“User-Agent”:random.choice(UA)
}
defresp(i):
base_url=”https://tj.58.com/pinpaigongyu/pn/{}/”
response=requests.get(base_url.format(i),headers=headers)
print(“正在下载:”,response.url)
returnresponse
defget_base64_str(response):
base_font=re.compile(“base64,(.*?)\\'”)
base64_str=re.search(base_font,response.text).group().split(‘,’)[1].split(‘\\”)[0]
returnbase64_str
defmake_font_file(base64_str):
b=base64.b64decode(base64_str)
withopen(“58.ttf”,”wb”)asf:
f.write(b)
defmake_dict():
font=TTFont(’58.ttf’)
b=font[‘cmap’].tables[2].ttFont.getReverseGlyphMap()页面的十六进制数对应的编码
returnb,c
defparse_title(text):
s=””
title_re=re.compile(“\\s”)
html=lxml.html.fromstring(text)
title=html.xpath(‘//div[@class=”desstrongbox”]/h2/text()’)[0]
title=re.sub(title_re,”,title)
foriintitle:
encode_str=str(i.encode(“unicode-escape”)).split(r’\\\\u’)[-1].replace(‘\\”,”).replace(r’b(‘,”).strip()
num,code=make_dict()
iflen(encode_str)!=4:
i=i
elifint(encode_str,16)notincode:
i=i
else:
i=str(num
]-1)
s+=i
returns
defparse_price(text):
s=””
html=lxml.html.fromstring(text)
price_code=html.xpath(‘//span[@class=”strongbox”]/b/text()’)[0]
price_code=price_code.strip().replace(‘\\r\\n’,”).replace(”,”)
price_encode_str=str(price_code.encode(“unicode-escape”)).split(‘\\”)[1].split(‘-‘)
iflen(price_encode_str)>1:
s1=””
s2=””
encode_list1=price_encode_str[0].split(r”\\\\u”)[1:]
encode_list2=price_encode_str[1].split(r”\\\\u”)[1:]
foriinencode_list1:
price=int(i,16)
num,code=make_dict()
s1+=str(num
]-1)
foriinencode_list2:
price=int(i,16)
num,code=make_dict()
s2+=str(num
]-1)
s=s1+’-‘+s2
else:
str_list=price_encode_str[0].split(r’\\\\u’)[1:]
foriinstr_list:
price=int(i,16)
num,code=make_dict()
s+=str(num
]-1)
returns
defparse_room(text):
s=””
html=lxml.html.fromstring(text)
p_rooms=html.xpath(‘//p[@class=”room”]/text()’)[0]
room_re=re.compile(‘[\\s]’)
room_re1=re.compile(r'[m2]’)
room_re2=re.compile(r’/’)
rooms=re.sub(room_re,”,p_rooms)
rooms=re.sub(room_re1,”平米”,rooms)
rooms=re.sub(room_re2,”至”,rooms)
foriinrooms:
encode_str=str(i.encode(“unicode-escape”)).split(r’\\\\u’)[-1].replace(‘\\”,”).replace(r’b/’,”).strip()
#print(encode_str)
num,code=make_dict()
iflen(encode_str)!=4:
i=i
elifint(encode_str,16)notincode:
i=i
else:
i=str(num
]-1)
s+=i
returns
defparse_dist(text):
s=””
html=lxml.html.fromstring(text)
p_dist_re=re.compile(‘\\skm’)
try:
p_dist=html.xpath(‘//p[@class=”dist”]//text()’)[1]
p_dist=”.join(p_dist).replace(”,”)
p_dist=re.sub(p_dist_re,’千米’,p_dist)
foriinp_dist:
encode_str=str(i.encode(“unicode-escape”)).split(r’\\\\u’)[-1].replace(‘\\”,”).replace(r’\\\\r’,”).replace(r’\\\\n’,”).replace(r’b.’,”).strip()
num,code=make_dict()
iflen(encode_str)!=4:
i=i
elifint(encode_str,16)notincode:
i=i
else:
i=str(num
]-1)
s+=i
dist=s
except:
dist=”暂无”
returndist
defshort_rent(text):
html=lxml.html.fromstring(text)
try:
rent=html.xpath(‘//p[@class=”room”]/b/text()’)[0]
except:
rent=”不可短租”
returnrent
defparse_li(response):
li_re=re.compile(‘<lilogr([\\s\\S]*?)</li>’)
li_list=re.findall(li_re,response.text)
returnli_list
defparse_target(text):
html=lxml.html.fromstring(text)
try:
target=html.xpath(‘//p[@class=”spec”]/span/text()’)
target=’,’.join(target)
except:
target=”暂无”
returntarget
if__name__==’__main__’:
foriinrange(1,171):
response=resp(i)
base64_str=get_base64_str(response)
make_font_file(base64_str)
make_dict()
li_list=parse_li(response)
foriinli_list:
title=parse_title(i)
price=parse_price(i)
room=parse_room(i)
dist=parse_dist(i)
rent=short_rent(i)
target=parse_target(i)
city=”天津”
cursor.execute(“insertintohome(title,price,room,dist,rent,target,city)values(?,?,?,?,?,?,?)”,[title,price,room,dist,rent,target,city])
db.commit()
由于我的正则表达式功底有点差,所以这里的正则表达式都用的是比较low的……….
但是数据爬下来了,而且没有问题
一次愉快的破解字体反爬机制就到此结束了
———————
作者:在杭州
来源:CSDN
原文:https://blog.csdn.net/WanYu_Lss/article/details/83447174
版权声明:本文为博主原创文章,转载请附上博文链接!
文章分享结束,怎么把所有网站的源码分享脱落和怎么把网站源码扒下来的答案你都知道了吗?欢迎再次光临本站哦!
