内容简介:最近一直在为找工作烦恼,刚好遇到一家公司要求我先做几道反爬虫的题,看了之后觉得自己还挺菜的,不过也过了几关,刚好遇到一个之前没遇到过的反爬虫手段 — 字体反爬题目要求:就这,从图里能看出
最近一直在为找工作烦恼,刚好遇到一家公司要求我先做几道反爬虫的题,看了之后觉得自己还挺菜的,不过也过了几关,刚好遇到一个之前没遇到过的反爬虫手段 — 字体反爬
正文
一、站点分析
题目要求: 这里有一个网站,分了1000页,求所有数字的和。注意,是人看到的数字,不是网页源码中的数字哦~
就这,从图里能看出 数字 的字体有些不同,看看源码是什么样的
可以看到,源码里的内容和网页上显示的内容根本不一样,当然,题目也说了;那么这是怎么回事呢,切换到 Network 栏,刷新网页看看请求
可以看到,这里有两个字体请求,选择后可以预览字体
很明显,数字有点问题,被改过了,上面那一个请求的字体文件是正常的字体(下图),可以拿来做比较,以便于我们分析
一般来说字体文件的数字就是这样的顺序 1 2 3 4 5 6 7 8 9 0 ,以这个为模板,被 修改后的字体 中的数字 2 处与 正常字体 中 9 的位置。回到网页源码和内容,网页上显示 274 ,实际源码中是 920 (下图),用上面的字体做替换我们会发现, 2 在被 修改过的字体 中的位置是 8 ,而 8 在 正常字体 中就是 8,由此可得结论:我们只要把这 修改过的字体 搞到手,然后把网页上显示的内容逐个拆分为单个数字,然后从字体中匹配出正常字体就行了,不过,根据题目,我们需要反着来做,也就是从源码入手,获取到内容后拆分为单个字体,接着从字体中获取网页上显示的内容。
我自己写的时候都觉得头晕,直接写代码,这样能更好的表达我要说什么,不过,这里要说一点,据我分析,这个网页有1000页,每一页的字体都是不同的,就需要每获取一个网页就得重新获取被修改的字体。我这里用的是 scrapy 框架。
二、代码阶段
首先新建一个 scrapy 项目
➜ ~ scrapy startproject glidedsky
New Scrapy project 'glidedsky', using template directory '/usr/local/lib/python3.7/site-packages/scrapy/templates/project', created in:
/Users/zhonglizhen/glidedsky
You can start your first spider with:
cd glidedsky
scrapy genspider example example.com
➜ ~
复制代码
接着创建一个 Spider
➜ ~ cd glidedsky ➜ ~ glidedsky scrapy genspider glidedsky glidesky.com Cannot create a spider with the same name as your project ➜ ~ glidedsky 复制代码
scrapy 怎么用我就不说了,直接看代码
# glidedsky.py
import scrapy
import requests
import re
from glidedsky.items import GlidedskyItem
from glidedsky.spiders.config import *
class GlidedskySpider(scrapy.Spider):
name = 'glidedsky'
start_urls = ['http://glidedsky.com/level/web/crawler-font-puzzle-1']
def __int__(self):
self.headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
}
def request(self, url, callback):
request = scrapy.Request(url=url, callback=callback)
# 添加 cookies
request.cookies['XSRF-TOKEN'] = XSRF_TOKEN
request.cookies['glidedsky_session'] = glidedsky_session
# 添加 headers
request.headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
return request
def start_requests(self):
for i, url in enumerate(self.start_urls):
yield self.request(url, self.parse_item)
def parse_item(self, response):
"""
解析numbers
:param response:
:return:
"""
body = response.css('html').get()
self.save_font(body)
col_md_nums = response.css('.col-md-1::text').extract()
items = GlidedskyItem()
for col_md_num in col_md_nums:
# 这里获取到的是源码中的内容,并不是我们在网页上看到的内容,需要去数据管道进一步处理
items['numbers'] = col_md_num.replace('\n', '').replace(' ', '')
yield items
# 获取下一页
next = response.xpath('//li/a[@rel="next"]')
# 判断是否有下一页
if len(next) > 0:
next_page = next[0].attrib['href']
# response.urljoin 可以帮我们构造下一页的链接
url = response.urljoin(next_page)
yield self.request(url=url, callback=self.parse_item)
def save_font(self, body):
"""
保存字体到本地
:param response: 网页源代码
:return:
"""
pattern = r'src:.url\("(.*?)"\).format\("woff"\)'
woff_font_url = re.findall(pattern, body, re.S)
print(woff_font_url)
resp = requests.get(woff_font_url[0], headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'})
with open(WOFF_FONT_FILENAME, 'wb') as f:
f.write(resp.content)
复制代码
在解析字体之前先分析一下字体文件的内容,因为这里面有坑(起码我这个站点是这样),下载好字体后,用 python 的 fontTools 库把 woff格式 转成 xml文件 ,然后打开;或者用 font-creator 直接打开,但是这个 工具 只有windows上有,所以这里就用第一种方法。
1、先把 woff格式 转成 xml格式 文件
import requests
from fontTools.ttLib import TTFont
# 先把字体文件下载下来
url = "https://guyujiezi.com/fonts/LQ1K9/1A7s3D.woff"
filename = url.split('/')[-1]
resp = requests.get(url)
with open(filename, 'wb') as f:
f.write(resp.content)
# 接着用 TTFont 打开文件
font = TTFont(filename)
# TTFont 中有一个 saveXML 的方法
font.saveXML(filename.replace(filename.split('.')[-1], 'xml'))
复制代码
2、用文本编辑器打开
只需要看 GlyphOrder 项就行了,其实直接看 GlyphOrder 一个屁都看不出来,完全和之前做的分析不一样,不过仔细观察后发现这里面也被人做了手脚, 1703589624 这跟电话号码一样的就是上面看到的 修改后的字体 预览到的,可能这样还是看不出什么;其中 id 属性的值为 修改后的字体 中的数字, name 属性为 正常字体 ,但是根本不对,之前算过,网页中的 274 ,正常内容是 920 ,而下面, 2 明显对应着 zero ,其实我在这里被坑了,如果把 2+1=3 , 3 不就是对应着 nine 了吗,然后发现后面 74 也是对应着 20 ,有 12 项 GlyphID 的目的就是坑我们的(我猜的),不过这确实挺坑的。分析过后可以开始写代码了
3、代码如下,这是 pipelines.py 文件
# pipelines.py
# -*- coding: utf-8 -*-
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
from scrapy.exceptions import DropItem
from fontTools.ttLib import TTFont
from glidedsky.spiders.config import *
class GlidedskyPipeline(object):
result = 0
def process_item(self, item, spider):
if item['numbers']:
numbers = item['numbers']
#print("@@@@@ 假数字: %s \n" % numbers)
font = TTFont(WOFF_FONT_FILENAME) # 首先创建一个TTFont对象,参数为字体文件的路径
true_number = ""
for num in range(len(numbers)):
fn = NUMBER_TEMP[numbers[num]] # 从模版中获取数字对应着的英语单词
glyph_id = int(font.getGlyphID(fn)) - 1 # font.getGlyphID 方法是根据GlyphID name属性获取id属性的值,参数传入name值,最后减一
true_number += str(glyph_id)
self.result += int(true_number)
print("@@@@@ 计算结果: %d" % self.result)
else:
return DropItem('Missing Number.')
复制代码
config.py
DATA_PATH = '/Volumes/HDD500G/Documents/Python/Scrapy/glidedsky/glidedsky/data' # 这是我为了存储字体文件新建的文件夹
WOFF_FONT_FILENAME = DATA_PATH + '/woff-font.woff'
XSRF_TOKEN = ''
glidedsky_session = ''
NUMBER_TEMP = {'1': 'one', '2': 'two', '3': 'three', '4': 'four', '5': 'five', '6': 'six', '7': 'seven', '8': 'eight', '9': 'nine', '0': 'zero'} # 这个模版是为了方便我计算,题目需要
复制代码
items.py
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class GlidedskyItem(scrapy.Item):
# define the fields for your item here like:
numbers = scrapy.Field()
复制代码
settings.py,设置我就不全部贴了,只贴需要改的部分
# 这本来是注释掉了的
ITEM_PIPELINES = {
'glidedsky.pipelines.GlidedskyPipeline': 300,
}
复制代码
接着直接运行即可
➜ cd /你项目存储地址/glidedsky/ ➜ scrapy startpoject glidedsky 复制代码
输出结果就不展示了,贼鸡儿多
结论
这种反爬虫手段是我第一次遇到,以前遇到的也就验证码和ip限制,不过也算是涨了知识,最后结果是我解决了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 反爬虫之字体反爬虫
- 反爬虫之字体反爬虫
- Python爬虫实例:爬取猫眼电影——破解字体反爬
- CSS 字体:字体特性
- iOS 自定义字体设置与系统自带的字体
- ReactNative字体大小不随系统字体大小变化而变化
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Producing Masculinity
Michele White / Routledge / 2019-3 / $39.95
Thoughtful, witty, and illuminating, in this book Michele White explores the ways normative masculinity is associated with computers and the Internet and is a commonly enacted online gender practice. ......一起来看看 《Producing Masculinity》 这本书的介绍吧!