В связи с бурным развитием Интернета вся текущая информация находится в состоянии массового накопления, нам необходимо не только получать большое количество данных из внешнего мира, но и отфильтровывать бесполезные данные из большого количества данных. Для наших полезных данных нам нужно указать обход, поэтому появляется актуальная технология обхода, с помощью которой мы можем быстро получить нужные нам данные. Однако в этом процессе сканирования владелец информации будет выполнять обработку, препятствующую сканированию, на сканере, и нам нужно преодолевать эти трудности одну за другой.
Некоторое время назад я проделал некоторую работу, связанную с рептилиями, так что вот некоторые связанные с этим события.
Код дела по адресу этой статьиGitHub.com/Ян Тао9502…
Здесь я использую фреймворк Scrapy для сканирования, соответствующий номер версии среды разработки:
Scrapy : 1.5.1
lxml : 4.2.5.0
libxml2 : 2.9.8
cssselect : 1.0.3
parsel : 1.5.1
w3lib : 1.20.0
Twisted : 18.9.0
Python : 3.7.1 (default, Dec 10 2018, 22:54:23) [MSC v.1915 64 bit (AMD64)]
pyOpenSSL : 18.0.0 (OpenSSL 1.1.1a 20 Nov 2018)
cryptography : 2.4.2
Platform : Windows-10-10.0.15063-SP0
Рекомендуется использовать Анаконду для установки соответствующего окружения в локальной среде разработки, иначе могут быть конфликты различных зависимых пакетов.Я считаю, что у всех, кто сталкивался с этим, есть глубокое понимание, и вы потеряете интерес к краулерам при настройке соответствующую среду. В этой статье Xpath в основном используется для извлечения данных страницы, поэтому, прежде чем приступить к операциям в этой статье, сначала разберитесь с основным использованием Xpath.
Создать Scrapy-проект
Создать проект с помощью scrapy очень просто, и это можно сделать одной командой.Далее мы создаем проект ytaoCrawl:
scrapy startproject ytaoCrawl
Обратите внимание, что имя проекта должно начинаться с буквы и содержать только буквы, цифры и символы подчеркивания. После успешного создания в интерфейсе отображается:
Файлы для инициализации проекта:
Назначение каждого из этих файлов:
- Каталог паука используется для хранения файлов паука.
- Файл items.py является самым большим объектом, и данные сканера сохраняются в этом объекте.
- Файл middlewares.py является обработчиком промежуточного программного обеспечения, в нем реализовано преобразование запросов и ответов.
- Файл pipelines.py представляет собой конвейер данных, который используется для сбора и доставки данных.
- Файл settings.py — это файл конфигурации, и в нем можно задать некоторые конфигурации сканера.
- Файл scrapy.cfg — это файл конфигурации, развернутый сканером.
Разобравшись с несколькими сгенерированными по умолчанию файлами, взгляните на следующую схематическую диаграмму структуры scrapy, которую относительно легко понять.
Таким образом создается один из наших проектов сканера scrapy.
Создать паука
Сначала мы создаем файл Python ytaoSpider, который должен наследовать класс scrapy.Spider. Далее мы возьмем сканирование информации об аренде в Пекине 58 в качестве примера для анализа.
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# @Author : YangTao
# @blog : https://ytao.top
#
import scrapy
class YtaoSpider(scrapy.Spider):
# 定义爬虫名称
name = "crawldemo"
# 允许爬取的域名,但不包含 start_urls 中的链接
allowed_domains = ["58.com"]
# 起始爬取链接
start_urls = [
"https://bj.58.com/chuzu/?PGTID=0d100000-0038-e441-0c8a-adeb346199d8&ClickID=2"
]
def download(self, response, fName):
with open(fName + ".html", 'wb') as f:
f.write(response.body)
# response 是返回抓取后的对象
def parse(self, response):
# 下载北京租房页面到本地,便于分析
self.download(response, "北京租房")
Запустите сканер, выполнив команду, указав имя сканера:
scrapy crawl crawldemo
Когда у нас есть несколько поисковых роботов, мы можем передатьscrapy list
Получить все имена сканеров.
Конечно, вы также можете использовать функцию mian для запуска в редакторе во время разработки:
if __name__ == '__main__':
name = YtaoSpider.name
cmd = 'scrapy crawl {0} '.format(name)
cmdline.execute(cmd.split())
В это время страница, которую мы сканируем, будет загружена и сгенерирована в каталоге, который мы запустили.
Перелистывание страниц
Мы просканировали только первую страницу выше, но в фактическом процессе сканирования данных разбивка на страницы определенно будет задействована, поэтому наблюдается, что разбивка на страницы веб-сайта показывает последнюю страницу (58 показывает только первые 70 страниц). данные), как показано на рис.
Обратите внимание на html-часть кода для разбиения на страницы на изображении ниже.
Далее получаем номер последней страницы через Xpath и обычное сопоставление.
def pageNum(self, response):
# 获取分页的 html 代码块
page_ele = response.xpath("//li[@id='pager_wrap']/div[@class='pager']")
# 通过正则获取含有页码数字的文本
num_eles = re.findall(r">\d+<", page_ele.extract()[0].strip())
# 找出最大的一个
count = 0
for num_ele in num_eles:
num_ele = str(num_ele).replace(">", "").replace("<", "")
num = int(num_ele)
if num > count:
count = num
return count
Анализируя ссылки на прокат, видно, что ссылки с разными номерами страниц:https://bj.58.com/chuzu/pn
+num
здесьnum
Представляет номер страницы. Когда мы получаем разные номера страниц, нам нужно изменить только номер страницы. Функцию синтаксического анализа можно изменить на:
# 爬虫链接,不含页码
target_url = "https://bj.58.com/chuzu/pn"
def parse(self, response):
print("url: ", response.url)
num = self.pageNum(response)
# 开始页面本来就是第一页,所以在遍历页面时,过滤掉第一页
p = 1
while p < num:
p += 1
try:
# 拼接下一页链接
url = self.target_url + str(p)
# 进行抓取下一页
yield Request(url, callback=self.parse)
except BaseException as e:
logging.error(e)
print("爬取数据异常:", url)
После выполнения выводимая информация выглядит следующим образом:
Поскольку поисковый робот извлекает данные асинхронно, наша распечатка не является упорядоченными данными.Вышеупомянутое предназначено для обхода и сканирования путем получения номера страницы последней страницы, но некоторые веб-сайты не имеют номера последней страницы.В это время мы можем судить, является ли текущая страница последней страницей через следующую страницу. , Если нет, получите Ссылка на следующей странице просканирована.
получить данные
Здесь мы получаем информацию о названии, площади, местоположении, сюжете и цене.Нам нужно создать эти поля в элементе сначала, меньше сплетен и коде.
# 避免取xpath解析数据时索引越界
def xpath_extract(self, selector, index):
if len(selector.extract()) > index:
return selector.extract()[index].strip()
return ""
def setData(self, response):
items = []
houses = response.xpath("//ul[@class='house-list']/li[@class='house-cell']")
for house in houses:
item = YtaocrawlItem()
# 标题
item["title"] = self.xpath_extract(house.xpath("div[@class='des']/h2/a/text()"), 0)
# 面积
item["room"] = self.xpath_extract(house.xpath("div[@class='des']/p[@class='room']/text()"), 0)
# 位置
item["position"] = self.xpath_extract(house.xpath("div[@class='des']/p[@class='infor']/a/text()"), 0)
# 小区
item["quarters"] = self.xpath_extract(house.xpath("div[@class='des']/p[@class='infor']/a/text()"), 1)
money = self.xpath_extract(house.xpath("div[@class='list-li-right']/div[@class='money']/b/text()"), 0)
unit = self.xpath_extract(house.xpath("div[@class='list-li-right']/div[@class='money']/text()"), 1)
# 价格
item["price"] = money+unit
items.append(item)
return items
def parse(self, response):
items = self.setData(response)
for item in items:
yield item
# 接着上面的翻页操作 .....
На этом этапе мы можем получить нужные нам данные и увидеть результат, распечатав элемент в синтаксическом анализе.
Хранилище данных
Мы зафиксировали данные страницы, и следующим шагом будет их сохранение.В качестве примера возьмем хранилище MySQL.В случае большого объема данных рекомендуется использовать другие продукты для хранения. Сначала мы устанавливаем свойство ITEM_PIPELINES в файле конфигурации settings.py, чтобы указать класс обработки Pipeline.
ITEM_PIPELINES = {
# 值越小,优先级调用越高
'ytaoCrawl.pipelines.YtaocrawlPipeline': 300,
}
Сохранение данных обрабатывается в классе YtaocrawlPipeline, где код mysqlUtils класса инструмента пакета MySQL можно просмотреть на github. Передайте данные в YtaocrawlPipeline#process_item для обработки с помощью yield в YtaoSpider#parse.
class YtaocrawlPipeline(object):
def process_item(self, item, spider):
table = "crawl"
item["id"] = str(uuid.uuid1())
# 如果当前爬取信息的链接在库中有存在,那么就删除旧的再保存新的
list = select(str.format("select * from {0} WHERE url = '{1}'", table, item["url"]))
if len(list) > 0:
for o in list:
delete_by_id(o[0], table)
insert(item, table)
return item
В базе данных вы можете видеть, что данные были успешно собраны и включены в базу данных.
Противоподъемный механизм
Поскольку есть спрос на сканеры данных, должны быть и контрмеры, и мы проанализируем текущие случаи использования сканеров.
шифрование шрифта
Из приведенной выше диаграммы данных базы данных видно, что乱码
, Изучив правила искажения данных, вы можете определить, где зашифрованы числа.
В то же время вы можете увидеть, распечатав данные\xa0
символ, этот (представляющий пустой символ) находится в диапазоне символов ASCII 0x20~0x7e, и видно, что он преобразован в кодировку ASCII.
Поскольку я знаю, что это шифрование шрифта, я проверяю его на странице загрузки.font-family
При отображении шрифта обнаруживается код, как показано на следующем рисунке:
видеть этоfangchan-secret
Шрифт подозрительный.Это шрифт, динамически сгенерированный в js и сохраненный в base64.Расшифрованы следующие шрифты.
if __name__ == '__main__':
secret = "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"
# 将字体文件编码转换为 UTF-8 编码的字节对象
bytes = secret.encode(encoding='UTF-8')
# base64位解码
decodebytes = base64.decodebytes(bytes)
# 利用 decodebytes 初始化 BytesIO,然后使用 TTFont 解析字体库
font = TTFont(BytesIO(decodebytes))
# 字体的映射关系
font_map = font['cmap'].tables[0].ttFont.tables['cmap'].tables[0].cmap
print(font_map)
При анализе шрифтов из TTFont библиотеки fontTools результаты сопоставления шрифтов следующие:
{
38006: 'glyph00007',
38287: 'glyph00005',
39228: 'glyph00006',
39499: 'glyph00003',
40506: 'glyph00010',
40611: 'glyph00001',
40804: 'glyph00009',
40850: 'glyph00004',
40868: 'glyph00002',
40869: 'glyph00008'
}
Есть ровно десять отображений, соответствующих числам от 0 до 9, но после поиска соответствующего правила после 1–9 есть 10, так что же за правило является соответствующим числом здесь? Кроме того, ключ, соответствующий приведенному выше отображению, является не шестнадцатеричным кодом ASCII, а чистым числом.Возможно ли, что это десятичный код? Далее проверяем наше предположение, преобразуем шестнадцатеричный код, полученный на странице, в десятичный код, а затем сопоставляем данные в карте, и обнаруживаем, что ненулевая числовая часть отображаемого значения как раз больше, чем соответствующие числовые символы на на странице 1 видно, что реальное значение требует от нас вычесть 1 из отображенного значения. После сортировки кода
def decrypt(self, response, code):
secret = re.findall("charset=utf-8;base64,(.*?)'\)", response.text)[0]
code = self.secretfont(code, secret)
return code
def secretfont(self, code, secret):
# 将字体文件编码转换为 UTF-8 编码的字节对象
bytes = secret.encode(encoding='UTF-8')
# base64位解码
decodebytes = base64.decodebytes(bytes)
# 利用 decodebytes 初始化 BytesIO,然后使用 TTFont 解析字体库
font = TTFont(BytesIO(decodebytes))
# 字体的映射关系
font_map = font['cmap'].tables[0].ttFont.tables['cmap'].tables[0].cmap
chars = []
for char in code:
# 将每个字符转换成十进制的 ASCII 码
decode = ord(char)
# 如果映射关系中存在 ASCII 的 key,那么这个字符就有对应的字体
if decode in font_map:
# 获取映射的值
val = font_map[decode]
# 根据规律,获取数字部分,再减1得到真正的值
char = int(re.findall("\d+", val)[0]) - 1
chars.append(char)
return "".join(map(lambda s:str(s), chars))
Теперь давайте расшифруем все просканированные данные и посмотрим на данные:
На приведенном выше рисунке после расшифровки искаженные данные идеально решены!
Проверочный код и забаненный IP
Коды подтверждения обычно делятся на две категории: при первом входе необходимо ввести код подтверждения, а при частых запросах требуется подтверждение кода подтверждения, прежде чем продолжить следующий запрос. Для первого необходимо взломать его проверочный код, чтобы продолжить, а для второго, кроме взлома проверочного кода, можно также использовать прокси для обхода проверки. Для защиты от сканирования заблокированных IP-адресов вы также можете использовать прокси для его обхода. Например, указанный выше поисковый робот URL все еще используется. Когда они узнают, что я могу быть поисковым роботом, они будут использовать код подтверждения для перехвата, как показано ниже:
Затем мы используем случайный User-Agent и прокси-IP для обхода. Сначала установите settings.USER_AGENT, обратите внимание, чтоНе смешивайте настройки User-Agent на ПК и мобильных терминалах, иначе вы будете сканировать данные ненормально, т.к. страницы на разных терминалах разные:
USER_AGENT = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.10 Safari/537.36",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
# ......
]
Установить случайное промежуточное ПО User-Agent в запросе
class RandomUserAgentMiddleware(object):
def __init__(self, agents):
self.agent = agents
@classmethod
def from_crawler(cls, crawler):
return cls(
agents=crawler.settings.get('USER_AGENT')
)
def process_request(self, request, spider):
# 随机获取设置中的一个 User-Agent
request.headers.setdefault('User-Agent', random.choice(self.agent))
Настройка промежуточного ПО с динамическим IP
class ProxyIPMiddleware(object):
def __init__(self, ip=''):
self.ip = ip
def process_request(self, request, spider):
# 如果当前的地址重定向到了验证码地址,就使用代理ip进行重新请求
if self.ban_url(request.url):
# 获取被重定向的地址
redirect_urls = request.meta.get("redirect_urls")[0]
# 将当前重定向到验证码的地址改为原始请求地址
request._set_url(redirect_urls)
# 设置动态代理,这里在线上一般使用接口动态生成代理
request.meta["proxy"] = "http://%s" % (self.proxy_ip())
def ban_url(self, url):
# settings中设置的验证码或被禁止的页面链接,当遇到该链接时,爬虫会进行绕行重爬
dic = settings.BAN_URLS
# 验证当前请求地址是否为验证码地址
for d in dic:
if url.find(d) != -1:
return True
return False
# 代理动态生成的 ip:port
def proxy_ip(self):
# 模拟动态生成代理地址
ips = [
"127.0.0.1:8888",
"127.0.0.1:8889",
]
return random.choice(ips);
def process_response(self, request, response, spider):
# 如果不是成功响应,则重新爬虫
if response.status != 200:
logging.error("失败响应: "+ str(response.status))
return request
return response
Наконец, включите это промежуточное ПО в файле конфигурации настроек.
DOWNLOADER_MIDDLEWARES = {
'ytaoCrawl.middlewares.RandomUserAgentMiddleware': 500,
'ytaoCrawl.middlewares.ProxyIPMiddleware': 501,
'ytaoCrawl.middlewares.YtaocrawlDownloaderMiddleware': 543,
}
На данный момент настройка случайного User-Agent и динамического обхода IP завершена.
развертывать
Используя scrapyd для развертывания проекта сканера, вы можете удаленно управлять сканером, например запускать, выключать, регистрировать вызовы и т. д. Перед развертыванием мы должны сначала установить scrapyd, используя команду:
pip install scrapyd
После успешной установки вы увидите, что версия1.2.1
.
После развертывания нам также нужен клиент для доступа, здесь нам нужен клиент scrapyd-client:
pip install scrapyd-client
Изменить файл scrapy.cfg
[settings]
default = ytaoCrawl.settings
[deploy:localytao]
url = http://localhost:6800/
project = ytaoCrawl
# deploy 可批量部署
Запустить скрапид:
scrapyd
Если это Windows, сначалаX:\xx\Scripts
Создать подscrapyd-deploy.bat
документ
@echo off
"X:\xx\python.exe" "X:\xx\Scripts\scrapyd-deploy" %1 %2
Разверните проект в сервисе Scrapyd:
scrapyd-deploy localytao -p ytaoCrawl
Удаленный запуск завитокhttp://localhost:6800/schedule.json -d project=ytaoCrawl -d spider=ytaoSpider
После выполнения запуска вы можетеhttp://localhost:6800/
Просмотр состояния выполнения искателя и вход в систему
Помимо возможности удаленных вызовов, Scrapyd также предоставляет более богатый API:
- Запрос состояния искателя в обслуживании
curl http://localhost:6800/daemonstatus.json
- Отменить поисковый робот
curl http://localhost:6800/cancel.json -d project=projectName -d job=jobId
- Демонстрационный проект
curl http://localhost:6800/listprojects.json
- удалить пункт
curl http://localhost:6800/delproject.json -d project=projectName
- показать сканер
curl http://localhost:6800/listspiders.json?project=projectName
- Получить все номера версий проекта
curl http://localhost:6800/listversions.json?project=projectName
- Удалить номер версии проекта
curl http://localhost:6800/delversion.json -d project=projectName -d version=versionName
Подробнеескрап YD.прочитайте документ S.IO/en/stable/ ах…
Суммировать
Объем этой статьи ограничен, и процесс анализа не может охватить все. Некоторые веб-сайты труднее реверсивно пройти. Пока мы анализируем их один за другим, мы можем найти способ взломать их, и данные, которые мы видим, не обязательно данные, которые вы получаете, например HTML-рендеринг некоторых веб-сайтов является динамическим, и нам необходимо обрабатывать эту информацию. Когда вы войдете в мир краулеров, вы обнаружите, что это на самом деле довольно интересно. Наконец, я надеюсь, что никто не столкнется с поисковыми роботами, данных миллионы, и первое правило — соблюдать закон.
личный блог: ytao.top
Мой официальный аккаунт ytao