предисловие
В последнее время я беспокоился о поиске работы.Я только что наткнулся на компанию, которая попросила меня сначала сделать несколько вопросов против рептилий.Прочитав это, я почувствовал, что у меня неплохо, но я прошел несколько уровней, и я Довелось столкнуться с тем, с чем раньше не сталкивался.
текст
1. Анализ сайта
Требования темы:Вот сайт, разбитый на 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
Я не буду говорить, как использовать скрап, просто посмотрите код
# 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
Результаты вывода отображаться не будут, воров много
В заключение
Такого рода антирептильный метод я встречаю впервые.Проверочные коды и ограничения по айпи встречались и раньше,но это можно расценивать как повышение знаний.Конечным результатом является то,что я его решил.