\\n\\n\\n\\n
Отлично! У нас есть работающий сервис с формальной спецификацией. Теперь потребители могут реализовать клиентов для общения с ним, используя любой HTTP-клиент. Благодаря спецификации OpenAPI мы можем сделать еще один шаг и создать для них SDK с сильным типом клиента.
\\n\\n\\n\\nВ этом примере мы достигнем этого, используя openapi-typescript и openapi-typescript-fetch.
\\n\\n\\n\\nnpm install -D openapi-typescript @types/node-fetch\\nnpm install node-fetch openapi-typescript-fetch\\nnpx openapi-typescript http://localhost:3000/v3/api-docs --output ./client-types.ts\\n
\\n\\n\\n\\nЗатем мы можем использовать сгенерированные типы для выполнения вызовов API с сильной типизацией (как для ввода, так и для вывода). Создайте файл client.ts, чтобы опробовать его:
\\n\\n\\n\\n// client.ts\\nimport fetch, { Headers, Request, Response } from 'node-fetch';\\nimport { Fetcher } from 'openapi-typescript-fetch';\\nimport { paths } from './client-types';\\n\\n// polyfill `fetch` for node\\nif (!globalThis.fetch) {\\n globalThis.fetch = fetch as any;\\n globalThis.Headers = Headers as any;\\n globalThis.Request = Request as any;\\n globalThis.Response = Response as any;\\n}\\n\\nasync function main() {\\n const fetcher = Fetcher.for<paths>();\\n fetcher.configure({\\n baseUrl: 'http://localhost:3000',\\n });\\n\\n const login = fetcher.path('/api/login').method('post').create();\\n const { data: loginResult } = await login({\\n email: 'tom@pet.inc',\\n password: 'abc123',\\n });\\n // loginResult is typed as { id: string, email: string, token: string }\\n console.log('Login result:', JSON.stringify(loginResult, undefined, 2));\\n const token = loginResult.token;\\n\\n // get orders together with their pets\\n const getOrders = fetcher.path(`/api/order/findMany`).method('get').create();\\n const { data: orders } = await getOrders(\\n { q: JSON.stringify({ include: { pets: true } }) },\\n { headers: { Authorization: `Bearer ${token}` } }\\n );\\n console.log('Orders:', JSON.stringify(orders, undefined, 2));\\n}\\n\\nmain();\\n
\\n\\n\\n\\nВы можете запустить его с:
\\n\\n\\n\\nnpx tsx client.ts\\n
\\n\\n\\n\\nСоздание сервиса OpenAPI, ориентированного на базу данных, включает множество задач: проектирование модели данных, составление спецификации, реализация сервиса и создание клиентского SDK. Но, как вы видите, это не обязательно должно быть сложно и долго.
\\n\\n\\n\\nГлавный вывод: если вы можете использовать единый источник истины для представления схемы данных и правил доступа, на его основе можно создать множество других артефактов. Это сэкономит ваше драгоценное время на написание шаблонного кода, а также значительно упростит синхронизацию всего процесса.
\\n\\n\\n\\nГотовый проект можно найти здесь.
\\n\\n\\n\\nP.S. Мы создаем ZenStack, набор инструментов, который усиливает Prisma ORM мощным слоем управления доступом и раскрывает его полный потенциал для фуллстэк разработки.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Если вы являетесь разработчиком, знакомым с RESTful API, вы, возможно, слышали о OpenAPI. Это спецификация для описания RESTful API в формате, читаемом людьми и машинами. Создание публичного OpenAPI включает в себя три задачи: В этом посте вы увидите, как выполнить все эти задачи и создать OpenAPI-сервис, ориентированный на базу данных, безопасный и документированный, за 15 […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/sozdanie-bezopasnogo-openapi-orientirovannogo-na-bazu-dannyh-za-15-minut/\"],\"title\":[0,\"Создание безопасного OpenAPI, ориентированного на базу данных, за 15 минут - Gorlov.\"],\"breadcrumbTitle\":[0,\"Создание безопасного OpenAPI, ориентированного на базу данных, за 15 минут\"],\"description\":[0,\"Если вы являетесь разработчиком, знакомым с RESTful API, вы, возможно, слышали о OpenAPI. Это спецификация для описания RESTful API в формате, читаемом людьми\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Если вы являетесь разработчиком, знакомым с RESTful API, вы, возможно, слышали о OpenAPI. Это спецификация для описания RESTful API в формате, читаемом людьми\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Создание безопасного OpenAPI, ориентированного на базу данных, за 15 минут - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-20T22:11:06+00:00\"],\"url\":[0,\"http://igorlov.loc/sozdanie-bezopasnogo-openapi-orientirovannogo-na-bazu-dannyh-za-15-minut/\"]}]}],\"title\":[0,\"Создание безопасного OpenAPI, ориентированного на базу данных, за 15 минут\"],\"uri\":[0,\"/sozdanie-bezopasnogo-openapi-orientirovannogo-na-bazu-dannyh-za-15-minut/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"sozdanie-bezopasnogo-openapi-orientirovannogo-na-bazu-dannyh-za-15-minut\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Openapi\\\"],\\\"id\\\":[0,\\\"dGVybToxODc=\\\"],\\\"uri\\\":[0,\\\"/tag/openapi/\\\"]}],[0,{\\\"name\\\":[0,\\\"Prisma\\\"],\\\"id\\\":[0,\\\"dGVybToxODg=\\\"],\\\"uri\\\":[0,\\\"/tag/prisma/\\\"]}],[0,{\\\"name\\\":[0,\\\"Restapi\\\"],\\\"id\\\":[0,\\\"dGVybToxNDA=\\\"],\\\"uri\\\":[0,\\\"/tag/restapi/\\\"]}],[0,{\\\"name\\\":[0,\\\"ZenStack\\\"],\\\"id\\\":[0,\\\"dGVybToxODk=\\\"],\\\"uri\\\":[0,\\\"/tag/zenstack/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg3MjQ=\"],\"node\":[0,{\"date\":[0,\"2023-03-20T21:37:57\"],\"content\":[0,\"\\nGit – это мощный инструмент, который разработчики используют для управления изменениями своего кода. Он широко используется при разработке программного обеспечения для управления версиями кода и совместной работы с другими разработчиками. Git может быть сложным, и бывает трудно запомнить все доступные команды и опции. Именно здесь может помочь шпаргалка по командам Git.
\\n\\n\\n\\nШпаргалка по командам Git – это удобное справочное руководство, в котором перечислены все основные команды Git и их опции. Это полезный инструмент для новичков, которые только начинают работать с Git, а также для опытных разработчиков, которым нужно освежить в памяти некоторые команды Git.
\\n\\n\\n\\nШпаргалка по командам Git может стать ценным инструментом для разработчиков, использующих Git для управления изменениями кода. Она поможет им запомнить основные команды Git и их опции, а также сэкономит время и усилия при работе с Git. Независимо от того, начинающий вы или опытный разработчик, шпаргалка по командам Git может стать полезным справочником, который всегда будет у вас под рукой.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Что такое git? Git – это мощный инструмент, который разработчики используют для управления изменениями своего кода. Он широко используется при разработке программного обеспечения для управления версиями кода и совместной работы с другими разработчиками. Git может быть сложным, и бывает трудно запомнить все доступные команды и опции. Именно здесь может помочь шпаргалка по командам Git. Что […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/shpargalka-po-komandam-git/\"],\"title\":[0,\"Шпаргалка по командам Git - Gorlov.\"],\"breadcrumbTitle\":[0,\"Шпаргалка по командам Git\"],\"description\":[0,\"Git - это мощный инструмент, который разработчики используют для управления изменениями своего кода. Он широко используется при разработке программного\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Git - это мощный инструмент, который разработчики используют для управления изменениями своего кода. Он широко используется при разработке программного\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Шпаргалка по командам Git - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-20T21:37:58+00:00\"],\"url\":[0,\"http://igorlov.loc/shpargalka-po-komandam-git/\"]}]}],\"title\":[0,\"Шпаргалка по командам Git\"],\"uri\":[0,\"/shpargalka-po-komandam-git/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"shpargalka-po-komandam-git\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Git\\\"],\\\"id\\\":[0,\\\"dGVybToxODY=\\\"],\\\"uri\\\":[0,\\\"/tag/git/\\\"]}],[0,{\\\"name\\\":[0,\\\"Github\\\"],\\\"id\\\":[0,\\\"dGVybTo1Mw==\\\"],\\\"uri\\\":[0,\\\"/tag/github/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg3Mjg=\"],\"node\":[0,{\"date\":[0,\"2023-03-20T21:33:32\"],\"content\":[0,\"\\nВ постоянно развивающемся ландшафте разработки программного обеспечения и веб-приложений API и Webhooks стали важнейшими компонентами для подключения и автоматизации различных сервисов. Хотя оба эти инструмента являются популярными для обеспечения бесперебойной связи между системами, важно понимать их ключевые различия. В этой статье мы дадим минимальное описание API и Webhooks, а также рассмотрим, как такие инструменты, как Netlify Functions, и платформы, такие как Zapier, могут повысить их полезность как для новичков, так и для экспертов.
\\n\\n\\n\\nAPI (интерфейсы прикладного программирования) и Webhooks – это механизмы, облегчающие взаимодействие между различными приложениями, но они служат разным целям и работают по-разному.
\\n\\n\\n\\nAPI позволяют разработчикам получать доступ и взаимодействовать с функциональностью внешних приложений или сервисов с помощью заранее определенного набора правил и протоколов. Используя API, разработчики могут интегрировать сторонние сервисы или получать данные из внешних источников, не создавая всю функциональность с нуля.
\\n\\n\\n\\nWebhooks, с другой стороны, обеспечивают связь между приложениями в режиме реального времени, управляемую событиями. Они позволяют одному приложению уведомлять другое при возникновении определенных событий, например, при добавлении новых данных или выполнении пользователем определенного действия. Webhooks – это определенные пользователем HTTP-обратные вызовы, которые отправляют запрос на указанный URL при срабатывании.
\\n\\n\\n\\nПонимание основных различий между API и Webhooks имеет решающее значение для определения того, какой инструмент лучше всего подходит для конкретного случая использования.
\\n\\n\\n\\nНиже приведены основные различия:
\\n\\n\\n\\nAPI используют стиль связи “запрос-ответ”, когда клиент посылает запрос на сервер, который затем отвечает нужными данными. Напротив, Webhooks используют событийный стиль взаимодействия, когда одно приложение отправляет HTTP-запрос другому при наступлении определенного события.
\\n\\n\\n\\nAPI обычно требуют опроса, когда клиент должен периодически запрашивать данные у сервера для проверки обновлений. Это может привести к увеличению сетевого трафика и задержек. Webhooks, напротив, передает данные непосредственно принимающему приложению сразу после наступления события, что снижает необходимость в опросе и повышает эффективность.
\\n\\n\\n\\nAPI обеспечивают большую гибкость в отношении данных и функциональности, к которым можно получить доступ, поскольку разработчики могут выбирать, какие конечные точки и методы вызывать. Webhooks более ограничены, поскольку они привязаны к заранее определенным событиям и действиям.
\\n\\n\\n\\nВозможности API и Webhooks могут быть расширены с помощью таких инструментов, как Netlify Functions, и платформ, таких как Zapier.
\\n\\n\\n\\nNetlify Functions упрощает процесс создания и развертывания бессерверных функций, которые можно использовать для создания пользовательских API. Используя возможности AWS Lambda, Netlify Functions позволяет разработчикам создавать бессерверные конечные точки для своих приложений с минимальной конфигурацией, которые затем можно использовать для получения данных, обработки отправки форм или даже аутентификации. Узнайте больше о Netlify Functions.
\\n\\n\\n\\nZapier – это популярная платформа автоматизации, которая позволяет пользователям подключать различные приложения и создавать автоматизированные рабочие процессы с помощью Webhooks . Благодаря интуитивно понятному интерфейсу и обширной библиотеке интеграций Zapier позволяет пользователям любого уровня квалификации легко устанавливать Webhooks и автоматизировать задачи в различных приложениях, упрощая процесс интеграции и повышая производительность. Вы также можете использовать этот Webflow Webhook Generator от Evil Twins Studio (на базе Netlify Function!) для запуска Webhook Zapier при наступлении выбранного вами события (например, создание элемента коллекции Webflow CMS).
\\n\\n\\n\\nИ API, и Webhooks играют важную роль в современной разработке программного обеспечения, предлагая различные преимущества и служа уникальным целям. Понимая основные различия между ними и используя такие инструменты, как Netlify Functions, и такие платформы, как Zapier, разработчики и пользователи могут использовать возможности этих технологий для создания более эффективных, взаимосвязанных и динамичных приложений. По мере роста и развития экосистемы разработки программного обеспечения, API и Webhooks останутся незаменимыми инструментами для обеспечения бесперебойной связи и интеграции между различными сервисами. Оставаясь в курсе этих технологий и соответствующих случаев их использования, новички и эксперты могут обеспечить максимальную отдачу от своих усилий по разработке и максимизировать потенциал своих приложений.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Введение В постоянно развивающемся ландшафте разработки программного обеспечения и веб-приложений API и Webhooks стали важнейшими компонентами для подключения и автоматизации различных сервисов. Хотя оба эти инструмента являются популярными для обеспечения бесперебойной связи между системами, важно понимать их ключевые различия. В этой статье мы дадим минимальное описание API и Webhooks, а также рассмотрим, как такие инструменты, […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/api-i-webhooks-ponimanie-osnovnyh-razlichij-i-ispolzovanie-ih-vozmozhnostej-s-pomoshhyu-netlify-functions-i-zapier/\"],\"title\":[0,\"API и Webhooks: Понимание основных различий и использование их возможностей с помощью Netlify Functions и Zapier - Gorlov.\"],\"breadcrumbTitle\":[0,\"API и Webhooks: Понимание основных различий и использование их возможностей с помощью Netlify Functions и Zapier\"],\"description\":[0,\"В постоянно развивающемся ландшафте разработки программного обеспечения и веб-приложений API и Webhooks стали важнейшими компонентами для подключения и\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"В постоянно развивающемся ландшафте разработки программного обеспечения и веб-приложений API и Webhooks стали важнейшими компонентами для подключения и\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"API и Webhooks: Понимание основных различий и использование их возможностей с помощью Netlify Functions и Zapier - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-20T21:33:34+00:00\"],\"url\":[0,\"http://igorlov.loc/api-i-webhooks-ponimanie-osnovnyh-razlichij-i-ispolzovanie-ih-vozmozhnostej-s-pomoshhyu-netlify-functions-i-zapier/\"]}]}],\"title\":[0,\"API и Webhooks: Понимание основных различий и использование их возможностей с помощью Netlify Functions и Zapier\"],\"uri\":[0,\"/api-i-webhooks-ponimanie-osnovnyh-razlichij-i-ispolzovanie-ih-vozmozhnostej-s-pomoshhyu-netlify-functions-i-zapier/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"api-i-webhooks-ponimanie-osnovnyh-razlichij-i-ispolzovanie-ih-vozmozhnostej-s-pomoshhyu-netlify-functions-i-zapier\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Restapi\\\"],\\\"id\\\":[0,\\\"dGVybToxNDA=\\\"],\\\"uri\\\":[0,\\\"/tag/restapi/\\\"]}],[0,{\\\"name\\\":[0,\\\"Webhooks\\\"],\\\"id\\\":[0,\\\"dGVybToxODU=\\\"],\\\"uri\\\":[0,\\\"/tag/webhooks/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg3Mjk=\"],\"node\":[0,{\"date\":[0,\"2023-03-19T23:59:47\"],\"content\":[0,\"\\nВ современном мире кибернетические атаки становятся все более изощренными. Двумя распространенными типами атак, с которыми сталкиваются веб-сайты и приложения, являются:
\\n\\n\\n\\n
Атаки HPP происходят, когда параметры HTTP загрязняются дублирующими или вредоносными значениями.
Атаки XSS происходят, когда злоумышленники внедряют вредоносные скрипты на сайт или в приложение. Чаще всего это происходит, когда мы, пользователи, можем делать запросы, используя URL.
\\n\\n\\n\\nК счастью, в Node.js существуют модули, которые могут помочь предотвратить эти типы атак. Модуль “hpp” может предотвратить HPP-атаки, а модуль “xss-clean” – XSS-атаки.
\\n\\n\\n\\nМодуль “hpp” работает путем предотвращения дублирования HTTP-параметров. Для этого он проверяет каждый параметр и удаляет дубликаты перед передачей запроса следующему промежуточному программному обеспечению. Это гарантирует, что сервер получает только один экземпляр каждого параметра, предотвращая любые HPP-атаки, которые могут быть предприняты.
\\n\\n\\n\\nЧтобы использовать модуль “hpp”, просто установите его с помощью NPM
\\n\\n\\n\\nnpm install hpp
\\n\\n\\n\\nВключите его в свой код:
\\n\\n\\n\\nconst hpp = require('hpp');
\\n\\n\\n\\nЗатем добавьте промежуточное ПО в ваше приложение:
\\n\\n\\n\\napp.use(hpp());
\\n\\n\\n\\nМодуль “xss-clean”, с другой стороны, предотвращает XSS-атаки путем санации пользовательского ввода. Для этого он экранирует символы, которые могут быть использованы для выполнения скриптов, такие как “<” и “>”. Это гарантирует, что любой пользовательский ввод безопасен для использования и не может быть использован для выполнения вредоносных скриптов.
\\n\\n\\n\\nЧтобы использовать модуль “xss-clean”, установите его с помощью NPM
\\n\\n\\n\\nnpm install xss-clean
\\n\\n\\n\\nВключите его в свой код:
\\n\\n\\n\\nconst xss = require('xss-clean');\\napp.use(xss());
\\n\\n\\n\\nВ заключение, HPP и XSS атаки – это два распространенных типа атак, с которыми сталкиваются веб-сайты и приложения. К счастью, такие модули, как “hpp” и “xss-clean”, доступны в Node.js для предотвращения этих атак. Используя эти модули в своем приложении Node.js, вы можете гарантировать, что ваше приложение безопасно и защищено от этих типов атак.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
В современном мире кибернетические атаки становятся все более изощренными. Двумя распространенными типами атак, с которыми сталкиваются веб-сайты и приложения, являются: HPP (HTTP Parameter Pollution). Атаки HPP происходят, когда параметры HTTP загрязняются дублирующими или вредоносными значениями. XSS (межсайтовый скриптинг). Атаки XSS происходят, когда злоумышленники внедряют вредоносные скрипты на сайт или в приложение. Чаще всего это происходит, […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/how-to-prevent-hpp-and-xss-attacks-in-nodejs/\"],\"title\":[0,\"How To Prevent HPP And XSS Attacks In Nodejs - Gorlov.\"],\"breadcrumbTitle\":[0,\"How To Prevent HPP and XSS Attacks In Nodejs\"],\"description\":[0,\"В современном мире кибернетические атаки становятся все более изощренными. Двумя распространенными типами атак, с которыми сталкиваются веб-сайты и\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"В современном мире кибернетические атаки становятся все более изощренными. Двумя распространенными типами атак, с которыми сталкиваются веб-сайты и\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"How To Prevent HPP And XSS Attacks In Nodejs - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T23:59:49+00:00\"],\"url\":[0,\"http://igorlov.loc/how-to-prevent-hpp-and-xss-attacks-in-nodejs/\"]}]}],\"title\":[0,\"How To Prevent HPP and XSS Attacks In Nodejs\"],\"uri\":[0,\"/how-to-prevent-hpp-and-xss-attacks-in-nodejs/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"how-to-prevent-hpp-and-xss-attacks-in-nodejs\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Hpp\\\"],\\\"id\\\":[0,\\\"dGVybToxODM=\\\"],\\\"uri\\\":[0,\\\"/tag/hpp/\\\"]}],[0,{\\\"name\\\":[0,\\\"Node\\\"],\\\"id\\\":[0,\\\"dGVybTo1Ng==\\\"],\\\"uri\\\":[0,\\\"/tag/node/\\\"]}],[0,{\\\"name\\\":[0,\\\"Security\\\"],\\\"id\\\":[0,\\\"dGVybToxODQ=\\\"],\\\"uri\\\":[0,\\\"/tag/security/\\\"]}],[0,{\\\"name\\\":[0,\\\"Xss\\\"],\\\"id\\\":[0,\\\"dGVybToxODI=\\\"],\\\"uri\\\":[0,\\\"/tag/xss/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg3NzQ=\"],\"node\":[0,{\"date\":[0,\"2023-03-19T23:51:51\"],\"content\":[0,\"\\nЗдравствуйте и добро пожаловать в эту статью о создании перехватчика Axios в React и Next.js. В этой статье мы рассмотрим, как настроить и использовать Axios, а также как создать перехватчик, который может автоматически обновлять токены.
\\n\\n\\n\\n
Сначала нам нужно инициализировать проект с помощью следующей команды: yarn create react-app <имя приложения> или npx create-react-app <имя приложения>. Эта команда создаст новое приложение React с выбранным вами именем.
Теперь, когда у нас есть новое приложение React, мы можем создать службу каталогов и создать внутри нее файл с именем axiosConfig.ts. Вот код, который нужно поместить в этот файл:
import axios from 'axios';\\nimport { getToken, setToken } from '../../../utils/localStorage';\\nimport { redirect } from \\\"react-router-dom\\\";\\nimport { getRefreshToken } from '../login';\\n\\nconst statusCode = [401,402,403]\\nconst HttpAuthInstance = axios.create({\\n baseURL: process.env.REACT_APP_BASE_URL,\\n headers: {\\n \\\"Authorization\\\": \\\"Bearer\\\" + \\\" \\\" + getToken(\\\"token\\\").accessToken\\n }\\n})\\n\\nHttpAuthInstance.interceptors.response.use((response) => {\\n return response;\\n}, (error) => {\\n if (statusCode.indexOf(error?.response?.status) !== -1) {\\n getRefreshToken(getToken(\\\"token\\\")?.refreshToken).then(res=>setToken(\\\"token\\\",res?.data))\\n }\\n})\\n\\nexport default HttpAuthInstance;\\n
\\n\\n\\n\\nЭтот код устанавливает экземпляр Axios, который включает базовый URL и заголовки с маркером авторизации. Он также устанавливает перехватчик, который проверяет наличие определенных кодов состояния ошибки и при необходимости обновляет маркер.
\\n\\n\\n\\n
Чтобы использовать экземпляр Axios в своем приложении, просто импортируйте его в файл, в котором необходимо выполнять вызовы API. Вот пример того, как это сделать:
import HttpAuthInstance from './service/axiosConfig';\\n\\nHttpAuthInstance.get('/api/users').then(response => {\\n console.log(response.data);\\n});\\n
\\n\\n\\n\\nВ этом примере мы делаем GET-запрос к конечной точке /api/users и записываем данные ответа в консоль.
\\n\\n\\n\\nВот и все! С помощью этого перехватчика Axios ваше приложение будет автоматически обновлять токены при необходимости, что сделает его более безопасным и эффективным. Надеюсь, эта статья была полезной и информативной для вас.
\\n\\n\\n\\nСчастливого кодинга!
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Здравствуйте и добро пожаловать в эту статью о создании перехватчика Axios в React и Next.js. В этой статье мы рассмотрим, как настроить и использовать Axios, а также как создать перехватчик, который может автоматически обновлять токены. Шаг 1: Инициализация проекта Сначала нам нужно инициализировать проект с помощью следующей команды: yarn create react-app <имя приложения> или npx […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/sozdanie-axios-interceptors-v-react-i-nextjs/\"],\"title\":[0,\"Создание Axios Interceptors в React и NextJs - Gorlov.\"],\"breadcrumbTitle\":[0,\"Создание Axios interceptors в React и NextJs\"],\"description\":[0,\"Здравствуйте и добро пожаловать в эту статью о создании перехватчика Axios в React и Next.js. В этой статье мы рассмотрим, как настроить и использовать Axios,\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Здравствуйте и добро пожаловать в эту статью о создании перехватчика Axios в React и Next.js. В этой статье мы рассмотрим, как настроить и использовать Axios,\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Создание Axios Interceptors в React и NextJs - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T23:51:53+00:00\"],\"url\":[0,\"http://igorlov.loc/sozdanie-axios-interceptors-v-react-i-nextjs/\"]}]}],\"title\":[0,\"Создание Axios interceptors в React и NextJs\"],\"uri\":[0,\"/sozdanie-axios-interceptors-v-react-i-nextjs/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"sozdanie-axios-interceptors-v-react-i-nextjs\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Axios\\\"],\\\"id\\\":[0,\\\"dGVybTozNw==\\\"],\\\"uri\\\":[0,\\\"/tag/axios/\\\"]}],[0,{\\\"name\\\":[0,\\\"Next.js\\\"],\\\"id\\\":[0,\\\"dGVybToxNTA=\\\"],\\\"uri\\\":[0,\\\"/tag/next-js/\\\"]}],[0,{\\\"name\\\":[0,\\\"React\\\"],\\\"id\\\":[0,\\\"dGVybTozNg==\\\"],\\\"uri\\\":[0,\\\"/tag/react/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg3NzU=\"],\"node\":[0,{\"date\":[0,\"2023-03-19T23:42:02\"],\"content\":[0,\"\\nDevOps – это подход к разработке программного обеспечения, в котором особое внимание уделяется сотрудничеству и коммуникации между командами разработчиков и операторов. Он направлен на оптимизацию процесса поставки программного обеспечения и повышение скорости и эффективности выпуска программного обеспечения. DevOps основан на принципах автоматизации, непрерывной интеграции и развертывания, а также мониторинга. Этот подход помогает организациям быстрее предоставлять высококачественное программное обеспечение, оперативно реагировать на потребности клиентов, а также сократить время простоя и риск сбоев. DevOps – это междисциплинарная область, объединяющая элементы разработки программного обеспечения, ИТ-операций и обеспечения качества, что способствует сотрудничеству и постоянному совершенствованию.
\\n\\n\\n\\nПоскольку индустрия программного обеспечения продолжает развиваться, а спрос на более быстрое и эффективное предоставление программного обеспечения растет, роль DevOps становится все более важной. DevOps – это направление, которое объединяет обязанности команд разработчиков и операторов для рационализации процессов доставки программного обеспечения и улучшения сотрудничества и коммуникации. Если вы front-end разработчик, переход на DevOps может стать отличной возможностью расширить свои навыки и направить карьеру в новое русло.
\\n\\n\\n\\nЕсть несколько причин, по которым вы, будучи front-end разработчиком, можете рассмотреть возможность перехода на DevOps. Вот некоторые из причин, по которым вы можете захотеть перейти в DevOps в качестве front-end разработчика:
\\n\\n\\n\\nПереход на DevOps может предложить ряд преимуществ и возможностей для front-end разработчиков, желающих расширить свои навыки и продвинуться по карьерной лестнице.
\\n\\n\\n\\nАвтоматизация лежит в основе DevOps и имеет решающее значение для оптимизации процессов доставки программного обеспечения. Автоматизация позволяет снизить количество человеческих ошибок, повысить эффективность и позволить командам сосредоточиться на более творческой и сложной работе. В роли DevOps вы сможете работать с различными инструментами и технологиями автоматизации, включая скриптовые языки, облачные сервисы и виртуализацию.
Автоматизация является важнейшим аспектом DevOps и имеет ряд преимуществ, которые делают ее ценным инструментом для организаций, стремящихся улучшить процесс доставки программного обеспечения. Некоторые из преимуществ автоматизации включают следующее:
Автоматизация может принести пользу людям и организациям в самых разных отраслях и ролях. Вот несколько причин, по которым каждый захочет автоматизировать часть своей работы:
\\n\\n\\n\\nВ целом, автоматизация может принести пользу людям и организациям, повышая эффективность, скорость, надежность, масштабируемость и прозрачность. Независимо от того, являетесь ли вы front-end разработчиком, системным администратором или работаете в любой другой роли, автоматизация вашей работы может помочь вам стать более продуктивным, эффективным и результативным.
\\n\\n\\n\\nХотите узнать о своих возможностях? Конечно! Я расскажу подробнее о каждой из различных профессий в DevOps.
\\n\\n\\n\\nВо всех случаях необходимы сильные навыки решения проблем и общения, чтобы работать в нескольких командах для решения сложных технических задач.
\\n\\n\\n\\nНавыки и знания, необходимые для роли DevOps, могут варьироваться в зависимости от конкретной выбранной вами роли, но есть некоторые общие навыки и знания, которые важны для успеха в этой области:
\\n\\n\\n\\nУспех в роли DevOps требует сочетания технических навыков, умения решать проблемы и сильных коммуникативных навыков. Инженеры DevOps также должны быть привержены постоянному обучению и совершенствованию и должны уметь работать в сотрудничестве с межфункциональными командами для решения сложных технических задач.
\\n\\n\\n\\nПереход от фронтенд-разработки к DevOps может показаться сложным, но при правильном подходе это возможно. Ниже приведены некоторые шаги, которые необходимо предпринять при переходе:
\\n\\n\\n\\nПри переходе на новую работу лучше всего начинать с малого и постепенно наращивать свои навыки. Поиск наставника также может быть невероятно полезен, так как он может дать рекомендации и оказать поддержку в освоении новой сферы деятельности. Наконец, продолжайте учиться! Индустрия программного обеспечения постоянно меняется, и DevOps не является исключением. Постоянное знакомство с новейшими инструментами, технологиями и передовым опытом имеет решающее значение для успеха в этой области.
\\n\\n\\n\\nВ заключение следует отметить, что переход от front-end разработки к DevOps может стать отличной возможностью расширить свои навыки и направить карьеру в новое русло. С учетом растущего спроса на скорость и эффективность доставки программного обеспечения, DevOps – это область с большим потенциалом роста и возможностей. Освоив навыки и знания, необходимые для работы в DevOps, и следуя передовому опыту, вы сможете успешно перевести свою карьеру на новый уровень.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
DevOps – это подход к разработке программного обеспечения, в котором особое внимание уделяется сотрудничеству и коммуникации между командами разработчиков и операторов. Он направлен на оптимизацию процесса поставки программного обеспечения и повышение скорости и эффективности выпуска программного обеспечения. DevOps основан на принципах автоматизации, непрерывной интеграции и развертывания, а также мониторинга. Этот подход помогает организациям быстрее предоставлять […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/perehod-ot-razrabotki-k-devops/\"],\"title\":[0,\"Переход от разработки к DevOps - Gorlov.\"],\"breadcrumbTitle\":[0,\"Переход от разработки к DevOps\"],\"description\":[0,\"DevOps - это подход к разработке программного обеспечения, в котором особое внимание уделяется сотрудничеству и коммуникации между командами разработчиков и\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"DevOps - это подход к разработке программного обеспечения, в котором особое внимание уделяется сотрудничеству и коммуникации между командами разработчиков и\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Переход от разработки к DevOps - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T23:44:25+00:00\"],\"url\":[0,\"http://igorlov.loc/perehod-ot-razrabotki-k-devops/\"]}]}],\"title\":[0,\"Переход от разработки к DevOps\"],\"uri\":[0,\"/perehod-ot-razrabotki-k-devops/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"perehod-ot-razrabotki-k-devops\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"DevOps\\\"],\\\"id\\\":[0,\\\"dGVybToxODE=\\\"],\\\"uri\\\":[0,\\\"/tag/devops/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0NTg=\"],\"node\":[0,{\"date\":[0,\"2023-03-19T22:07:12\"],\"content\":[0,\"\\nВ этой статье вы узнаете, как использовать функцию range() в Python с некоторыми примерами кода по ходу дела.
\\n\\n\\n\\nЧто такое функция range() в Python? Разбивка синтаксиса функции range()
\\n\\n\\n\\nВстроенная в Python функция range() в основном используется при работе с циклами for – с ее помощью вы можете перебирать определенные блоки кода заданное количество раз.
\\n\\n\\n\\nФункция range() принимает три аргумента — один обязательный, а два необязательных.
\\n\\n\\n\\nПо умолчанию синтаксис функции range() выглядит следующим образом:
\\n\\n\\n\\nrange(stop)\\n
\\n\\n\\n\\nАргумент stop является обязательным.
\\n\\n\\n\\nФункция range() возвращает последовательность чисел, начинающуюся с 0, увеличивающуюся на 1 и заканчивающуюся на значении, которое вы указали в качестве stop (не включительно).
\\n\\n\\n\\nНо что если вы хотите выполнить итерацию по диапазону из двух указанных вами чисел и не хотите начинать отсчет с 0?
\\n\\n\\n\\nВы можете передать второй необязательный аргумент start, start, чтобы указать начальное число. Синтаксис для этого выглядит следующим образом:
\\n\\n\\n\\nrange(start, stop)\\n
\\n\\n\\n\\nЭтот синтаксис генерирует последовательность чисел на основе значений start (включительно) и stop (не включительно), которые увеличиваются на 1.
\\n\\n\\n\\nИ наконец, если вы не хотите, чтобы по умолчанию инкремент был равен 1, вы можете указать третий необязательный аргумент, step. Синтаксис для этого выглядит следующим образом:
\\n\\n\\n\\nrange(start, stop, step)\\n
\\n\\n\\n\\nЭтот синтаксис генерирует последовательность чисел, которая начинает отсчет с start (включительно) и увеличивается в соответствии с шагом, пока не достигнет stop (не включительно).
\\n\\n\\n\\nПри использовании только аргумента stop в функции range() подсчет начинается с 0 и увеличивается на 1. Подсчет останавливается при достижении значения, указанного в качестве stop.
\\n\\n\\n\\nПомните, что указанное значение stop не является полным!
\\n\\n\\n\\nЕсли вы укажете аргумент stop, равный 5, диапазон будет включать числа 0 – 4, а не 0 – 5 – подсчет остановится на 4, а не на 5.
\\n\\n\\n\\nДавайте посмотрим на пример ниже:
\\n\\n\\n\\nfor num in range(5):\\n print(num)\\n \\n# output \\n\\n# 0\\n# 1\\n# 2\\n# 3\\n# 4\\n
\\n\\n\\n\\nВ этом примере я указал range(5).
\\n\\n\\n\\nФункция начала отсчет с 0, увеличивала на 1 на каждой итерации и закончила на 4.
\\n\\n\\n\\nЕсли вы хотите получить диапазон из двух чисел, вы используете два аргумента – start и stop. Имейте в виду, что значение start является инклюзивным, а значение stop – нет.
\\n\\n\\n\\nЕсли вам нужен диапазон значений от 5 включительно до 10 включительно, вы напишете range(5,11) следующим образом:
\\n\\n\\n\\nfor num in range(5,11):\\n print(num)\\n \\n# output\\n\\n# 5\\n# 6\\n# 7\\n# 8\\n# 9\\n# 10\\n
\\n\\n\\n\\nВ range() можно передавать и отрицательные целые значения:
\\n\\n\\n\\nfor num in range(-5, 1):\\n print(num)\\n\\n# output\\n\\n# -5\\n# -4\\n# -3\\n# -2\\n# -1\\n# 0\\n
\\n\\n\\n\\nСледует отметить, что в range() нельзя передавать значения с плавающей точкой.
\\n\\n\\n\\nВ этом примере, когда я передаю два значения с плавающей точкой в качестве аргументов, возникает ошибка:
\\n\\n\\n\\nfor num in range(5.2, 4.3):\\n print(num)\\n\\n# output\\n\\n# Traceback (most recent call last):\\n# File \\\"main.py\\\", line 1, in <module>\\n# for num in range(5.2, 4.3):\\n# TypeError: 'float' object cannot be interpreted as an integer\\n
\\n\\n\\n\\nВ качестве аргументов start и stop можно передавать как отрицательные, так и положительные целые числа.
\\n\\n\\n\\nКак использовать функцию range() с аргументами start, stop и step
\\n\\n\\n\\nПо умолчанию значение инкремента равно 1 и не указывается. Однако его можно изменить, передав в функцию range() аргумент step.
\\n\\n\\n\\nДавайте рассмотрим следующий пример:
\\n\\n\\n\\nfor num in range(10,21,2):\\n print(num)\\n \\n# output\\n\\n# 10\\n# 12\\n# 14\\n# 16\\n# 18\\n# 20\\n
\\n\\n\\n\\nВ приведенном примере я создал последовательность чисел от 10 до 20 и увеличил шаги на 2. Я достиг этого, указав значение шага 2.
\\n\\n\\n\\nСледует отметить, что step может быть как отрицательным, так и положительным числом, но он не может быть равен 0.
\\n\\n\\n\\nВот как можно сгенерировать диапазон с отрицательным аргументом step:
\\n\\n\\n\\nfor num in range(20, 11, -2):\\n print(num)\\n\\n# output\\n\\n# 20\\n# 18\\n# 16\\n# 14\\n# 12\\n
\\n\\n\\n\\nПриведенный выше код генерирует последовательность чисел в обратном порядке.
\\n\\n\\n\\nПосмотрите, что происходит, когда шаг равен 0:
\\n\\n\\n\\nfor num in range(10, 21 0):\\n print(num)\\n\\n# output\\n\\n# File \\\"main.py\\\", line 1\\n# for num in range(10, 21 0):\\n ^\\n# SyntaxError: invalid syntax\\n
\\n\\n\\n\\nВы можете создать список чисел, передав функцию range() в качестве аргумента конструктору list() следующим образом:
\\n\\n\\n\\nmy_numbers_list = list(range(5))\\n\\nprint(my_numbers_list)\\n\\n# output\\n\\n# [0, 1, 2, 3, 4]\\n
\\n\\n\\n\\nВ приведенном выше примере я создал список чисел от 0 до 4.
\\n\\n\\n\\nДопустим, у вас есть список элементов и вы хотите что-то сделать с элементами в зависимости от длины списка.
\\n\\n\\n\\nДля этого вы можете использовать функцию range() и передать ей в качестве аргумента длину списка.
\\n\\n\\n\\nЧтобы вычислить длину списка, используйте функцию len().
\\n\\n\\n\\nprogramming_languages = [\\\"Python\\\", \\\"JavaScript\\\", \\\"Java\\\", \\\"C++\\\"]\\n\\nprogramming_languages_length = len(programming_languages)\\n\\nfor languages in range(programming_languages_length):\\n print(\\\"Hello World\\\")\\n \\n# output\\n\\n# Hello World\\n# Hello World\\n# Hello World\\n# Hello World\\n
\\n\\n\\n\\nВот и все! Теперь вы знаете, как использовать функцию range() в Python.
\\n\\n\\n\\nСпасибо, что дочитали, и счастливого кодинга!
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
В этой статье вы узнаете, как использовать функцию range() в Python с некоторыми примерами кода по ходу дела. Что такое функция range() в Python? Разбивка синтаксиса функции range() Встроенная в Python функция range() в основном используется при работе с циклами for – с ее помощью вы можете перебирать определенные блоки кода заданное количество раз. Функция […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/python-range-primer-funkczii/\"],\"title\":[0,\"Python Range() Пример функции - Gorlov.\"],\"breadcrumbTitle\":[0,\"Python range() Пример функции\"],\"description\":[0,\"В этой статье вы узнаете, как использовать функцию range() в Python с некоторыми примерами кода по ходу дела.\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"В этой статье вы узнаете, как использовать функцию range() в Python с некоторыми примерами кода по ходу дела.\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Python Range() Пример функции - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T22:09:54+00:00\"],\"url\":[0,\"http://igorlov.loc/python-range-primer-funkczii/\"]}]}],\"title\":[0,\"Python range() Пример функции\"],\"uri\":[0,\"/python-range-primer-funkczii/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"python-range-primer-funkczii\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Python\\\"],\\\"id\\\":[0,\\\"dGVybTo2NA==\\\"],\\\"uri\\\":[0,\\\"/tag/python/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0NjA=\"],\"node\":[0,{\"date\":[0,\"2023-03-19T21:48:01\"],\"content\":[0,\"\\nЧтобы ускорить выполнение, мы обычно выполняем код параллельно.
Одним из способов одновременного выполнения кода в JavaScript является одновременный вызов множества обещаний без ожидания их результатов, затем вы используете Promise.all для ожидания завершения всех обещаний. Посмотрите пример ниже:
const promiseA = asyncFnA();\\nconst promiseB = asyncFnB();\\n\\nconst results = await Promise.all([promiseA, promiseB]);\\n
\\n\\n\\n\\nПриведенный выше код будет выполнять asyncFnA и asyncFnB одновременно, а Promise.all будет ожидать выполнения обоих обещаний для разрешения.
\\n\\n\\n\\nДавайте посмотрим на этот код
\\n\\n\\n\\nconst users = await User.find(); // return all users in the database\\n\\nconst results = await Promise.all(users.map(async (user) => processUser(user));\\n
\\n\\n\\n\\nЭтот код будет выполнять столько обещаний, сколько пользователей в вашей базе данных. Node и JavaScript не очень хорошо справляются с одновременным выполнением многих обещаний, а Go справляется с этим хорошо.
Этот код, вероятно, будет потреблять много процессора и памяти и в итоге закончится.
Чтобы решить эту проблему, нам нужно обработать все эти обещания в пакетном режиме
export async function processPromisesBatch(\\n items: Array<any>,\\n limit: number,\\n fn: (item: any) => Promise<any>,\\n): Promise<any> {\\n let results = [];\\n for (let start = 0; start < items.length; start += limit) {\\n const end = start + limit > items.length ? items.length : start + limit;\\n\\n const slicedResults = await Promise.all(items.slice(start, end).map(fn));\\n\\n results = [\\n ...results,\\n ...slicedResults,\\n ]\\n }\\n\\n return results;\\n}\\n
\\n\\n\\n\\nUsage
\\n\\n\\n\\nconst results = await processPromisesBatch(users, 100, processUser)\\n
\\n\\n\\n\\nprocessPromisesBatch
нарежет ваши элементы на куски размером N и выполнит N обещаний одновременно.
Это гарантирует, что он не будет потреблять много процессора и памяти, а также не перегрузит цикл событий.
Понимание ограничений вашего языка программирования и среды выполнения может помочь вам разработать решение для их обхода.
\\n\\n\\n\\nПоделитесь решениями, которые вы разработали на основе ограничений вашего языка программирования, среды выполнения или фреймворка.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Одновременное выполнение кода Чтобы ускорить выполнение, мы обычно выполняем код параллельно.Одним из способов одновременного выполнения кода в JavaScript является одновременный вызов множества обещаний без ожидания их результатов, затем вы используете Promise.all для ожидания завершения всех обещаний. Посмотрите пример ниже: Приведенный выше код будет выполнять asyncFnA и asyncFnB одновременно, а Promise.all будет ожидать выполнения обоих обещаний […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/paketnaya-obrabotka-promisov/\"],\"title\":[0,\"Пакетная обработка промисов - Gorlov.\"],\"breadcrumbTitle\":[0,\"Пакетная обработка промисов\"],\"description\":[0,\"Чтобы ускорить выполнение, мы обычно выполняем код параллельно.Одним из способов одновременного выполнения кода в JavaScript является одновременный вызов\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Чтобы ускорить выполнение, мы обычно выполняем код параллельно.Одним из способов одновременного выполнения кода в JavaScript является одновременный вызов\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Пакетная обработка промисов - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T21:48:16+00:00\"],\"url\":[0,\"http://igorlov.loc/paketnaya-obrabotka-promisov/\"]}]}],\"title\":[0,\"Пакетная обработка промисов\"],\"uri\":[0,\"/paketnaya-obrabotka-promisov/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"paketnaya-obrabotka-promisov\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"JavaScript\\\"],\\\"id\\\":[0,\\\"dGVybTo0Mw==\\\"],\\\"uri\\\":[0,\\\"/tag/javascript/\\\"]}],[0,{\\\"name\\\":[0,\\\"Promise\\\"],\\\"id\\\":[0,\\\"dGVybToxODA=\\\"],\\\"uri\\\":[0,\\\"/tag/promise/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0NjE=\"],\"node\":[0,{\"date\":[0,\"2023-03-19T21:35:53\"],\"content\":[0,\"\\nКогда речь заходит об управлении и развертывании контейнерных приложений, на ум приходят два самых популярных варианта. Да, мы говорим о Kubernetes и Docker.
\\n\\n\\n\\nОба варианта широко используются, но у каждого из них есть свои нюансы, и в зависимости от того или иного сценария лучше выбрать тот или иной. В этой статье мы сравним различия между Kubernetes и Docker и посмотрим, в каких сценариях лучше использовать тот или иной вариант.
\\n\\n\\n\\nKubernetes, часто известный как K8s, — это платформа с открытым исходным кодом для автоматизации развертывания, масштабирования и администрирования контейнерных приложений. Она была создана компанией Google, и впоследствии была принята на вооружение многими предприятиями благодаря своей способности работать с крупномасштабными много узловыми установками.
\\n\\n\\n\\nKubernetes работает, предлагая стандартизированный набор абстракций для управления контейнерами, такими как капсулы, сервисы и тома. Эти абстракции позволяют легко развертывать, масштабировать и управлять контейнерами с высокой доступностью.
\\n\\n\\n\\nKubernetes может работать на двух различных типах узлов: узлах физических машин или узлах виртуальных машин. Контейнеры, запланированные Kubernetes, запускаются на этих узлах, чтобы убедиться, что они работают так, как должны работать.
\\n\\n\\n\\nЕго основными особенностями являются:
\\n\\n\\n\\nDocker – это бесплатная программная среда с открытым исходным кодом для управления контейнерами приложений. Используя контейнеры, разработчики могут упаковать приложение и все его зависимости в переносимый пакет. Простота использования Docker для управления контейнерами и образами дополняется надежностью его экосистемы в плане инструментов и сервисов, которые могут быть использованы для расширения его функциональности.
\\n\\n\\n\\nДля создания, выполнения и управления контейнерами Docker использует клиент-серверную архитектуру, в которой клиент взаимодействует с демоном Docker. Основная работа, такая как создание образа, запуск и остановка контейнеров, управление сетью и хранилищем для контейнеров, выполняется демоном Docker.
\\n\\n\\n\\nНекоторые из особенностей Docker следующие:
\\n\\n\\n\\nКогда речь идет об управлении крупномасштабными многоузловыми установками, Kubernetes часто выбирают предприятия благодаря его высокой доступности и хорошим возможностям оркестровки.
\\n\\n\\n\\nОрганизации также предпочитают Kubernetes из-за его высокой масштабируемости и одновременного управления множеством контейнеров.
\\n\\n\\n\\nDocker в данном случае является хорошим вариантом для тех компаний, которые только начинают использовать контейнеры и ищут в основном простоту.
\\n\\n\\n\\nКрупные организации также могут использовать Docker, поскольку им не требуются высокие возможности масштабирования или оркестровки.
\\n\\n\\n\\nПомимо предприятий, Docker также широко используется разработчиками, которым необходимо быстро разрабатывать и тестировать приложения в контейнерной среде.
\\n\\n\\n\\nВ заключение следует отметить, что выбор между Docker и Kubernetes зависит от ваших конкретных потребностей и сложности вашего проекта.
\\n\\n\\n\\nЕсли Docker представляет собой более простое решение для небольших одноконтейнерных приложений, то Kubernetes предлагает более надежные функции для управления несколькими контейнерами и масштабирования.
\\n\\n\\n\\nВыбор между этими двумя решениями в конечном итоге зависит от размера и масштаба вашего проекта, а также от знаний и опыта вашей команды.
\\n\\n\\n\\nКакое бы решение вы ни выбрали, важно учитывать ваши текущие и будущие потребности, чтобы убедиться, что вы выбрали правильный инструмент для достижения целей вашей организации.
\\n\\n\\n\\nНезависимо от выбора, и Docker, и Kubernetes зарекомендовали себя как ценные инструменты в мире контейнеризации и продолжают развиваться и совершенствоваться.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Когда речь заходит об управлении и развертывании контейнерных приложений, на ум приходят два самых популярных варианта. Да, мы говорим о Kubernetes и Docker. Оба варианта широко используются, но у каждого из них есть свои нюансы, и в зависимости от того или иного сценария лучше выбрать тот или иной. В этой статье мы сравним различия между […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/kubernetes-vs-docker-most-important-differences/\"],\"title\":[0,\"Kubernetes Vs Docker: Most Important Differences - Gorlov.\"],\"breadcrumbTitle\":[0,\"Kubernetes vs Docker: Most Important Differences\"],\"description\":[0,\"Когда речь заходит об управлении и развертывании контейнерных приложений, на ум приходят два самых популярных варианта. Да, мы говорим о Kubernetes и Docker.\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Когда речь заходит об управлении и развертывании контейнерных приложений, на ум приходят два самых популярных варианта. Да, мы говорим о Kubernetes и Docker.\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Kubernetes Vs Docker: Most Important Differences - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T21:35:55+00:00\"],\"url\":[0,\"http://igorlov.loc/kubernetes-vs-docker-most-important-differences/\"]}]}],\"title\":[0,\"Kubernetes vs Docker: Most Important Differences\"],\"uri\":[0,\"/kubernetes-vs-docker-most-important-differences/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"kubernetes-vs-docker-most-important-differences\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Docker\\\"],\\\"id\\\":[0,\\\"dGVybToxNjc=\\\"],\\\"uri\\\":[0,\\\"/tag/docker/\\\"]}],[0,{\\\"name\\\":[0,\\\"Kubernetes\\\"],\\\"id\\\":[0,\\\"dGVybToxNDI=\\\"],\\\"uri\\\":[0,\\\"/tag/kubernetes/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0NjU=\"],\"node\":[0,{\"date\":[0,\"2023-03-18T21:57:23\"],\"content\":[0,\"\\nПроект act – это мощный инструмент, который можно использовать вместе с GitHub Actions для быстрого тестирования и доработки конвейера непрерывной интеграции и непрерывной доставки (CI/CD). С помощью act вы можете локально использовать контейнеры Docker для прямого запуска этапов в GitHub Actions. act помогает разработчикам запускать независимые этапы конвейера и в целом улучшает цикл обратной связи при построении конвейеров с помощью GitHub Actions.
\\n\\n\\n\\nВ этой статье мы представим act на примере проекта, установим его, а затем рассмотрим различные способы, которыми act может улучшить ваш опыт создания и тестирования GitHub Actions. Чтобы проследить за ходом работы, посмотрите мой пример проекта на GitHub. Давайте начнем!
\\n\\n\\n\\nПрежде чем приступить к работе с act, мы должны получить базовое представление о том, как работают GitHub Actions. Подобно CI/CD инструментам, таким как CircleCI, Jenkins и другим, GitHub Actions позволяют вам определить конвейер в YAML-файле. Затем GitHub будет запускать ваш конвейер при определенных событиях, которые могут включать открытие запроса на притяжение или слияние с основной веткой.
\\n\\n\\n\\nСинтаксис GitHub Actions выглядит следующим образом:
\\n\\n\\n\\nname: Node.js CI\\n'on':\\n push:\\n branches:\\n - master\\njobs:\\n build:\\n runs-on: ubuntu-latest\\n steps:\\n - uses: actions/checkout@v3\\n - name: Use Node.js 16.x\\n uses: actions/setup-node@v3\\n with:\\n node-version: 16.x\\n cache: npm\\n - run: npm install\\n - run: npm run build
\\n\\n\\n\\nВ приведенном выше примере действие GitHub Action определено с заданием сборки, которое проверяет ваш код, выполняет установку npm и собирает проект. У вас могут быть дополнительные задания, которые зависят от этого, но шаги могут быть и собственными действиями. Например, если вы хотите кэшировать модули node, вы можете просто добавить следующий код:
\\n\\n\\n\\n - run: npm install\\n - run: npm run build\\n - name: Cache node modules\\n uses: actions/cache@v3\\n env:\\n cache-name: cache-node-modules\\n with:\\n path: ~/.npm\\n key: >-\\n ${{ runner.os }}-build-${{ env.cache-name }}-${{\\n hashFiles('**/package-lock.json') }}\\n restore-keys: |\\n ${{ runner.os }}-build-${{ env.cache-name }}-
\\n\\n\\n\\nactions/cache@v3 – это собственное действие, которое выполняется как шаг в этом конвейере. Вы также можете создать эти действия. Например, включив их в своем репозитории GitHub, вы можете запускать CI/CD на pushes to master и другие события. В GitHub это выглядит следующим образом:
\\n\\n\\n\\nВы можете подробно рассмотреть различные этапы и даже просмотреть историю действий по мере их выполнения. В документации GitHub Actions есть подробное определение этого синтаксиса; я рекомендую ознакомиться с ним.
\\n\\n\\n\\nВ следующих разделах мы научимся делать все это локально, а не полагаться на консоль GitHub и события для тестирования нашего конвейера.
\\n\\n\\n\\nact работает как CLI на вашей локальной машине, поддерживая Linux, Mac и Windows. Я работаю на Mac, поэтому я использовал brew для установки act следующей командой:
\\n\\n\\n\\nbrew install act
\\n\\n\\n\\nЧтобы узнать больше об установке, ознакомьтесь с инструкциями в репозитории GitHub.
\\n\\n\\n\\nПосле установки act использовать его очень просто. Внутри папки .github в вашем репозитории вызовите CLI непосредственно с помощью act из терминала внутри проекта, в котором настроен YAML-файл действия GitHub. Если у вас еще не настроены действия GitHub, нажмите на опцию actions в верхней части вашего проекта GitHub, и GitHub проведет вас через создание начального YAML-файла:
\\n\\n\\n\\nСуществует множество различных вариантов, но наиболее полезными мне показались следующие:
\\n\\n\\n\\n# List all the actions in your YAML file\\nact -l\\n\\n# List actions for a specific event (here the event is push)\\nact push -l\\n\\n# Get Act to run the workflow as if a specific push to master event occured\\nact push\\n\\n# Get Act to run a specific job\\nact -j test\\n\\n# pass secrets into a job so that the GitHub action can consume them\\nact -s MY_TOKEN_SECRET=<token> -s MY_NETLIFY_SITE_ID=<site_id> \\n\\n# run a GitHub action that uses artifacts between jobs\\nact --artifact-server-path /tmp/artifacts push\\n
\\n\\n\\n\\nПри выполнении этих команд act создает контейнер Docker для запуска ваших действий на GitHub. Образы, перечисленные в проекте act на GitHub, включают следующие:
\\n\\n\\n\\nЕсли в задании GitHub Action указан образ для использования, оно извлекает этот образ и запускает его в контейнере act для выполнения работы.
\\n\\n\\n\\nКак я уже говорил во вступлении, я использовал пример проекта с Act для проверки некоторых функций. Проект представляет собой очень простое, базовое приложение для составления списка дел на React. Я включил один тест, для которого я мог создать этап в конвейере, а также включил этап для развертывания в Netlify.
\\n\\n\\n\\nКод ниже представляет собой фактический YAML-файл, который я создал для GitHub Actions в этом проекте:
\\n\\n\\n\\nname: Node.js CI\\n'on':\\n push:\\n branches:\\n - master\\njobs:\\n build:\\n runs-on: ubuntu-latest\\n steps:\\n - uses: actions/[email protected]\\n - name: Use Node.js 16.x\\n uses: actions/[email protected]\\n with:\\n node-version: 16.x\\n cache: npm\\n - run: npm install\\n - run: npm run build\\n - name: Cache node modules\\n uses: actions/[email protected]\\n env:\\n cache-name: cache-node-modules\\n with:\\n path: ~/.npm\\n key: >-\\n ${{ runner.os }}-build-${{ env.cache-name }}-${{\\n hashFiles('**/package-lock.json') }}\\n restore-keys: |\\n ${{ runner.os }}-build-${{ env.cache-name }}-\\n - name: Archive production artifacts\\n uses: actions/[email protected]\\n with:\\n name: built-project\\n path: build\\n retention-days: 1\\n test:\\n needs: build\\n runs-on: ubuntu-latest\\n steps:\\n - uses: actions/[email protected]\\n - name: Use Node.js 16.x\\n uses: actions/[email protected]\\n with:\\n node-version: 16.x\\n cache: npm\\n - name: Download build for testing\\n uses: actions/[email protected]\\n with:\\n name: built-project\\n - run: npm install\\n - run: npm run pipeline-test\\n deploy:\\n needs: [build, test]\\n runs-on: ubuntu-latest\\n name: 'Deploy to Netlify'\\n steps:\\n - uses: actions/[email protected]\\n - name: Download build for deployment\\n uses: actions/[email protected]\\n with:\\n name: built-project\\n - uses: jsmrcaga/[email protected]\\n with:\\n NETLIFY_AUTH_TOKEN: ${{ secrets.MY_TOKEN_SECRET }}\\n NETLIFY_SITE_ID: ${{ secrets.MY_NETLIFY_SITE_ID }}\\n NETLIFY_DEPLOY_TO_PROD: true\\n build_command: \\\"echo build command not required since we are using artifacts\\\"\\n
\\n\\n\\n\\nКак видите, у меня три разных работы:
\\n\\n\\n\\nЗадание тестирования зависит от задания сборки, а задание развертывания зависит от заданий тестирования и сборки. Я также использовал кэширование и хранение артефактов между этапами. Эти темы выходят за рамки данной статьи, но для справки я рекомендую ознакомиться с документацией по Actions на GitHub.
\\n\\n\\n\\nИспользуя Act в этом конвейере, я смог сделать несколько вещей, включая независимый запуск заданий, а также прямой просмотр данных о заданиях. Мне это показалось очень полезным, поскольку я мог строить конвейер без необходимости напрямую взаимодействовать с консолью GitHub. Это сэкономило значительное время, которое в противном случае я бы потратил на развертывание и обновление YAML-файла, а затем на ожидание завершения работы консоли.
\\n\\n\\n\\nВ примере проекта я перечислил связанные задания следующим образом:
\\n\\n\\n\\n➜ getting-started-with-act git:(master) act -l\\nWARN ⚠ You are using Apple M1 chip and you have not specified container architecture, you might encounter issues while running act. If so, try running it with '--container-architecture linux/amd64'. ⚠ \\nStage Job ID Job name Workflow name Workflow file Events\\n0 build build Node.js CI node.js.yml push \\n1 test test Node.js CI node.js.yml push \\n2 deploy Deploy to Netlify Node.js CI node.js.yml push \\n
\\n\\n\\n\\nПредупреждающее сообщение указывает на то, что Act заметил тип машины, которую я использую. Если бы я захотел, я мог бы указать архитектуру и избежать появления этого сообщения. Далее я рассмотрю зависимости заданий от события push:
\\n\\n\\n\\n➜ getting-started-with-act git:(master) act push -l\\nWARN ⚠ You are using Apple M1 chip and you have not specified container architecture, you might encounter issues while running act. If so, try running it with '--container-architecture linux/amd64'. ⚠ \\nStage Job ID Job name Workflow name Workflow file Events\\n0 build build Node.js CI node.js.yml push \\n1 test test Node.js CI node.js.yml push \\n2 deploy Deploy to Netlify Node.js CI node.js.yml push \\n
\\n\\n\\n\\nЕсли я просто хочу запустить задание сборки независимо, я использую приведенный ниже код:
\\n\\n\\n\\n➜ getting-started-with-act git:(master) act -j build\\nWARN ⚠ You are using Apple M1 chip and you have not specified container architecture, you might encounter issues while running act. If so, try running it with '--container-architecture linux/amd64'. ⚠ \\n[Node.js CI/build] 🚀 Start image=node:16-buster-slim\\n[Node.js CI/build] 🐳 docker pull image=node:16-buster-slim platform= username= forcePull=false\\n[Node.js CI/build] 🐳 docker create image=node:16-buster-slim platform= entrypoint=[\\\"tail\\\" \\\"-f\\\" \\\"/dev/null\\\"] cmd=[]\\n[Node.js CI/build] 🐳 docker run image=node:16-buster-slim platform= entrypoint=[\\\"tail\\\" \\\"-f\\\" \\\"/dev/null\\\"] cmd=[]\\n[Node.js CI/build] ☁ git clone 'https://github.com/actions/setup-node' # ref=v3\\n[Node.js CI/build] ☁ git clone 'https://github.com/actions/cache' # ref=v3\\n[Node.js CI/build] ☁ git clone 'https://github.com/actions/upload-artifact' # ref=v3\\n[Node.js CI/build] ⭐ Run Main actions/[email protected]\\n[Node.js CI/build] 🐳 docker cp src=/Users/andrewevans/Documents/projects/getting-started-with-act/. dst=/Users/andrewevans/Documents/projects/getting-started-with-act\\n[Node.js CI/build] ✅ Success - Main actions/[email protected]\\n[Node.js CI/build] ⭐ Run Main Use Node.js 16.x\\n[Node.js CI/build] 🐳 docker cp src=/Users/andrewevans/.cache/act/[email protected]/ dst=/var/run/act/actions/[email protected]/\\n[Node.js CI/build] 🐳 docker exec cmd=[node /var/run/act/actions/[email protected]/dist/setup/index.js] user= workdir=\\n[Node.js CI/build] 💬 ::debug::isExplicit: \\n[Node.js CI/build] 💬 ::debug::explicit? false\\n
\\n\\n\\n\\nЕсли я хочу запустить задания сборки и тестирования вместе, мне нужно указать местоположение для артефактов. Действие GitHub Action, передающее артефакты между заданиями, использует местоположение по умолчанию на серверах GitHub.
\\n\\n\\n\\nПоскольку я запускаю его локально в контейнере Docker, мне нужно указать местоположение, которое он будет использовать в контейнере. На изображениях ниже вы можете видеть, как задание запускается, а затем успешно создается и сохраняется артефакт:
\\n\\n\\n\\n[Node.js CI/build] 🐳 docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/3] user= workdir=\\n| \\n| > [email protected] build\\n| > react-scripts build\\n| \\n| Creating an optimized production build...\\n| Compiled successfully.\\n| \\n| File sizes after gzip:\\n| \\n| 47.11 kB build/static/js/main.172f414d.js\\n| 1.79 kB build/static/js/787.de4328d8.chunk.js\\n| 313 B build/static/css/main.51a848c0.css\\n| \\n| The project was built assuming it is hosted at /.\\n| You can control this with the homepage field in your package.json.\\n| \\n| The build folder is ready to be deployed.\\n| You may serve it with a static server:\\n| \\n| npm install -g serve\\n| serve -s build\\n| \\n| Find out more about deployment here:\\n| \\n| https://cra.link/deployment\\n| \\n[Node.js CI/build] ✅ Success - Main npm run build\\n[Node.js CI/build] ⭐ Run Main Cache node modules\\n
\\n\\n\\n\\nЧасто у вас есть секреты, которые нужно передать определенным заданиям. При работе с act это можно сделать непосредственно в командной строке с помощью следующего кода:
\\n\\n\\n\\nact -s MY_SECRET=<first_secret> push \\n
\\n\\n\\n\\nЕсть много других вещей, которые можно делать с помощью act в процессе разработки. Мне показалось очень полезным иметь возможность запускать задания независимо для отладки возникающих проблем.
\\n\\n\\n\\nКак я уже говорил ранее, я также включил этап развертывания для загрузки артефактов в Netlify. У меня были некоторые проблемы с передачей маркеров, и в конечном итоге я понял, что это была проблема со способом генерации маркера в Netlify. Тем не менее, вы можете видеть, как можно использовать этап развертывания. Вы можете протестировать это с другими провайдерами, такими как AWS, Azure и т.д.
\\n\\n\\n\\nЭта статья – лишь вершина айсберга того, что вы можете сделать с помощью act. Запустив Docker вместе с act, я смог увидеть запущенные контейнеры и образы, которые были стянуты. Я также прошел через множество итераций, выполняя части заданий, а затем обращаясь к документации, чтобы очистить код. Это очень помогло в разработке конвейера, даже если он был очень простым.
\\n\\n\\n\\nЯ настоятельно рекомендую ознакомиться с проектом act и прочитать о нем больше в README репозитория. Я обнаружил, что у act довольно сильное сообщество, поэтому все проблемы, которые я видел, обычно имели связанную с ними проблему на GitHub, к которой я мог обратиться за помощью.
\\n\\n\\n\\nСпасибо за чтение!
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Проект act – это мощный инструмент, который можно использовать вместе с GitHub Actions для быстрого тестирования и доработки конвейера непрерывной интеграции и непрерывной доставки (CI/CD). С помощью act вы можете локально использовать контейнеры Docker для прямого запуска этапов в GitHub Actions. act помогает разработчикам запускать независимые этапы конвейера и в целом улучшает цикл обратной связи […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/rukovodstvo-po-ispolzovaniyu-act-s-github-actions/\"],\"title\":[0,\"Руководство по использованию Act с GitHub Actions - Gorlov.\"],\"breadcrumbTitle\":[0,\"Руководство по использованию act с GitHub Actions\"],\"description\":[0,\"Проект act - это мощный инструмент, который можно использовать вместе с GitHub Actions для быстрого тестирования и доработки конвейера непрерывной интеграции\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Проект act - это мощный инструмент, который можно использовать вместе с GitHub Actions для быстрого тестирования и доработки конвейера непрерывной интеграции\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Руководство по использованию Act с GitHub Actions - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-18T21:59:46+00:00\"],\"url\":[0,\"http://igorlov.loc/rukovodstvo-po-ispolzovaniyu-act-s-github-actions/\"]}]}],\"title\":[0,\"Руководство по использованию act с GitHub Actions\"],\"uri\":[0,\"/rukovodstvo-po-ispolzovaniyu-act-s-github-actions/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"rukovodstvo-po-ispolzovaniyu-act-s-github-actions\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"JavaScript\\\"],\\\"id\\\":[0,\\\"dGVybTo0Mw==\\\"],\\\"uri\\\":[0,\\\"/tag/javascript/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0ODA=\"],\"node\":[0,{\"date\":[0,\"2023-03-18T21:35:51\"],\"content\":[0,\"\\nНачну с того, что я очень не люблю сметное дело. В большинстве случаев это похоже на облизывание пальца и засовывание его в воздух, а в других случаях – еще хуже! Между необходимостью (обычно) количественно оценить большое количество неизвестных, которые могут замедлить работу, вы должны попытаться спланировать, не уйдет ли коллега, помогающий вам, на больничный (по праву) как раз перед тем, как появится крупная зависимость. Когда вы, наконец, даете оценку, для людей, которым вы ее даете, это не оценка, а гарантия, и когда это не происходит по множеству причин, вы получаете довольно неудобную встречу, где вам приходится пытаться объяснить, почему вы не сделали то, что обещали. Это чувство настолько укоренилось в разработке программного обеспечения, что существует довольно распространенная “шутка” на этот счет:
\\n\\n\\n\\nЧеловек: Эй, у нас есть очень крутая функция, которую нужно добавить! Все, что вам нужно сделать, это добавить кнопку в форму\\r\\nРазработчик: 3 недели.\\r\\nЧеловек: но это просто добавление кнопки?\\r\\nРазработчик: конечно, это займет 4 недели.\\n
\\n\\n\\n\\nОднако все это не имеет значения, потому что бизнесу нужна эта информация для прогнозирования будущих работ, и если этого не произойдет, компания может прекратить свою деятельность. Поэтому, как бы мне ни не нравилось составлять сметы, это все же ключевой навык для любого разработчика.
\\n\\n\\n\\nИтак, мы выяснили, что все мы должны знать, как составлять сметы, но есть небольшая проблема в том, как разработчик на самом деле составляет смету. Я уверен, что большинство из нас, имеющих небольшой опыт, просто выкидывали число и были достаточно точны в этом прогнозе, не задумываясь об этом. Конечно, это совершенно бесполезно, когда вы пытаетесь научиться оценивать, и вы можете прочитать такие статьи, как эта от Time Camp, в которых рассматривается достаточное количество отдельных методов, которые вы можете использовать для оценки. Однако на мой взгляд, реальный ответ на этот вопрос – использовать смесь техник, которые могут дать вам оценку менее чем за 30 секунд (на самом деле за 10) – дольше, и вы, вероятно, слишком много думаете, или задача слишком велика, и вам нужно разбить ее на части. Сказав это, вот как я лично оцениваю задачи.
\\n\\n\\n\\nДля меня оценку можно разделить на три части. Получение фактической оценки, преобразование того, сколько времени, по моему мнению, это займет, в реалистичную оценку и, наконец, как донести эту оценку до бизнеса. Я разложил все это ниже.
\\n\\n\\n\\nКогда я думаю о том, сколько времени что-то займет, я, по сути, задаю себе вопросы, как показано на приведенной ниже блок-схеме, чтобы попытаться составить точную смету:
\\n\\n\\n\\nПРИМЕЧАНИЕ: Приведенное выше – это не все, а лишь пример вопросов, которые вы должны задать себе, прежде чем дать оценку. Например, если код, который я пишу, использует интересную технологию, я, вероятно, немного сокращу время, просто потому, что я вложил в него дополнительную работу.
\\n\\n\\n\\nСуществует несколько методик, которые вы можете использовать для этого, но я собираюсь обсудить две из наиболее распространенных.
\\n\\n\\n\\nЧестно говоря, я уже не так часто использую эту методику, но когда я начинал и не знал, что делать, оценка по трем точкам помогает представить проблему в легко усваиваемом виде.
\\n\\n\\n\\nПРИМЕЧАНИЕ: Оценка по трем точкам – это конечная точка оценки, т.е. после того, как вы прошли через другие шаги, пытаясь определить, сколько времени займет задача.
\\n\\n\\n\\nХотя существует несколько способов получить оценку по трем точкам, нас больше всего интересует самый быстрый способ, поэтому мы будем использовать самый простой.
\\n\\n\\n\\nПо сути, вы задаете себе эти три вопроса:
\\n\\n\\n\\nЗатем вы делите эти 3 оценки на 3 и затем умножаете их на 3. Например: Я получаю задание добавить кнопку в форму и, основываясь на том, что я знаю, оптимистично это займет у меня час, реалистично – 4 часа, а пессимистично – 2 дня.
\\n\\n\\n\\nЭто дает следующее:
\\n\\n\\n\\n1+4+163=7
{1 + 4 + 16 \\\\over 3} = 7
31+4+16=7
Так как это близко к 8 часам, я бы просто округлил до полного 8-часового дня, так как это достаточно близко.
\\n\\n\\n\\nЭто действительно простой способ оценки, и, по моему опыту, это самый популярный способ выполнения данного задания. Я бы не рекомендовал его новичкам, так как легко ошибиться, но, по сути, вы берете время, которое, по вашему мнению, потребуется, прибавляете 20% и округляете до ближайших 4 часов, 1 дня, 1,5 дня, 2 дней, 3 дней, 4 дней и 1 недели. Если больше, то задачу следует разделить на части.
\\n\\n\\n\\nТ.е:
\\n\\n\\n\\n8×1.2=9.6
8\\\\times 1.2 = 9.6
8×1.2=9.6
Затем я беру оценку 9,6 и округляю до 1,5 дня.
\\n\\n\\n\\nЭто (обычно) гораздо менее точно, чем оценка по трем пунктам, но в большинстве случаев позволяет получить результат. На мой взгляд, несмотря на более простой расчет, этот способ на самом деле сложнее, так как он предполагает полное понимание решения, прежде чем вы сможете дать точную оценку, и, как я уже говорил, на него лучше не полагаться, если вы новичок в оценке.
\\n\\n\\n\\nПередача информации может быть разделена на две части. Что делать, когда вы составляете смету, и что делать во время работы над задачей.
\\n\\n\\n\\nКогда вы находитесь на встрече и вас просят дать оценку, вот несколько советов:
\\n\\n\\n\\nПотратьте несколько секунд на обдумывание, прежде чем ответить.
\\n\\n\\n\\nДаже если вы уже знаете, что вас попросят сделать, всегда стоит потратить несколько секунд на обдумывание ответа в голове, поскольку это последний шанс, прежде чем смета закрепится в сознании людей. Это неоднократно помогало мне вспомнить одну мелочь, которую я забыл учесть, что позволило мне сделать более точную оценку.
\\n\\n\\n\\nБудьте честны
\\n\\n\\n\\nЯ знаю, что иногда на вас будут давить, заставляя дать более короткую смету, чем вы ожидаете на самом деле. Если это происходит с вами, поверьте мне, будет гораздо менее неловко объяснить это сейчас, чем когда вам придется сказать тем же людям, которые давят на вас, что это займет больше времени, чем вы сказали.
\\n\\n\\n\\nБудьте честны с собой
\\n\\n\\n\\nЕсли вы выкидываете оценки, которые, по вашему мнению, могут быть возможными, но исторически они занимают у вас гораздо больше времени (а также постоянно приходится объяснять руководителю проекта, почему это занимает больше времени), вероятно, вам стоит взглянуть на свой процесс оценки.
\\n\\n\\n\\nНе паникуйте
\\n\\n\\n\\nЕсли вы новичок в процессе составления смет, и окружающие вас люди знают, что если вы ошибетесь, то это не такая уж большая проблема, поскольку вы с каждым разом становитесь все ближе. Мы все были там, где вы, и это нелегко сделать, когда вы только начинаете.
\\n\\n\\n\\nОбъясните свои доводы.
\\n\\n\\n\\nЯ имею в виду, что нужно просто сказать короткую фразу, показывающую, что вы понимаете задание, и сформулировать ожидания относительно трудностей, которые могут у вас возникнуть. Например, если я знаю, что у меня есть зависимость от другой команды, я, вероятно, скажу что-то вроде “Я смогу сделать это завтра к концу дня, при условии, что я получу зависимость X в ближайшие пару часов”.
\\n\\n\\n\\nПосле составления сметы вы можете предпринять некоторые действия, чтобы постараться выполнить задание в срок, а также смягчить проблемы, если вы ошиблись:
\\n\\n\\n\\nТаймбоксинг
\\n\\n\\n\\nСуществует множество руководств по этому вопросу (например, вот это от clockify), но в двух словах это практика выделения определенного времени в течение дня, когда вы пытаетесь выполнить задачу.
\\n\\n\\n\\nОбщайтесь
\\n\\n\\n\\nЕсли вы сказали, что выполнение задачи займет неделю, и каждый день вы говорите, что все идет хорошо, вплоть до последнего дня, когда вы вдруг говорите, что вам понадобится еще неделя, вы, скорее всего, напрашиваетесь на гневные вопросы. Всегда лучше убедиться, что руководитель проекта понимает, как у вас идут дела, и, на мой взгляд, это основная причина для ежедневных совещаний. Если ваша команда по каким-то причинам не проводит ежедневный стендап, то у вас, вероятно, есть доступ к средству обмена мгновенными сообщениями, и вы можете использовать его вместо этого.
\\n\\n\\n\\nНе волнуйтесь, если вы ошибетесь
\\n\\n\\n\\nВсе мы в какой-то момент оказывались в подобном положении, и лучшее, что можно сделать, это не слишком переживать по этому поводу и сообщить кому-то, что вам может понадобиться помощь и почему у вас возникли проблемы. Проблемы возникнут не из-за недооценки, а из-за того, что вы попытаетесь это скрыть.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Справочная информация Начну с того, что я очень не люблю сметное дело. В большинстве случаев это похоже на облизывание пальца и засовывание его в воздух, а в других случаях – еще хуже! Между необходимостью (обычно) количественно оценить большое количество неизвестных, которые могут замедлить работу, вы должны попытаться спланировать, не уйдет ли коллега, помогающий вам, на […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/rukovodstvo-po-oczenke-dlya-razrabotchikov/\"],\"title\":[0,\"Руководство по оценке для разработчиков - Gorlov.\"],\"breadcrumbTitle\":[0,\"Руководство по оценке для разработчиков\"],\"description\":[0,\"Начну с того, что я очень не люблю сметное дело. В большинстве случаев это похоже на облизывание пальца и засовывание его в воздух, а в других случаях - еще\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Начну с того, что я очень не люблю сметное дело. В большинстве случаев это похоже на облизывание пальца и засовывание его в воздух, а в других случаях - еще\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Руководство по оценке для разработчиков - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-18T21:45:54+00:00\"],\"url\":[0,\"http://igorlov.loc/rukovodstvo-po-oczenke-dlya-razrabotchikov/\"]}]}],\"title\":[0,\"Руководство по оценке для разработчиков\"],\"uri\":[0,\"/rukovodstvo-po-oczenke-dlya-razrabotchikov/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"rukovodstvo-po-oczenke-dlya-razrabotchikov\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Управление\\\"],\\\"id\\\":[0,\\\"dGVybToxNzk=\\\"],\\\"uri\\\":[0,\\\"/tag/upravlenie/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0NjY=\"],\"node\":[0,{\"date\":[0,\"2023-03-18T01:05:36\"],\"content\":[0,\"\\nВеб-скрейпинг, если говорить простым языком, – это техника, используемая для сбора полезных данных с веб-сайта. Согласитесь, в Интернете есть масса информации, и чаще всего она может быть структурирована не совсем так, как нам нужно. Таким образом, веб-скрейпинг позволяет нам извлекать данные из Интернета, которые затем можно реструктурировать или перестроить так, чтобы они были полезны для нас.
\\n\\n\\n\\nВ этой статье я проведу вас шаг за шагом через процесс веб-скрейпинга, дам полезные советы по развитию ваших навыков, подскажу, что делать и чего не делать при скрейпинге веб-сайтов (в частности, о нарушении авторских прав), и многое другое. Кроме того, мы будем скреативить два сайта, CoinMarketCap и Bitcoin.com, чтобы получить цены на криптовалюты и последние новости о Bitcoin.
\\n\\n\\n\\n\\n\\n\\n\\n\\nПозвольте мне быстро познакомить вас с двумя пакетами: requests и BeautifulSoup. Это библиотеки Python, которые используются для соскабливания веб-сайтов. В этой статье они нам понадобятся.
\\n
Когда вы заходите в браузер и вводите url сайта, который хотите посетить, ваш браузер делает запрос на сервер. Затем сервер отвечает вашему браузеру. Браузер получает данные от сервера в виде текста, HTML, JSON или многокомпонентного запроса (медиафайла).
\\n\\n\\n\\nКогда браузер получает HTML, он анализирует его, создает узлы DOM и отображает их на странице, выводя прекрасный веб-сайт на ваш экран.
\\n\\n\\n\\nПри скрейпинге веб-сайтов нам нужен этот HTML-контент, и это знакомит нас с первыми пакетными запросами.
\\n\\n\\n\\nКак следует из названия, он используется для отправки запросов на серверы. Если у вас есть опыт разработки фронтенда или Javascript, это эквивалент fetch API в Javascript.
\\n\\n\\n\\nДля того чтобы мы могли соскабливать содержимое сайта, нам нужно убедиться, что конечная точка сервера, к которой мы обращаемся, возвращает HTML.
\\n\\n\\n\\nПосле получения HTML следующим шагом будет сбор нужных нам данных. И это приводит нас ко второму пакету BeautifulSoup.
\\n\\n\\n\\nBeautiful Soup – это библиотека, используемая для извлечения данных из HTML и XML файлов. Beautiful soup содержит множество очень полезных утилит, которые делают веб-скрейпинг действительно простым.
\\n\\n\\n\\nПосле долгих разговоров перейдем к самой сути дела – написанию кода и созданию собственно веб-скреперов.
\\n\\n\\n\\nЯ создал репозиторий на Github, который содержит код для скреперов. Полный код находится в ветке completed, для начала работы перейдите в ветку get-started.
\\n\\n\\n\\nВ этой статье я буду создавать проект с нуля, для тех, кто не хочет клонировать репозиторий Github.
\\n\\n\\n\\nВыполните следующие команды для создания нового виртуального окружения
\\n\\n\\n\\n# if you've not already installed virtualenv\\npip install virtualenv\\n\\n# you can name your environment whatever you want\\npython -m venv <name_of_environment>\\n
\\n\\n\\n\\nПосле успешного выполнения предыдущих команд вы должны увидеть папку с именем виртуальной среды, которую вы только что создали.
\\n\\n\\n\\nВам также необходимо активировать виртуальную среду. Для этого выполните следующие команды в зависимости от вашей ОС.
\\n\\n\\n\\n# macOS / linux\\nsource ./<virtual_env_name>/bin/activate\\n\\n# windows\\n<virtual_env_name>/Scripts/activate.bat # In CMD\\n<virtual_env_name>/Scripts/Activate.ps1 # In Powershell\\n
\\n\\n\\n\\nУстановите необходимые пакеты.
\\n\\n\\n\\nАктивировав нашу виртуальную среду, давайте перейдем к установке пакетов. Для этого выполните в терминале следующие действия:
\\n\\n\\n\\npip install requests beautifulsoup4\\n
\\n\\n\\n\\nСоздайте файл requirements.txt.
\\n\\n\\n\\nЕсли вы будете делиться кодом с кем-то или командой, важно, чтобы другая сторона установила точно такую же версию пакета, которую вы использовали для сборки проекта. В используемом пакете могут быть изменения, поэтому важно, чтобы все использовали одну и ту же версию. Файл requirements.txt позволяет другим узнать точную версию пакетов, которые вы использовали в проекте.
\\n\\n\\n\\nЧтобы сгенерировать файл requirements.txt, просто выполните следующие действия:
\\n\\n\\n\\npip freeze > requirements.txt\\n
\\n\\n\\n\\nПосле выполнения этой команды вы должны увидеть файл, содержащий пакеты, необходимые для запуска проекта.
\\n\\n\\n\\nЕсли вы работаете в команде и в проекте есть файл requirements.txt, запустите pip install -r requirements.txt, чтобы установить точную версию пакетов из файла requirements.txt.
\\n\\n\\n\\nСколько раз я сказал про файл requirements.txt? 🤡
\\n\\n\\n\\nДобавьте файл .gitignore.
\\n\\n\\n\\nОн используется для указания git’у файлов или папок, которые следует игнорировать при запуске git add. Добавьте /<virtual_env_name> в файл .gitignore.
\\n\\n\\n\\nТеперь мы займемся скраппингом первого сайта. Первое, что нам нужно сделать, это получить HTML с запросами.
\\n\\n\\n\\nИтак, создайте файл bitcoinnews.py (вы можете назвать его как угодно).
\\n\\n\\n\\nДобавьте в файл следующий код
\\n\\n\\n\\nimport requests\\n\\ndef get_news():\\n url = '<https://news.bitcoin.com>'\\n\\n response = requests.get(url) # making a request\\n response_text = response.text # getting the html\\n\\n # here's where we should get the news content from the html, we're just printing the content to the terminal for now\\n print(response_text)\\n\\nget_news()\\n
\\n\\n\\n\\n\\n\\n\\n\\nПри сканировании веб-сайтов важно понимать основы HTML, поскольку это поможет нам выбрать наилучший способ извлечения данных.
\\n\\n\\n\\nHTML (HyperText Markup Language) – это стандартный язык разметки для создания веб-страниц. HTML используется для описания структуры веб-страницы. Элементы HTML – это строительные блоки каждой веб-страницы. Элементы HTML связаны друг с другом таким образом, что напоминают дерево.
\\n\\n\\n\\nНа схеме выше у нас есть корневой элемент, элемент <html>, который имеет два дочерних элемента, элементы <head> и <body>. У тега <head> есть один дочерний элемент, тег <, который имеет в качестве дочернего элемента простой текст. Элемент <body> имеет три дочерних элемента (один тег заголовка и два тега абзаца).
\\n\\n\\n\\nЭта древовидная структура облегчает компоновку элементов и определение отношений между ними. Это упрощает написание абзаца и включение в него ссылок.
\\n\\n\\n\\nЭлементы HTML, помимо наличия дочерних элементов, имеют атрибуты, которые добавляют им гораздо больше функциональности. Элемент ‘image’ требует указания источника изображения, которое он должен отображать. Когда вы нажимаете на ссылку (тег якоря), он должен знать, куда вы хотите перейти. Атрибуты также могут использоваться для различения одного элемента и группы элементов.
\\n\\n\\n\\nПонимание атрибутов HTML очень важно, поскольку при сканировании веб-сайта нам нужны конкретные данные, и важно, чтобы мы могли нацелиться на элементы, содержащие нужные нам данные.
\\n\\n\\n\\nЕсли вы хотите узнать больше об HTML, вы можете посетить сайт W3schools.com.
\\n\\n\\n\\nПрежде чем мы вернемся к нашему скреперу Bitcoin News, давайте соскребем цены ведущих криптовалют с CoinMarketCap вместе с изображениями.
\\n\\n\\n\\nСОВЕТ: Прежде чем приступить к скраппингу веб-сайта, отключите Javascript и откройте страницу в браузере. Это важно, потому что некоторые сайты отображают содержимое на веб-странице с помощью Javascript на стороне клиента, который не может быть использован нашими скреперами. Поэтому имеет смысл видеть только точный HTML, который возвращает сервер.
\\n\\n\\n\\nС запущенным Javascript
\\n\\n\\n\\nБез работающего Javascript
\\n\\n\\n\\nЕсли вы откроете сайт coinmarketcap.com в браузере с отключенным Javascript, вы заметите, что можете получить цены только на первые десять криптовалют. Вы также заметите, что в браузере, где включен Javascript, вы можете прокручивать страницу, чтобы получить цены на другие криптовалюты. Это различие во внешнем виде страницы (HTML) может доставить вам много неприятностей при скраппинге веб-сайта.
\\n\\n\\n\\nimport requests\\nfrom bs4 import BeautifulSoup\\n\\ndef get_crypto_prices():\\n url = '<https://coinmarketcap.com>'\\n response_text = requests.get(url).text\\n\\n soup = BeautifulSoup(response_text, 'html.parser') #added this line\\n\\n print(soup)\\n\\nget_crypto_prices()\\n
\\n\\n\\n\\nЭтот файл выглядит почти так же, как предыдущий, я только изменил URL и название функции, а также добавил строку с BeautifulSoup.
\\n\\n\\n\\nЭта строка кода анализирует HTML-текст, который мы получаем от конечной точки, и преобразует его в объект BeautifulSoup, который имеет методы, которые мы можем использовать для извлечения информации из текста.
\\n\\n\\n\\nТеперь, когда у нас есть доступ к HTML, давайте разберемся, как извлечь нужные нам данные: в нашем случае цены на криптовалюты.
\\n\\n\\n\\nОткройте DevTools в своем веб-браузере.
Если вы используете Chrome на Mac, вы можете нажать Cmd + Option + I, чтобы открыть DevTools.
Или вы можете просто щелкнуть правой кнопкой мыши на целевом элементе и нажать кнопку inspect.
\\n\\n\\n\\nЕсли вы посмотрите на элементы в разделе Inspect Element в Chrome DevTools, вы заметите, что там есть элемент table с дочерними элементами. Внутри элемента таблицы есть элементы colgroup, thead, tbody. Элемент tbody содержит все содержимое таблицы. Внутри элемента tbody есть элемент tr, обозначающий строку таблицы, который также содержит несколько элементов td. td обозначает данные таблицы.
\\n\\n\\n\\nТеперь просто знать, что нужные нам данные находятся в таблице, недостаточно. Мы должны углубиться в дерево HTML, чтобы извлечь именно те данные, которые нам нужны. В данном случае нам нужно название криптовалюты, сокращенное название, например, BTC для Bitcoin, текущая цена и изображение криптовалюты.
\\n\\n\\n\\nЕсли присмотреться, можно заметить, что название криптовалюты находится в теге параграфа с классом sc-e225a64a-0 ePTNty. Сокращенное название криптовалюты также находится в теге абзаца с другим именем класса sc-e225a64a-0 dfeAJi coin-item-symbol.
\\n\\n\\n\\nМы используем такие атрибуты, как class и id, для уникальной идентификации элементов HTML или групп знакомых элементов HTML. Когда у нас есть эти уникальные атрибуты, мы можем использовать их для нацеливания на элементы и извлечения из них нужных нам значений.
\\n\\n\\n\\nПроанализировав сайт Coinmarketcap, мы увидели, что данные о каждой криптовалюте расположены в строке, и каждая строка имеет дочерние элементы, содержащие данные, которые мы хотим извлечь.
\\n\\n\\n\\nДавайте вернемся к редактору кода и обновим наш файл coinmarketcap.py
\\n\\n\\n\\nimport requests\\nfrom bs4 import BeautifulSoup\\n\\ndef get_crypto_prices():\\n url = '<https://coinmarketcap.com>'\\n response_text = requests.get(url).text\\n\\n soup = BeautifulSoup(response_text, 'html.parser')\\n\\n # get all the table rows\\n table_rows = soup.findAll('tr')\\n\\n # iterate through all the table rows and get the required data\\n for table_row in table_rows:\\n crypto_name = table_row.find('p', class_ = 'sc-e225a64a-0 ePTNty')\\n shortened_crypto_name = table_row.find('p', class_ = 'sc-e225a64a-0 dfeAJi coin-item-symbol')\\n coin_img = table_row.find('img', class_ = 'coin-logo')\\n\\n print(crypto_name, shortened_crypto_name)\\n\\n get_crypto_prices()\\n
\\n\\n\\n\\nОбратите внимание на разницу между findAll и find
\\n\\n\\n\\nЕсли вы выполните приведенный выше код, то получите следующее
\\n\\n\\n\\nВы можете видеть, что некоторые данные возвращают значение None. Это происходит из-за того, что оставшиеся строки таблицы пусты. Что мы можем сделать в этом случае, так это проверить, есть ли значение, прежде чем печатать значения.
\\n\\n\\n\\nОбновив наш цикл for, мы получим следующее:
\\n\\n\\n\\n# iterate through all the table rows and get the required data\\n\\nfor table_row in table_rows:\\n crypto_name = table_row.find('p', class_ = 'sc-e225a64a-0 ePTNty')\\n shortened_crypto_name = table_row.find('p', class_ = 'sc-e225a64a-0 dfeAJi coin-item-symbol')\\n coin_img = table_row.find('img', class_ = 'coin-logo')\\n\\n if crypto_name is None or shortened_crypto_name is None:\\n continue\\n else:\\n crypto_name = crypto_name.text\\n shortened_crypto_name = shortened_crypto_name.text\\n coin_img = coin_img.attrs.get('src')\\n\\n print(crypto_name, shortened_crypto_name)\\n
\\n\\n\\n\\nЕсли есть значение crypto_name или shortened_crypto_name, мы получаем текст из HTML-элемента и выводим его в консоль. Мы также получаем src изображения криптовалюты.
\\n\\n\\n\\nЗапустив обновленный код, мы должны получить следующее:
\\n\\n\\n\\nТеперь давайте получим цены для каждой криптовалюты.
\\n\\n\\n\\nВернувшись в Chrome Devtools и щелкнув правой кнопкой мыши на тексте цены, мы должны увидеть следующее:
\\n\\n\\n\\nМы видим, что цена валюты находится в теге span, который обернут в тег якоря: тег a, который имеет значение класса cmc-link. Однако использование класса тега якоря для поиска цены не сработает, потому что класс cmc-link не идентифицирует элемент, на который мы пытаемся нацелиться.
\\n\\n\\n\\nconst bitcoinRow = document.querySelectorAll('tr')[1]\\nconst cmcLinks = bitcoinRow.querySelectorAll('.cmc-link')\\n\\nconsole.log(cmcLinks) // NodeList(4) [a.cmc-link, a.cmc-link, a.cmc-link, a.cmc-link]\\n
\\n\\n\\n\\nЕсли вы запустите приведенный выше код Javascript в консоли браузера, вы увидите, что в каждом ряду есть четыре ссылки с именем класса cmc-link. Это определенно не лучший способ получить цену криптовалюты в данном ряду.
\\n\\n\\n\\nДавайте посмотрим на родителя: div с именем класса sc-8bda0120-0 dskdZn
\\n\\n\\n\\nОбратите внимание, что при наведении элемента на консоль цена также наводится на веб-страницу. Таким образом, это оказывается лучшим способом получения цены криптовалюты.
\\n\\n\\n\\nОбновив код, мы получили:
\\n\\n\\n\\nimport requests\\nfrom bs4 import BeautifulSoup\\n\\ndef get_crypto_prices():\\n url = '<https://coinmarketcap.com>'\\n response_text = requests.get(url).text\\n\\n soup = BeautifulSoup(response_text, 'html.parser')\\n\\n # get all the table rows\\n table_rows = soup.findAll('tr')\\n\\n # iterate through all the table rows and get the required data\\n for table_row in table_rows:\\n crypto_name = table_row.find('p', class_ = 'sc-e225a64a-0 ePTNty')\\n shortened_crypto_name = table_row.find('p', class_ = 'sc-e225a64a-0 dfeAJi coin-item-symbol')\\n coin_img = table_row.find('img', class_ = 'coin-logo')\\n crypto_price = table_row.find('div', class_ = 'sc-8bda0120-0 dskdZn')\\n\\n if crypto_name is None or shortened_crypto_name is None or crypto_price is None:\\n continue\\n else:\\n crypto_name = crypto_name.text\\n shortened_crypto_name = shortened_crypto_name.text\\n coin_img = coin_img.attrs.get('src')\\n crypto_price = crypto_price.text\\n\\n print(f\\\"Name: {crypto_name} ({shortened_crypto_name}) \\\\\\\\nPrice: {crypto_price} \\\\\\\\nImage URL: {crypto_img_url}\\\\\\\\n\\\")\\n\\nget_crypto_prices()\\n
\\n\\n\\n\\nЗапустив обновленный код, мы должны получить следующее:
\\n\\n\\n\\nУуууппппсссссссс… Это было очень сложно. Надеюсь, вы смогли довести дело до конца.
Возьмите чашку кофе, вы ее заслужили👍.
Теперь, вооружившись знаниями, которые мы получили от скраппинга Coinmarketcap, мы можем продолжить работу над скраппером Bitcoin News. Мы будем использовать этот скребок для получения последних новостей в криптовалютном пространстве.
\\n\\n\\n\\nЩелкнув правой кнопкой мыши на первой новости и открыв раздел Inspect Elements в Chrome Devtools, мы увидим, что заголовки новостей имеют класс story. Однако если вы щелкните правой кнопкой мыши на других новостных заголовках, то обнаружите, что они имеют разновидности. Есть средняя история, маленькая, огромная, крошечная и т.д., с разными названиями классов для уникальной идентификации каждого типа.
\\n\\n\\n\\nОчень важным навыком, необходимым для веб-скраппинга, является способность внимательно изучить структуру HTML веб-страницы. Если вы понимаете структуру веб-страницы, то извлечение полезного содержимого из элементов не представляет собой сложной задачи.
\\n\\n\\n\\nimport requests\\n\\ndef get_news():\\n url = '<https://news.bitcoin.com>'\\n\\n response = requests.get(url) # making a request\\n response_text = response.text # getting the html\\n\\n print(response_text)\\n\\n soup = BeautifulSoup(response_text, 'html.parser')\\n all_articles = soup.findAll('div', class_ = 'story')\\n\\n for article in all_articles:\\n print(article.text.strip())\\n\\nget_news()\\n
\\n\\n\\n\\nКогда вы запустите приведенный выше код, вы можете получить следующее:
\\n\\n\\n\\nЧтобы предотвратить доступ вредоносных ботов к своему сайту, некоторые сайты используют Cloudflare Bot Management. Cloudflare ведет список известных хороших ботов, которым разрешен доступ к сайту, например, поисковые системы, боты для защиты авторских прав, боты для чата, боты для мониторинга сайта и так далее. К сожалению для таких энтузиастов веб-скрапинга, как мы с вами, они также предполагают, что весь трафик ботов, не включенных в белый список, является вредоносным.
\\n\\n\\n\\nОднако есть несколько способов обойти эту проблему, и легкость зависит от того, насколько бот представляет угрозу для Cloudflare и от плана Bot Protection, на который подписался владелец сайта.
\\n\\n\\n\\nСписок способов обхода Cloudflare можно найти здесь. Щелкните здесь, чтобы узнать больше об управлении ботами Cloudflare.
\\n\\n\\n\\nВ этой статье мы рассмотрим самое основное – установку заголовка User-Agent. Этим мы делаем вид, что запрос поступает от обычного браузера.
\\n\\n\\n\\ndef get_news():\\n url = '<https://news.bitcoin.com>'\\n headers = {\\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',\\n }\\n\\n response = requests.get(url, headers=headers)\\n\\n # the rest of the code\\n
\\n\\n\\n\\nПосле добавления приведенной выше строки кода и ее запуска мы должны получить следующее:
\\n\\n\\n\\nТеперь, когда у нас есть фактический веб-контент, давайте перейдем в наш браузер, чтобы просмотреть веб-страницу:
\\n\\n\\n\\nЩелкнув правой кнопкой мыши на первой новости, мы увидим следующее:
\\n\\n\\n\\nОбратите внимание, что элемент h6 имеет класс story__title story–medium__title. Если вы щелкните правой кнопкой мыши на другой новости, вы можете увидеть что-то вроде story__title story–huge__title или story__title story–large__title. Заметьте, что уже существует закономерность: заголовок каждой новости всегда имеет класс story__title. Это кажется лучшим способом нацелиться на заголовок новости.
\\n\\n\\n\\nЕсли вы присмотритесь, то заметите, что у заголовка новости есть родитель, который является ссылкой. Эта ссылка содержит URL новости в атрибуте href.
\\n\\n\\n\\nСобрав все это вместе, мы можем написать код для скрепера.
\\n\\n\\n\\nimport requests\\nfrom bs4 import BeautifulSoup\\n\\ndef get_news():\\n url = '<https://news.bitcoin.com>'\\n headers = {\\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',\\n } # headers to bypass Cloudflare Protection\\n\\n response = requests.get(url, headers=headers)\\n response_text = response.text\\n\\n soup = BeautifulSoup(response_text, 'html.parser')\\n all_articles = soup.findAll('div', class_ = 'story')\\n\\n for article in all_articles:\\n news_title_element = article.select_one('.story__title')\\n news_url = news_title_element.parent.attrs.get('href')\\n news_title = news_title_element.text.strip()\\n\\n print(f\\\"HEADLINE: {news_title} \\\\\\\\nURL: {news_url}\\\\\\\\n\\\")\\n\\nget_news()\\n
\\n\\n\\n\\nВыполнив приведенный выше код, мы получим заголовок новости и URL-адрес
\\n\\n\\n\\nТеперь, когда мы успешно собрали необходимые данные с веб-сайтов, давайте сохраним собранные данные. Если вы работаете с базой данных, вы можете сразу сохранить ее в данных, вы можете выполнить вычисления с данными, вы можете сохранить их для будущего использования, как бы то ни было, данные, которые вы соскребли, не очень полезны в консоли.
\\n\\n\\n\\nДавайте сделаем что-то действительно простое: сохраним данные в JSON-файл
\\n\\n\\n\\nimport requests\\nfrom bs4 import BeautifulSoup\\nimport json\\n\\n# some code\\nall_articles = soup.findAll('div', class_ = 'story')\\nscraped_articles = []\\n\\nfor article in all_articles:\\n news_title_element = article.select_one('.story__title')\\n news_url = news_title_element.parent.attrs.get('href')\\n news_title = news_title_element.text.strip()\\n\\n scraped_articles.append({\\n \\\"headline\\\": news_title,\\n \\\"url\\\": news_url\\n })\\n\\nwith open ('news.json', 'w') as file:\\n news_as_json = json.dumps({\\n 'news': scraped_articles,\\n 'number_of_news': len(scraped_articles)\\n }, indent = 3, sort_keys = True)\\n\\n file.write(news_as_json)\\n
\\n\\n\\n\\nТеперь мы сохраняем сохраненные новости в JSON-файл, который можно использовать для любых целей.
\\n\\n\\n\\nВаш JSON-файл должен выглядеть примерно так.
\\n\\n\\n\\nWhooopppsssss.⚡️⚡️ Это было очень много для восприятия.
\\n\\n\\n\\nПерегружать серверы слишком большим количеством запросов одновременно. Причина, по которой многие сайты не одобряют ботов, заключается в частом злоупотреблении ими. Когда вы делаете запрос, сервер использует ресурсы, чтобы обработать его. Большое количество запросов может привести к тому, что у сервера закончатся ресурсы, а это нехорошо.
\\n\\n\\n\\n\\\"\\\"\\\"\\n⛔️ DON'T DO THIS\\n\\\"\\\"\\\"\\nfor i in range(10000):\\n request.get('<https://reallyamazingwebsite.com>')\\n
\\n\\n\\n\\nВаш IP-адрес может попасть в черный список.
\\n\\n\\n\\nПренебрежение правилами авторского права. Веб-скрейпинг является абсолютно законным, если вы используете данные, находящиеся в открытом доступе в Интернете. Но некоторые виды данных защищены международными нормами, поэтому будьте осторожны при соскабливании личных данных, интеллектуальной собственности или конфиденциальных данных. Некоторые сайты могут открыто заявлять, что содержимое страницы не должно распространяться никакими другими способами, это следует уважать.
\\n\\n\\n\\nНаконец-то вы добрались до конца статьи, молодец, чемпион.
\\n\\n\\n\\nВ заключение хочу сказать, что веб-скрейпинг в Python может быть полезным инструментом для сбора информации с веб-сайтов для различных целей. Python предоставляет удобный и эффективный способ извлечения структурированных данных с веб-сайтов с помощью популярных библиотек, таких как BeautifulSoup. Однако важно помнить, что сбор информации с веб-сайтов всегда должен осуществляться этично и в соответствии с условиями обслуживания веб-сайта. Также важно знать о любых юридических ограничениях, которые могут применяться к данным, которые собираются. Учитывая эти факторы, веб-скрейпинг в Python может стать полезным навыком для всех, кто хочет собирать и анализировать данные из Интернета.
\\n\\n\\n\\nЕсли вам понравилось читать эту статью, вы можете поделиться ею в своих социальных сетях и следить за мной в социальных сетях.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Веб-скрейпинг, если говорить простым языком, – это техника, используемая для сбора полезных данных с веб-сайта. Согласитесь, в Интернете есть масса информации, и чаще всего она может быть структурирована не совсем так, как нам нужно. Таким образом, веб-скрейпинг позволяет нам извлекать данные из Интернета, которые затем можно реструктурировать или перестроить так, чтобы они были полезны для […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/prakticheskoe-rukovodstvo-po-parsingu-v-python/\"],\"title\":[0,\"Практическое руководство по парсингу в Python - Gorlov.\"],\"breadcrumbTitle\":[0,\"Практическое руководство по парсингу в Python\"],\"description\":[0,\"Веб-скрейпинг, если говорить простым языком, - это техника, используемая для сбора полезных данных с веб-сайта. Согласитесь, в Интернете есть масса\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Веб-скрейпинг, если говорить простым языком, - это техника, используемая для сбора полезных данных с веб-сайта. Согласитесь, в Интернете есть масса\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Практическое руководство по парсингу в Python - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-18T01:06:11+00:00\"],\"url\":[0,\"http://igorlov.loc/prakticheskoe-rukovodstvo-po-parsingu-v-python/\"]}]}],\"title\":[0,\"Практическое руководство по парсингу в Python\"],\"uri\":[0,\"/prakticheskoe-rukovodstvo-po-parsingu-v-python/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"prakticheskoe-rukovodstvo-po-parsingu-v-python\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Python\\\"],\\\"id\\\":[0,\\\"dGVybTo2NA==\\\"],\\\"uri\\\":[0,\\\"/tag/python/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0Njc=\"],\"node\":[0,{\"date\":[0,\"2023-03-18T00:38:11\"],\"content\":[0,\"\\nI18n URL были доступны во всех основных генераторах статических сайтов, но почему-то отсутствуют в NextJs, и это определенно жаль 😔.
\\n\\n\\n\\nЯ француз и всегда создаю свои сайты как минимум на французском и английском языках.
\\n\\n\\n\\nВот подробное объяснение того, как любой разработчик может добиться этого менее чем за 10 минут и наконец-то иметь возможность работать с такими урлами, как
\\n\\n\\n\\nРепозиторий со всем исходным кодом можно найти на GitHub
\\n\\n\\n\\nВ этом руководстве используется отличная библиотека next-translate, но ее можно адаптировать для next-i18next.
\\n\\n\\n\\nналичие next-translate, уже установленного в вашем проекте.
\\n\\n\\n\\nВо всех последующих шагах созданные файлы и функции будут помещены в папку modules/I18n.
Это практика, к которой я пришел после многих лет программирования и которая очень помогает разделять части приложения (в данном случае всю логику, связанную с I18n).
Скоро я напишу об этом статью в блоге.
Первое, что необходимо сделать, это указать пермалинки, которые мы хотим использовать.
Давайте создадим modules/I18n/permalinks.json
{\\n \\\"https://dev.to/\\\": {\\n \\\"fr\\\": \\\"/accueil\\\"\\n }\\n}\\n
\\n\\n\\n\\nПРИМЕЧАНИЕ: это не идеальное решение для меня, так как оно отделяет фактическую страницу (jsx файл) от определения ее пермалинков, и было бы лучше иметь экспорт const пермалинков изнутри страницы. Эта проблема рассматривается в части 2 этой статьи (и вы также можете связаться со мной, если вам нужна дополнительная информация).
\\n\\n\\n\\nЦель здесь – преобразовать созданные нами пермалинки в правила перезаписи, чтобы NextJS мог правильно переписывать URL в зависимости от языка.
\\n\\n\\n\\nTLDR См. коммит на GitHub
\\n\\n\\n\\nСоздайте modules/I18n/next.config.js с
\\n\\n\\n\\nconst nextTranslate = require('next-translate-plugin');\\nconst fs = require('fs');\\nconst permalinks = require('./permalinks.json');\\n\\n/**\\n * \\n * Transforms\\n{\\n \\\"https://dev.to/\\\": {\\n \\\"fr\\\": \\\"/accueil\\\"\\n }\\n}\\n * into\\n[\\n {\\n source: '/fr/accueil',\\n destination: '/fr',\\n locale: false\\n }\\n]\\n*/\\nconst permalinksToRewriteRules = (permalinks) =>\\n Object.entries(permalinks).reduce(\\n (acc, [originalSlug, permalinks]) => [\\n ...acc,\\n ...Object.entries(permalinks).reduce(\\n (acc2, [locale, i18nSlug]) => [\\n ...acc2,\\n {\\n source: `/${locale}${i18nSlug}`,\\n destination: `/${locale}${originalSlug}`,\\n locale: false,\\n },\\n ],\\n []\\n ),\\n ],\\n []\\n );\\n\\nmodule.exports = (nextConfig) => {\\n const nextTranslateConfig = nextTranslate(nextConfig);\\n\\n return {\\n ...nextTranslateConfig,\\n async rewrites() {\\n const existingRewrites = nextTranslateConfig.rewrites\\n ? await nextTranslateConfig.rewrites()\\n : [];\\n return [...permalinksToRewriteRules(permalinks), ...existingRewrites];\\n },\\n };\\n};\\n
\\n\\n\\n\\nи замените вызов функции в файле next.config.js
\\n\\n\\n\\n- const nextTranslate = require('next-translate-plugin')\\n+ const nextTranslate = require('./src/modules/I18n/next.config');\\n
\\n\\n\\n\\nОтлично, теперь, если вы перезагрузите свой сервер, вы сможете получить доступ к странице
\\n\\n\\n\\nТеперь давайте адаптируем компонент Link, чтобы он учитывал этот новый URL
\\n\\n\\n\\nЦель состоит в том, чтобы иметь возможность переходить непосредственно к красивым URL, определенным ранее.
\\n\\n\\n\\nTLDR: См. коммит на GitHub
\\n\\n\\n\\nНеобходимо создать новый компонент modules/I18n под названием Link и изменить все импорты next/link.
\\n\\n\\n\\nДа, это действительно больная тема, я признаю, но я не смог найти способ сделать по-другому.
\\n\\n\\n\\nНа самом деле это не такая уж большая проблема, так как простой “поиск и замена” будет работать
\\n\\n\\n\\n- import Link from 'next/link';\\n+ import { Link } from 'modules/I18n';\\n
\\n\\n\\n\\nВо-первых, переменная permalinks должна быть открыта для фронтенда, чтобы ее мог использовать создаваемый компонент Link.
\\n\\n\\n\\nВ nextJs это делается с помощью
\\n\\n\\n\\n return {\\n ...nextTranslateConfig,\\n+ publicRuntimeConfig: {\\n+ ...nextTranslateConfig.publicRuntimeConfig,\\n+ permalinks, // add it to publicRuntimeConfig so it can be used by the Link component\\n+ },\\n async rewrites() {\\n ...\\n
\\n\\n\\n\\nВстроенный в nextJS компонент Link работает следующим образом: он строит URL из href и переданной (или существующей) локали.
\\n\\n\\n\\nЭто означает, что ссылка на / в fr приведет к /fr.
\\n\\n\\n\\nЭтот компонент создаст карту URL для прямого перехода к соответствующему правильному URL /fr/accueil
\\n\\n\\n\\nimport React from 'react';\\nimport Link from 'next/link';\\nimport { useRouter } from 'next/router';\\n\\nimport getConfig from 'next/config';\\n\\nconst { publicRuntimeConfig } = getConfig();\\nconst permalinks: { [key: string]: { [key: string]: string } } =\\n publicRuntimeConfig.permalinks || {};\\n\\n/**\\n * Formats permalinks\\n{\\n \\\"https://dev.to/\\\": {\\n \\\"fr\\\": \\\"/accueil\\\"\\n }\\n}\\n * into\\n{\\n \\\"/fr/\\\": \\\"/fr/accueil\\\",\\n \\\"/en/accueil\\\": \\\"https://dev.to/\\\"\\n} \\n */\\nexport const i18nFallbackUrls: { [key: string]: string } = Object.entries(\\n permalinks\\n).reduce(\\n (acc, [originalSlug, permalinks]) => ({\\n ...acc,\\n ...Object.entries(permalinks || {}).reduce(\\n (acc2, [locale, permalink]) => ({\\n ...acc2,\\n [`/${locale}${originalSlug}`]: `/${locale}${permalink}`,\\n [`/en${permalink}`]: originalSlug,\\n }),\\n {}\\n ),\\n }),\\n {}\\n);\\n\\nconst I18nLink = ({ href, locale, ...props }: any) => {\\n const router = useRouter();\\n const wantedLocale = locale || router.locale;\\n let i18nProps: any = {\\n href,\\n locale,\\n };\\n\\n if (i18nFallbackUrls[`/${wantedLocale}${href}`]) {\\n i18nProps = {\\n href: i18nFallbackUrls[`/${wantedLocale}${href}`],\\n locale: false,\\n };\\n }\\n\\n return <Link {...i18nProps} {...props} />;\\n};\\n\\nexport default I18nLink;\\n
\\n\\n\\n\\nИ вуаля! Все готово, и вот как это выглядит.
\\n\\n\\n\\nПосмотрите Github Repo
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
I18n URL были доступны во всех основных генераторах статических сайтов, но почему-то отсутствуют в NextJs, и это определенно жаль 😔. Я француз и всегда создаю свои сайты как минимум на французском и английском языках. Вот подробное объяснение того, как любой разработчик может добиться этого менее чем за 10 минут и наконец-то иметь возможность работать с […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/internaczionalizacziya-url-adresov-nextjs-s-pomoshhyu-next-translate-chast-1/\"],\"title\":[0,\"Интернационализация URL-адресов NextJs с помощью Next-translate (часть 1) - Gorlov.\"],\"breadcrumbTitle\":[0,\"Интернационализация URL-адресов NextJs с помощью next-translate (часть 1)\"],\"description\":[0,\"I18n URL были доступны во всех основных генераторах статических сайтов, но почему-то отсутствуют в NextJs, и это определенно жаль 😔.\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"I18n URL были доступны во всех основных генераторах статических сайтов, но почему-то отсутствуют в NextJs, и это определенно жаль 😔.\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Интернационализация URL-адресов NextJs с помощью Next-translate (часть 1) - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-18T00:38:19+00:00\"],\"url\":[0,\"http://igorlov.loc/internaczionalizacziya-url-adresov-nextjs-s-pomoshhyu-next-translate-chast-1/\"]}]}],\"title\":[0,\"Интернационализация URL-адресов NextJs с помощью next-translate (часть 1)\"],\"uri\":[0,\"/internaczionalizacziya-url-adresov-nextjs-s-pomoshhyu-next-translate-chast-1/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"internaczionalizacziya-url-adresov-nextjs-s-pomoshhyu-next-translate-chast-1\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"i18n\\\"],\\\"id\\\":[0,\\\"dGVybToxNzg=\\\"],\\\"uri\\\":[0,\\\"/tag/i18n/\\\"]}],[0,{\\\"name\\\":[0,\\\"JavaScript\\\"],\\\"id\\\":[0,\\\"dGVybTo0Mw==\\\"],\\\"uri\\\":[0,\\\"/tag/javascript/\\\"]}],[0,{\\\"name\\\":[0,\\\"Next.js\\\"],\\\"id\\\":[0,\\\"dGVybToxNTA=\\\"],\\\"uri\\\":[0,\\\"/tag/next-js/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0NzE=\"],\"node\":[0,{\"date\":[0,\"2023-03-18T00:17:22\"],\"content\":[0,\"\\nПрошло некоторое время с тех пор, как я в последний раз что-то писал. Я подумал, что если поделиться с вами чем-то приятным, это может послужить средством для возвращения к этому. Таким образом, я терпеливо ждал чего-то, что могло бы возродить мое вдохновение и интерес, что в конечном итоге пришло в виде старой, но затягивающей игры Minesweeper 🙂
\\n\\n\\n\\nМоя дочь недавно открыла для себя Minesweeper на своем компьютере, и, к моему удивлению, она стала для нас увлекательным совместным занятием. Я сижу рядом с ней, время от времени предлагая свои два цента, и поражаюсь тому, как быстро она уловила логику игры. Она играет все быстрее и быстрее, с каждым днем ставя рекорды.
\\n\\n\\n\\nСидя там, я не мог не задуматься о коде, лежащем в основе игры. В частности, я размышлял о расположении игрового поля. Это двумерный массив или плоский массив? Как вычисляются числа? Каким волшебником нужно быть, чтобы создать такую штуку?
\\n\\n\\n\\nЭтого достаточно, чтобы разжечь огонь под моей задницей и заставить меня действовать 🙂
\\n\\n\\n\\nИтак, хотите поучаствовать в создании игры Minesweeper с помощью SolidJS?
Поехали!
Эй! Для получения большего количества материалов, подобных тому, что вы собираетесь прочитать, проверьте @mattibarzeev на Twitter 🍻
\\n\\n\\n\\nКод можно найти в этом репозитории GitHub:
https://github.com/mbarzeev/solid-minesweeper
Доска сделана из массива с 16 ячейками. Это позволит нам создать доску 4х4. В настоящее время она жестко закодирована, позже мы сможем сделать на ней несколько случайных расположений:
\\n\\n\\n\\nconst boardArray: number[] = [0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0];\\n
\\n\\n\\n\\n\\n\\n\\n\\nСодержимое массива состоит из 0 и 1, где 1 означает плитку с миной, а 0 – пустую плитку.
Для отображения я использую компонент <For>
из Solid:
const App: Component = () => {\\n return (\\n <div class={styles.App}>\\n <header class={styles.header}>\\n <For each={boardArray}>\\n {(item: number, index: () => number) => <div>{item}</div>}\\n </For>\\n </header>\\n </div>\\n );\\n};\\n
\\n\\n\\n\\nВ результате получается вот что:
\\n\\n\\n\\nПодождите… дальше будет лучше.
\\n\\n\\n\\nОчевидно, нам нужен способ расположить их в сетке 4×4, и для этого я использую … css-сетку 🙂
Я помещу мой <For …> тег внутрь div, который имеет класс board css, и вот определение этого класса:
.board {\\n --tile-dimension: 30px;\\n --row-length: 4;\\n\\n\\n display: grid;\\n grid-template-columns: repeat(auto-fit, minmax(var(--tile-dimension), 1fr));\\n max-width: calc(var(--row-length) * var(--tile-dimension));\\n}\\n
\\n\\n\\n\\nТеперь это выглядит следующим образом:
\\n\\n\\n\\nДа, больше похоже на это.
Мы знаем, что эти пустые клетки должны указывать на количество мин, которые находятся рядом с ними во всех 8 направлениях. Как мы это сделаем?
Здесь я использую подход “грубой силы”, хотя может оказаться, что это самый эффективный способ достижения цели. Я проверяю каждую плитку на наличие мин рядом с ней, но поскольку массив плоский, нам нужно быть умными. Позвольте мне сначала поместить здесь код, а затем объяснить, что происходит в функции “getMinesCount()”.
Вот рендеринг, где мы передаем индекс текущей ячейки в функцию getMinesCount:
<div class={styles.board}>\\n <For each={boardArray} fallback={<div>Loading...</div>}>\\n {(item: number, index: () => number) => (\\n <div style={{width: '30px', height: '30px'}}>{getMinesCount(index())}</div>\\n )}\\n </For>\\n </div>\\n
\\n\\n\\n\\nА вот реализация функции getMinesCount:
\\n\\n\\n\\nfunction getMinesCount(index: number) {\\n const cell = boardArray[index];\\n if (cell === 1) {\\n return 'x';\\n } else {\\n let minesCount = 0;\\n const hasLeftCells = index % ROW_LENGTH > 0;\\n const hasRightCells = (index + 1) % ROW_LENGTH !== 0;\\n const bottomCellIndex = index + ROW_LENGTH;\\n const topCellIndex = index - ROW_LENGTH;\\n\\n\\n if (boardArray[bottomCellIndex] === 1) {\\n minesCount++;\\n }\\n\\n\\n if (boardArray[topCellIndex] === 1) {\\n minesCount++;\\n }\\n\\n\\n if (hasLeftCells) {\\n boardArray[index - 1] === 1 && minesCount++;\\n boardArray[topCellIndex - 1] === 1 && minesCount++;\\n boardArray[bottomCellIndex - 1] === 1 && minesCount++;\\n }\\n\\n\\n if (hasRightCells) {\\n boardArray[index + 1] === 1 && minesCount++;\\n boardArray[topCellIndex + 1] && minesCount++;\\n hasRightCells && boardArray[bottomCellIndex + 1] && minesCount++;\\n }\\n\\n\\n return minesCount;\\n }\\n}\\n
\\n\\n\\n\\nЛогика довольно проста – мы вычисляем верхнюю и нижнюю ячейки, выясняем, есть ли у ячейки соседи слева или справа, и соответственно увеличиваем minesCount.
\\n\\n\\n\\nНа самом деле это не так уж плохо, учитывая, что у нас сложность O(n).
\\n\\n\\n\\nВот как это выглядит сейчас:
\\n\\n\\n\\nСимвол “X” обозначает мины, а цифры показывают, сколько мин находится рядом с клеткой. Пора создать компонент Tile.
\\n\\n\\n\\nВы, наверное, заметили, что я использую константу “ROW_LENGTH” для вычисления размеров доски, и я также имею это значение в CSS как переменную, и это немного раздражает меня, что изменение размеров сетки требует изменения как CSS, так и JS, а не только в одном месте.
Для этого я решил определить переменную CSS в коде рендеринга, например, так:
<div class={styles.App} style={{'--row-length': ROW_LENGTH}}>\\n <header class={styles.header}>\\n <div class={styles.board}>\\n <For each={boardArray}>\\n {(item: number, index: () => number) => <Tile {...getTileData(index())} />}\\n </For>\\n </div>\\n </header>\\n </div>\\n
\\n\\n\\n\\nТаким образом, мне нужно только изменить константу “ROW_LENGTH”, и все выравнивается идеально.
\\n\\n\\n\\nimport {Component, createSignal} from 'solid-js';\\nimport styles from './Tile.module.css';\\n\\n\\nexport type TileData = {\\n isMine: boolean;\\n value?: number;\\n};\\n\\n\\nconst Tile: Component<TileData> = (data: TileData) => {\\n const [isOpen, setIsOpen] = createSignal(false);\\n const [isMarked, setIsMarked] = createSignal(false);\\n\\n\\n const onTileClicked = (event: MouseEvent) => {\\n !isMarked() && setIsOpen(true);\\n };\\n\\n\\n const onTileContextClick = (event: MouseEvent) => {\\n event.preventDefault();\\n !isOpen() && setIsMarked(!isMarked());\\n };\\n\\n\\n const value = data.isMine ? 'X' : data.value;\\n\\n\\n return (\\n <div class={styles.Tile} onclick={onTileClicked} onContextMenu={onTileContextClick}>\\n <div class={styles.value} classList={{[styles.exposed]: isOpen() || isMarked()}}>\\n {isMarked() ? '🚩' : value !== 0 ? value : ''}\\n </div>\\n </div>\\n );\\n};\\n\\n\\nexport default Tile;\\n
\\n\\n\\n\\nКак вы можете видеть, щелчок правой кнопкой мыши отмечает плитку, а обычный щелчок открывает ее. Отметку можно переключить, но после открытия плитка уже открыта.
\\n\\n\\n\\nИ мы используем это так в основном приложении:
\\n\\n\\n\\n<For each={boardArray} fallback={<div>Loading...</div>}>\\n {(item: number, index: () => number) => <Tile {...getTileData(index())} />}\\n </For>\\n
\\n\\n\\n\\nИ вот что мы получили: доска с “пустыми” плитками, при нажатии на которые они открываются – те, что с цифрами, показывают цифры, те, что с минами, показывают “X”, а отмеченные – флажки.
\\n\\n\\n\\nПора добавить немного случайности в котел. Я хотел бы сгенерировать плоский массив 20×20 (400 клеток), в котором разбросаны 40 мин. Вот код для этого:
\\n\\n\\n\\nconst totalMines = 40;\\nconst ROW_LENGTH = 20;\\nconst TOTAL_TILES = Math.pow(ROW_LENGTH, 2);\\n\\n\\nconst boardArray = [...Array(TOTAL_TILES)].fill(0);\\n\\n\\nlet count = 0;\\nwhile (count < totalMines) {\\n const randomCellIndex = Math.floor(Math.random() * TOTAL_TILES);\\n if (boardArray[randomCellIndex] !== 1) {\\n boardArray[randomCellIndex] = 1;\\n count++;\\n }\\n}\\n
\\n\\n\\n\\nВот как это выглядит без скрытия значения плитки для наглядности:
\\n\\n\\n\\nНа этом пока все.
\\n\\n\\n\\nУ нас есть игровое поле, которое позволяет нам настраивать его размеры и количество мин, которые мы хотим включить. В настоящее время у нас есть возможность раскрывать или помечать отдельные плитки.
\\n\\n\\n\\nСледующий шаг – понять логику, лежащую в основе функции “автораскрытия”, когда несколько плиток раскрываются одним щелчком мыши. Нам нужно определить соответствующую логику для открытия соседних плиток при нажатии на одну плитку. Нам также необходимо решить остальные вопросы механики игры, чтобы обеспечить ее бесперебойную работу.
\\n\\n\\n\\nКод можно найти в этом репозитории GitHub:
https://github.com/mbarzeev/solid-minesweeper
💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Прошло некоторое время с тех пор, как я в последний раз что-то писал. Я подумал, что если поделиться с вами чем-то приятным, это может послужить средством для возвращения к этому. Таким образом, я терпеливо ждал чего-то, что могло бы возродить мое вдохновение и интерес, что в конечном итоге пришло в виде старой, но затягивающей игры […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/sozdanie-igry-minesweeper-v-solidjs-igrovaya-doska/\"],\"title\":[0,\"Создание игры Minesweeper в SolidJS - Игровая доска - Gorlov.\"],\"breadcrumbTitle\":[0,\"Создание игры Minesweeper в SolidJS – Игровая доска\"],\"description\":[0,\"Прошло некоторое время с тех пор, как я в последний раз что-то писал. Я подумал, что если поделиться с вами чем-то приятным, это может послужить средством для\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Прошло некоторое время с тех пор, как я в последний раз что-то писал. Я подумал, что если поделиться с вами чем-то приятным, это может послужить средством для\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Создание игры Minesweeper в SolidJS - Игровая доска - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-18T00:17:24+00:00\"],\"url\":[0,\"http://igorlov.loc/sozdanie-igry-minesweeper-v-solidjs-igrovaya-doska/\"]}]}],\"title\":[0,\"Создание игры Minesweeper в SolidJS – Игровая доска\"],\"uri\":[0,\"/sozdanie-igry-minesweeper-v-solidjs-igrovaya-doska/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"sozdanie-igry-minesweeper-v-solidjs-igrovaya-doska\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Gamedev\\\"],\\\"id\\\":[0,\\\"dGVybToxNzc=\\\"],\\\"uri\\\":[0,\\\"/tag/gamedev/\\\"]}],[0,{\\\"name\\\":[0,\\\"JavaScript\\\"],\\\"id\\\":[0,\\\"dGVybTo0Mw==\\\"],\\\"uri\\\":[0,\\\"/tag/javascript/\\\"]}],[0,{\\\"name\\\":[0,\\\"Solidjs\\\"],\\\"id\\\":[0,\\\"dGVybToxNzY=\\\"],\\\"uri\\\":[0,\\\"/tag/solidjs/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0NzU=\"],\"node\":[0,{\"date\":[0,\"2023-03-18T00:04:27\"],\"content\":[0,\"\\nПревратите свои данные в выводы с помощью потрясающего графика box-and-whisker! Узнайте, что это такое и как легко создать такую диаграмму с помощью JavaScript. В этом уроке я проведу вас через шаги по созданию аккуратной и визуально привлекательной коробочной диаграммы на основе JS (HTML5) с годовыми валовыми зарплатами различных ИТ-профессий в Европе. Откройте силу визуализации данных и начните быстро выявлять тенденции и закономерности уже сегодня!
\\n\\n\\n\\nДиаграмма box-and-whisker, или просто box plot или box plot, – это тип графического представления, обычно используемый в статистическом анализе для отображения распределения набора данных. График состоит из прямоугольного поля, простирающегося от первого квартиля до третьего квартиля (также известного как межквартильный размах, или IQR), с горизонтальной линией внутри, представляющей медиану.
\\n\\n\\n\\nВ дополнение к коробке от нее могут отходить линии (называемые “усами”), указывающие на изменчивость за пределами верхнего и нижнего квартилей. Эти “усы” могут представлять различные вещи в зависимости от контекста, например, максимальное и минимальное значения в определенном диапазоне или кратное стандартное отклонение.
\\n\\n\\n\\nВыбросы, которые значительно отличаются от остальной части набора данных, могут быть изображены в виде отдельных точек за пределами усов на графике. Наличие выбросов может дать ценную информацию о распределении данных и помочь выявить потенциальные ошибки или аномалии в данных.
\\n\\n\\n\\nЧтобы пробудить ваш интерес к построению креативной диаграммы, позвольте мне показать вам окончательный вариант диаграммы “ящик и усы”, который будет готов к концу этого урока.
\\n\\n\\n\\nНе правда ли, выглядит великолепно? Продолжайте читать, чтобы узнать, как его создать.
\\n\\n\\n\\nЕсли у вас уже есть опыт создания графиков с помощью JavaScript, вы должны иметь базовое представление о том, как это работает. Однако если вы новичок, этот учебник по построению графиков в виде коробок поможет вам шаг за шагом. Давайте начнем с обзора необходимых шагов:
\\n\\n\\n\\nВы можете создать потрясающую базовую диаграмму “бокс и вискер” с помощью всего нескольких строк кода. Кроме того, я покажу вам несколько интересных настроек для улучшения внешнего вида графика. Давайте погрузимся!
\\n\\n\\n\\n
Мы будем работать с JavaScript, поэтому прежде всего нам нужно использовать HTML для создания веб-страницы, на которой будет отображаться наша бокс-диаграмма.
Начнем с того, что зададим название веб-страницы “JavaScript Box-and-Whisker Plot”. Затем мы включим несколько строк CSS-кода в тег style, чтобы установить margin и padding на 0; и сделать высоту и ширину веб-страницы 100%. Это обеспечит правильное отображение графика на веб-странице.
\\n\\n\\n\\nНаконец, мы добавим тег div с идентификатором “container”. Позже мы будем использовать этот div для размещения квадратного графика.
\\n\\n\\n\\n<!DOCTYPE html>\\n<html lang=\\\"en\\\">\\n <head>\\n <meta charset=\\\"utf-8\\\">\\n <title>JavaScript Box-and-Whisker Plot</title>\\n <style type=\\\"text/css\\\">\\n html, body, #container {\\n width: 100%;\\n height: 100%;\\n margin: 0;\\n padding: 0;\\n }\\n </style>\\n </head>\\n <body>\\n <div id=\\\"container\\\"></div>\\n </body>\\n</html>\\n
\\n\\n\\n\\nПосле завершения базовой верстки нашей веб-страницы HTML следующим шагом будет включение необходимых файлов JavaScript. Мы должны включить ссылку на библиотеку диаграмм JavaScript в раздел head нашей HTML-страницы.
\\n\\n\\n\\nДля этой цели мы будем использовать AnyChart. Нам понадобятся модули Core и Basic Cartesian для нашей диаграммы в виде квадрата и усов.
\\n\\n\\n\\n<!DOCTYPE html>\\n<html lang=\\\"en\\\">\\n <head>\\n <meta charset=\\\"utf-8\\\">\\n <title>JavaScript Box-and-Whisker Plot</title>\\n <script src=\\\"https://cdn.anychart.com/releases/8.11.0/js/anychart-core.min.js\\\"></script>\\n <script src=\\\"https://cdn.anychart.com/releases/8.11.0/js/anychart-cartesian.min.js\\\"></script>\\n <style type=\\\"text/css\\\">\\n html, body, #container {\\n width: 100%;\\n height: 100%;\\n margin: 0;\\n padding: 0;\\n }\\n </style>\\n </head>\\n <body>\\n <div id=\\\"container\\\"></div>\\n <script>\\n // All the code for the JS Box-and-Whisker Plot will come here\\n </script>\\n </body>\\n</html>\\n
\\n\\n\\n\\nМы будем использовать данные о годовой брутто-зарплате для различных профессий в Европе, взятые из обзора IT Salary Survey для региона ЕС (2018-2020), доступного на Kaggle.
\\n\\n\\n\\nПосле очистки данных для удаления дубликатов и некорректно оформленных или вводящих в заблуждение данных я выбрал только профессии с достаточным количеством данных и рассчитал их средние значения. Затем я выбрал 8 лучших ИТ-профессий для нашей визуализации в виде бокса и вискера.
\\n\\n\\n\\nДанные представлены в виде массива объектов, каждый из которых представляет профессию. В свойствах объекта отображаются название профессии, первый квартиль, медиана, третий квартиль, минимальное и максимальное значения, а также значения выбросов.
\\n\\n\\n\\nvar data = [\\n {\\n x: 'Backend Developer',\\n low: 35000,\\n q1: 60000,\\n median: 70000,\\n q3: 80000,\\n high: 110000,\\n outliers: [10001, 10001, 12000, 13000, 14400, 17500, 25000, 27000, 27000, 28000, 120000, 135000, 154000, 172000]\\n },\\n {\\n x: 'Data Engineer',\\n low: 40000,\\n q1: 54000,\\n median: 68000,\\n q3: 84000,\\n high: 110000,\\n outliers: [200000]\\n },\\n {\\n x: 'DevOps',\\n low: 52500,\\n q1: 65000,\\n median: 72000,\\n q3: 82500,\\n high: 105000,\\n outliers: [30000, 37000, 124000, 140000]\\n },\\n {\\n x: 'Engineering Manager',\\n low: 78000,\\n q1: 80000,\\n median: 85000,\\n q3: 95750,\\n high: 105000\\n },\\n {\\n x: 'ML Engineer',\\n low: 11500,\\n q1: 52500,\\n median: 65000,\\n q3: 81000,\\n high: 120000,\\n outliers: [180000]\\n },\\n {\\n x: 'Mobile Developer',\\n low: 40000,\\n q1: 61250,\\n median: 66000,\\n q3: 77000,\\n high: 85000,\\n outliers: [240000]\\n },\\n {\\n x: 'Product Manager',\\n low: 30000,\\n q1: 60000,\\n median: 70000,\\n q3: 85000,\\n high: 120000,\\n outliers: [150000]\\n },\\n {\\n x: 'Software Engineer',\\n low: 28800,\\n q1: 60000,\\n median: 72000,\\n q3: 81000,\\n high: 110000,\\n outliers: [14712, 16320, 21000, 21120, 24000, 26400, 113000, 115000, 120000, 120000, 120000, 120000, 120000, 120000, 130000, 130000, 140000, 150000, 151872, 160000, 200000, 250000]\\n }\\n];\\n
\\n\\n\\n\\nНаконец, давайте напишем немного кода JavaScript, чтобы запустить наш график.
\\n\\n\\n\\nМы включим функцию onDocumentReady() библиотеки построения графиков и заключим в нее наш код, чтобы обеспечить представление данных на экране после полной загрузки веб-страницы HTML.
\\n\\n\\n\\n<script>\\n anychart.onDocumentReady(function () {\\n // The box chart's code will be written here.\\n });\\n</script>\\n
\\n\\n\\n\\nСначала мы добавим наши данные из Шага 3.
\\n\\n\\n\\nanychart.onDocumentReady(function () {\\n var data = [\\n {\\n x: 'Backend Developer',\\n low: 35000,\\n q1: 60000,\\n median: 70000,\\n q3: 80000,\\n high: 110000,\\n outliers: [10001, 10001, 12000, 13000, 14400, 17500, 25000, 27000, 27000, 28000, 120000, 135000, 154000, 172000]\\n },\\n {\\n x: 'Data Engineer',\\n low: 40000,\\n q1: 54000,\\n median: 68000,\\n q3: 84000,\\n high: 110000,\\n outliers: [200000]\\n },\\n {\\n x: 'DevOps',\\n low: 52500,\\n q1: 65000,\\n median: 72000,\\n q3: 82500,\\n high: 105000,\\n outliers: [30000, 37000, 124000, 140000]\\n },\\n {\\n x: 'Engineering Manager',\\n low: 78000,\\n q1: 80000,\\n median: 85000,\\n q3: 95750,\\n high: 105000\\n },\\n {\\n x: 'ML Engineer',\\n low: 11500,\\n q1: 52500,\\n median: 65000,\\n q3: 81000,\\n high: 120000,\\n outliers: [180000]\\n },\\n {\\n x: 'Mobile Developer',\\n low: 40000,\\n q1: 61250,\\n median: 66000,\\n q3: 77000,\\n high: 85000,\\n outliers: [240000]\\n },\\n {\\n x: 'Product Manager',\\n low: 30000,\\n q1: 60000,\\n median: 70000,\\n q3: 85000,\\n high: 120000,\\n outliers: [150000]\\n },\\n {\\n x: 'Software Engineer',\\n low: 28800,\\n q1: 60000,\\n median: 72000,\\n q3: 81000,\\n high: 110000,\\n outliers: [14712, 16320, 21000, 21120, 24000, 26400, 113000, 115000, 120000, 120000, 120000, 120000, 120000, 120000, 130000, 130000, 140000, 150000, 151872, 160000, 200000, 250000]\\n }\\n];\\n
\\n\\n\\n\\nДалее мы создаем наш график box-and-whisker, указывая тип графика как “box”. Мы создаем серию box и передаем в нее наши данные.
\\n\\n\\n\\nvar chart = anychart.box()\\nvar series = chart.box(data);\\n
\\n\\n\\n\\nПосле этого мы добавляем заголовок графика и устанавливаем контейнер, ссылающийся на элемент div, которому мы присвоили id “container” в шаге 1.
\\n\\n\\n\\nchart.title('Yearly Gross Salary for Different IT Professions in Europe');\\nchart.container('container');\\n
\\n\\n\\n\\nНаконец, мы рисуем график с помощью функции draw().
\\n\\n\\n\\nchart.draw();\\n
\\n\\n\\n\\nВот как выглядит базовый интерактивный JS box-and-whisker plot! Полный код веб-страницы HTML приведен ниже. Вы также можете найти интерактивную версию этого графика на AnyChart Playground.
\\n\\n\\n\\n<!DOCTYPE html>\\n<html lang=\\\"en\\\">\\n <head>\\n <meta charset=\\\"utf-8\\\">\\n <title>JavaScript Box-and-Whisker Plot</title>\\n <script src=\\\"https://cdn.anychart.com/releases/8.11.0/js/anychart-core.min.js\\\"></script>\\n <script src=\\\"https://cdn.anychart.com/releases/8.11.0/js/anychart-cartesian.min.js\\\"></script>\\n <style type=\\\"text/css\\\">\\n html, body, #container {\\n width: 100%;\\n height: 100%;\\n margin: 0;\\n padding: 0;\\n }\\n </style>\\n </head>\\n <body>\\n <div id=\\\"container\\\"></div>\\n <script>\\n anychart.onDocumentReady(function () {\\n var data = [\\n {\\n x: 'Backend Developer',\\n low: 35000,\\n q1: 60000,\\n median: 70000,\\n q3: 80000,\\n high: 110000,\\n outliers: [10001, 10001, 12000, 13000, 14400, 17500, 25000, 27000, 27000, 28000, 120000, 135000, 154000, 172000]\\n },\\n {\\n x: 'Data Engineer',\\n low: 40000,\\n q1: 54000,\\n median: 68000,\\n q3: 84000,\\n high: 110000,\\n outliers: [200000]\\n },\\n {\\n x: 'DevOps',\\n low: 52500,\\n q1: 65000,\\n median: 72000,\\n q3: 82500,\\n high: 105000,\\n outliers: [30000, 37000, 124000, 140000]\\n },\\n {\\n x: 'Engineering Manager',\\n low: 78000,\\n q1: 80000,\\n median: 85000,\\n q3: 95750,\\n high: 105000\\n },\\n {\\n x: 'ML Engineer',\\n low: 11500,\\n q1: 52500,\\n median: 65000,\\n q3: 81000,\\n high: 120000,\\n outliers: [180000]\\n },\\n {\\n x: 'Mobile Developer',\\n low: 40000,\\n q1: 61250,\\n median: 66000,\\n q3: 77000,\\n high: 85000,\\n outliers: [240000]\\n },\\n {\\n x: 'Product Manager',\\n low: 30000,\\n q1: 60000,\\n median: 70000,\\n q3: 85000,\\n high: 120000,\\n outliers: [150000]\\n },\\n {\\n x: 'Software Engineer',\\n low: 28800,\\n q1: 60000,\\n median: 72000,\\n q3: 81000,\\n high: 110000,\\n outliers: [14712, 16320, 21000, 21120, 24000, 26400, 113000, 115000, 120000, 120000, 120000, 120000, 120000, 120000, 130000, 130000, 140000, 150000, 151872, 160000, 200000, 250000]\\n }\\n ];\\n // create a chart\\n var chart = anychart.box();\\n // create a box series and set the data\\n var series = chart.box(data);\\n // set the chart title\\n chart.title('Yearly Gross Salary for Different IT professions in Europe');\\n // set the container id\\n chart.container('container');\\n // draw the chart\\n chart.draw();\\n });\\n </script>\\n </body>\\n</html>\\n
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Превратите свои данные в выводы с помощью потрясающего графика box-and-whisker! Узнайте, что это такое и как легко создать такую диаграмму с помощью JavaScript. В этом уроке я проведу вас через шаги по созданию аккуратной и визуально привлекательной коробочной диаграммы на основе JS (HTML5) с годовыми валовыми зарплатами различных ИТ-профессий в Европе. Откройте силу визуализации данных […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/sozdanie-diagrammy-boksa-i-uiskera-js/\"],\"title\":[0,\"Создание диаграммы Бокса и Уискера (JS) - Gorlov.\"],\"breadcrumbTitle\":[0,\"Создание диаграммы Бокса и Уискера (JS)\"],\"description\":[0,\"Превратите свои данные в выводы с помощью потрясающего графика box-and-whisker! Узнайте, что это такое и как легко создать такую диаграмму с помощью\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Превратите свои данные в выводы с помощью потрясающего графика box-and-whisker! Узнайте, что это такое и как легко создать такую диаграмму с помощью\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Создание диаграммы Бокса и Уискера (JS) - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-18T00:04:40+00:00\"],\"url\":[0,\"http://igorlov.loc/sozdanie-diagrammy-boksa-i-uiskera-js/\"]}]}],\"title\":[0,\"Создание диаграммы Бокса и Уискера (JS)\"],\"uri\":[0,\"/sozdanie-diagrammy-boksa-i-uiskera-js/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"sozdanie-diagrammy-boksa-i-uiskera-js\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Charts\\\"],\\\"id\\\":[0,\\\"dGVybToxNzU=\\\"],\\\"uri\\\":[0,\\\"/tag/charts/\\\"]}],[0,{\\\"name\\\":[0,\\\"JavaScript\\\"],\\\"id\\\":[0,\\\"dGVybTo0Mw==\\\"],\\\"uri\\\":[0,\\\"/tag/javascript/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0OTE=\"],\"node\":[0,{\"date\":[0,\"2023-03-17T23:17:01\"],\"content\":[0,\"\\nБудучи разработчиком приложений, я никогда особо не интересовался командами Linux, но поскольку сейчас я работаю в очень маленькой компании, мне приходится делать всевозможные вещи, которые мне очень нравятся, если вы похожи на меня, то эта статья для вас.
\\n\\n\\n\\nНедавно я выполнил команду chmod 777 -R / на одном из наших администраторов AWS EC2, и это привело к множеству нежелательных и не очень хороших вещей. Я подробно расскажу о том, что произошло, а также о некоторых деталях chmod и разрешений в целом в этой статье, и к концу статьи вы будете хорошо разбираться в них и сможете выполнять эти команды с определенной уверенностью.
\\n\\n\\n\\nКак разработчик приложений, я не обладаю 100% знаниями о системах Linux и о том, как они работают внутри, но после того, как я совершил эту ошибку, я провел исследование и написал эту статью, чтобы не делать того же в будущем, если вы читаете эту статью, я могу спасти и вас.
\\n\\n\\n\\nПрежде чем перейти к деталям, давайте вкратце обсудим файловые системы, пользователей и группы пользователей в Linux. В основном, в системе на базе Unix есть разрешения, прикрепленные к каждому из созданных файлов, вы могли слышать, как чтение, запись и выполнение. На основании этих разрешений пользователь получает доступ к этим файлам, и есть так называемый суперпользователь, который может предоставить или отозвать доступ к любым файлам в файловой системе. Этот суперпользователь будет особенно полезен, когда пользователь владеет очень важным каталогом и покидает организацию, тогда в этом случае суперпользователь может прийти и сменить владельца этого каталога (если обычному пользователю разрешено выполнять некоторые команды на уровне root, то это можно сделать с помощью sudo).
\\n\\n\\n\\nТеперь давайте обсудим кое-что, связанное с правами доступа, которые могут быть установлены на файлы, они представлены либо алфавитами, либо цифрами
\\n\\n\\n\\nls -l your_file_name -- Command \\n-rw-------@ 1 SRA 4238108 Apr 21 2022 IMG_0237.jpg --- output\\n# here my file name is IMG_0237.jpg\\nls -ld your_folder_name -- Command\\n
\\n\\n\\n\\nТак, строка ниже ls – l дала нам разрешения на чтение и запись (rw). Если вы хотите узнать о каталоге, мы можем использовать ls -ld. Вы можете узнать больше, что может делать команда ls, используя команду man ls.
\\n\\n\\n\\nО том, как можно изменить права доступа, пользователя или группы пользователей
\\n\\n\\n\\nТеперь давайте обсудим, как можно изменить права доступа, назначить нового пользователя или группу на определенную папку или файл. Это можно сделать с помощью команд chown и chmod. Прежде всего, давайте обсудим chmod и коды доступа, которые поставляются с chmod
\\n\\n\\n\\nАльтернативный код Альтернативно, мы также можем использовать числа для представления этих разрешений.
\\n\\n\\n\\nДопустим, вы использовали ls -l для файла и вас не устроило разрешение на файл, тогда вы используете chmod.
\\n\\n\\n\\nchmod permission_you_want your_filename\\nchmod rwx your_filename\\n
\\n\\n\\n\\nТеперь давайте обсудим chown, который можно использовать для смены пользователя и группы в файле или каталоге. Допустим, как я уже говорил, файл или папка принадлежит какому-то пользователю, который покинул компанию, и мы хотим изменить его на другого пользователя и группу.
\\n\\n\\n\\nchown user_name:user_group_name file_or_folder_name\\n
\\n\\n\\n\\nКогда вы выполнили эту команду и теперь хотите проверить пользователя и группу, вы можете просто использовать ls -l или ls -ld.
\\n\\n\\n\\nДо этого момента мы имели дело либо с папкой, либо с одним файлом, но что делать, если вы хотите изменить права на каждый файл в папке и на все файлы во вложенных папках в папке, вот тут-то и пригодится опция -R(Recursive).
\\n\\n\\n\\nchmod -R your_access_modes folder_name\\nchmod -R 777 your_folder_name/\\n
\\n\\n\\n\\nТеперь давайте разберемся, почему нам следует быть очень осторожными при выполнении команды chmod 777. Вообще, 777 означает, что вы даете пользователю разрешение на чтение, запись и выполнение, что может быть нормально для одного файла, но давать разрешение на всю папку слишком рискованно, но может быть принято в определенной степени, но команда, которую я выполнил
\\n\\n\\n\\nchmod -R 777 /\\n
\\n\\n\\n\\nЭто слишком рискованно, и я думаю, что этого следует избегать и никогда не запускать, особенно если вы разработчик приложений. Это меняет разрешения на каждый файл под root, то есть на каждый файл на вашей Linux-машине, это дает разрешение на чтение, запись и выполнение всех файлов всем пользователям, имеющим доступ к этой машине, это очень серьезная проблема безопасности (эти проблемы могут быть отдельной статьей, поэтому я не буду обсуждать их здесь). В моем случае это повлияло на нас следующим образом: машина, на которой я выполнил эту команду, используется для запуска jenkins, и это повлияло на ваш CI/CD конвейер почти на два дня, это испортило sudo разрешения, которые есть у других пользователей на этой машине. Проще говоря, это привлекло внимание множества людей, и множеству людей пришлось работать над исправлением этого, так что это было влияние этого простыми словами.
\\n\\n\\n\\nНо да, вам не стоит беспокоиться об этом, если вы уже запустили его, вы ничего не можете с этим поделать, кроме как исправить его. Вот что сказал мне мой менеджер, когда я признался, что именно я являюсь причиной того, что трубопровод не работает, и я цитирую его точные слова.
\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\nЗа свою карьеру я бывал и хуже – если кто-то не испортил что-то в Linux, он, вероятно, недостаточно занимается разработкой.
\\n
💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Будучи разработчиком приложений, я никогда особо не интересовался командами Linux, но поскольку сейчас я работаю в очень маленькой компании, мне приходится делать всевозможные вещи, которые мне очень нравятся, если вы похожи на меня, то эта статья для вас. Недавно я выполнил команду chmod 777 -R / на одном из наших администраторов AWS EC2, и это […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/ya-ispolzoval-chmod-777-r-i-pochemu-vy-dolzhny-byt-ostorozhny-ili-ne-delat-etogo/\"],\"title\":[0,\"Я использовал Chmod 777 -R / и почему вы должны быть осторожны или не делать этого - Gorlov.\"],\"breadcrumbTitle\":[0,\"Я использовал chmod 777 -R / и почему вы должны быть осторожны или не делать этого\"],\"description\":[0,\"Будучи разработчиком приложений, я никогда особо не интересовался командами Linux, но поскольку сейчас я работаю в очень маленькой компании, мне приходится\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Будучи разработчиком приложений, я никогда особо не интересовался командами Linux, но поскольку сейчас я работаю в очень маленькой компании, мне приходится\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Я использовал Chmod 777 -R / и почему вы должны быть осторожны или не делать этого - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-17T23:17:02+00:00\"],\"url\":[0,\"http://igorlov.loc/ya-ispolzoval-chmod-777-r-i-pochemu-vy-dolzhny-byt-ostorozhny-ili-ne-delat-etogo/\"]}]}],\"title\":[0,\"Я использовал chmod 777 -R / и почему вы должны быть осторожны или не делать этого\"],\"uri\":[0,\"/ya-ispolzoval-chmod-777-r-i-pochemu-vy-dolzhny-byt-ostorozhny-ili-ne-delat-etogo/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"ya-ispolzoval-chmod-777-r-i-pochemu-vy-dolzhny-byt-ostorozhny-ili-ne-delat-etogo\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Linux\\\"],\\\"id\\\":[0,\\\"dGVybToxNDE=\\\"],\\\"uri\\\":[0,\\\"/tag/linux/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0OTM=\"],\"node\":[0,{\"date\":[0,\"2023-03-17T23:07:03\"],\"content\":[0,\"\\n\\n\\n\\n\\n\\nМарк Твен сказал, что секрет успеха заключается в том, чтобы начать. Программирование может показаться сложным для новичков, но лучший способ начать — это погрузиться в него и начать писать код.
\\n
Простые примеры кода — это отличный способ для начинающих намочить ноги и изучить основы программирования. В этой статье я приведу серию простых примеров кода, которые идеально подходят для начинающих пользователей Python.
\\n\\n\\n\\nЭти примеры охватывают целый ряд концепций программирования и помогут вам заложить прочный фундамент в программировании. Если вы новичок в программировании или просто хотите подтянуть свои навыки, эти примеры кода помогут вам начать свой путь в программировании.
\\n\\n\\n\\nЕсли вам нужно изучить основы Python, я добавил несколько полезных ресурсов в конце этого руководства.
\\n\\n\\n\\nВ этом проекте вы создадите простую игру по угадыванию чисел, которая позволит пользователю угадать случайное число от 1 до 100. Программа будет давать пользователю подсказки после каждого угадывания, указывая, было ли его угадывание слишком высоким или слишком низким, пока пользователь не угадает правильное число.
\\n\\n\\n\\nКод:
\\n\\n\\n\\nimport random\\n\\nsecret_number = random.randint(1, 100)\\n\\nwhile True:\\n guess = int(input(\\\"Guess the number between 1 and 100: \\\"))\\n \\n if guess == secret_number:\\n print(\\\"Congratulations! You guessed the number!\\\")\\n break\\n elif guess < secret_number:\\n print(\\\"Too low! Try again.\\\")\\n else:\\n print(\\\"Too high! Try again.\\\")\\n
\\n\\n\\n\\nПояснения:
\\n\\n\\n\\nГенератор паролей, как следует из названия, генерирует случайный пароль определенной длины, используя различные комбинации символов и специальные знаки.
\\n\\n\\n\\nКод:
\\n\\n\\n\\nimport random\\nimport string\\n\\ndef generate_password(length):\\n \\\"\\\"\\\"This function generates a random password\\n of a given length using a combination of\\n uppercase letters, lowercase letters,\\n digits, and special characters\\\"\\\"\\\"\\n \\n # Define a string containing all possible characters\\n all_chars = string.ascii_letters + string.digits + string.punctuation\\n \\n # Generate a password using a random selection of characters\\n password = \\\"\\\".join(random.choice(all_chars) for i in range(length))\\n \\n return password\\n\\n# Test the function by generating a password of length 10\\npassword = generate_password(10)\\nprint(password)\\n
\\n\\n\\n\\nПояснение:
\\n\\n\\n\\nОбратите внимание, что это очень простой генератор паролей, и он может не подойти для использования в реальных сценариях, где безопасность является проблемой.
\\n\\n\\n\\nВ этом разделе мы создадим программу проверки паролей. Его задача – проверить, является ли пароль достаточно надежным, основываясь на некоторых заданных нами критериях. Он выведет ошибку, если какой-либо из критериев пароля не будет выполнен.
\\n\\n\\n\\nКод:
\\n\\n\\n\\n# Define a function to check if the password is strong enough\\ndef password_checker(password):\\n # Define the criteria for a strong password\\n min_length = 8\\n has_uppercase = False\\n has_lowercase = False\\n has_digit = False\\n has_special_char = False\\n special_chars = \\\"!@#$%^&*()-_=+[{]}\\\\|;:',<.>/?\\\"\\n \\n # Check the length of the password\\n if len(password) < min_length:\\n print(\\\"Password is too short!\\\")\\n return False\\n \\n # Check if the password contains an uppercase letter, lowercase letter, digit, and special character\\n for char in password:\\n if char.isupper():\\n has_uppercase = True\\n elif char.islower():\\n has_lowercase = True\\n elif char.isdigit():\\n has_digit = True\\n elif char in special_chars:\\n has_special_char = True\\n \\n # Print an error message for each missing criteria\\n if not has_uppercase:\\n print(\\\"Password must contain at least one uppercase letter!\\\")\\n return False\\n if not has_lowercase:\\n print(\\\"Password must contain at least one lowercase letter!\\\")\\n return False\\n if not has_digit:\\n print(\\\"Password must contain at least one digit!\\\")\\n return False\\n if not has_special_char:\\n print(\\\"Password must contain at least one special character!\\\")\\n return False\\n \\n # If all criteria are met, print a success message\\n print(\\\"Password is strong!\\\")\\n return True\\n\\n# Prompt the user to enter a password and check if it meets the criteria\\npassword = input(\\\"Enter a password: \\\")\\npassword_checker(password)\\n
\\n\\n\\n\\nПояснения:
\\n\\n\\n\\nВеб-скрапер собирает/получает данные с веб-страниц и сохраняет их в любом нужном нам формате, будь то .csv или .txt. В этом разделе мы создадим простой веб-скрапер, используя библиотеку Python под названием Beautiful Soup.
\\n\\n\\n\\nКод:
\\n\\n\\n\\nimport requests\\nfrom bs4 import BeautifulSoup\\n\\n# Set the URL of the webpage you want to scrape\\nurl=\\\"https://www.example.com\\\"\\n\\n# Send an HTTP request to the URL and retrieve the HTML content\\nresponse = requests.get(url)\\n\\n# Create a BeautifulSoup object that parses the HTML content\\nsoup = BeautifulSoup(response.content, 'html.parser')\\n\\n# Find all the links on the webpage\\nlinks = soup.find_all('a')\\n\\n# Print the text and href attribute of each link\\nfor link in links:\\n print(link.get('href'), link.text)\\n
\\n\\n\\n\\nПояснения:
\\n\\n\\n\\nКонвертер валют – это программа, которая помогает пользователям конвертировать стоимость одной валюты в другую. Вы можете использовать его для различных целей, например, для расчета стоимости международных покупок, оценки расходов на путешествия или анализа финансовых данных.
\\n\\n\\n\\nПримечание: для получения данных об обменном курсе мы будем использовать API ExchangeRate-API, который является бесплатным API с открытым исходным кодом для курсов валют. Однако существуют и другие API, которые могут иметь различные ограничения или требования к использованию.
\\n\\n\\n\\nКод:
\\n\\n\\n\\n# Import the necessary modules\\nimport requests\\n\\n# Define a function to convert currencies\\ndef currency_converter(amount, from_currency, to_currency):\\n # Set the API endpoint for currency conversion\\n api_endpoint = f\\\"https://api.exchangerate-api.com/v4/latest/{from_currency}\\\"\\n \\n # Send a GET request to the API endpoint\\n response = requests.get(api_endpoint)\\n \\n # Get the JSON data from the response\\n data = response.json()\\n \\n # Extract the exchange rate for the target currency\\n exchange_rate = data[\\\"rates\\\"][to_currency]\\n \\n # Calculate the converted amount\\n converted_amount = amount * exchange_rate\\n \\n # Return the converted amount\\n return converted_amount\\n\\n# Prompt the user to enter the amount, source currency, and target currency\\namount = float(input(\\\"Enter the amount: \\\"))\\nfrom_currency = input(\\\"Enter the source currency code: \\\").upper()\\nto_currency = input(\\\"Enter the target currency code: \\\").upper()\\n\\n# Convert the currency and print the result\\nresult = currency_converter(amount, from_currency, to_currency)\\nprint(f\\\"{amount} {from_currency} is equal to {result} {to_currency}\\\")\\n
\\n\\n\\n\\nПояснения:
\\n\\n\\n\\nВсе эти проекты очень просты и легко создаются. Если вы действительно хотите улучшить свои навыки работы с Python, я бы посоветовал вам взять этот код, изменить и отредактировать его и развивать его. При желании многие из этих простых проектов можно превратить в гораздо более сложные приложения.
\\n\\n\\n\\nСчастливого кодинга!
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Марк Твен сказал, что секрет успеха заключается в том, чтобы начать. Программирование может показаться сложным для новичков, но лучший способ начать — это погрузиться в него и начать писать код. Простые примеры кода — это отличный способ для начинающих намочить ноги и изучить основы программирования. В этой статье я приведу серию простых примеров кода, которые […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/primery-programm-na-python-prostye-primery-koda-dlya-nachinayushhih/\"],\"title\":[0,\"Примеры программ на Python - простые примеры кода для начинающих - Gorlov.\"],\"breadcrumbTitle\":[0,\"Примеры программ на Python – простые примеры кода для начинающих\"],\"description\":[0,\"Марк Твен сказал, что секрет успеха заключается в том, чтобы начать. Программирование может показаться сложным для новичков, но лучший способ начать — это\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Марк Твен сказал, что секрет успеха заключается в том, чтобы начать. Программирование может показаться сложным для новичков, но лучший способ начать — это\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Примеры программ на Python - простые примеры кода для начинающих - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-17T23:07:31+00:00\"],\"url\":[0,\"http://igorlov.loc/primery-programm-na-python-prostye-primery-koda-dlya-nachinayushhih/\"]}]}],\"title\":[0,\"Примеры программ на Python – простые примеры кода для начинающих\"],\"uri\":[0,\"/primery-programm-na-python-prostye-primery-koda-dlya-nachinayushhih/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"primery-programm-na-python-prostye-primery-koda-dlya-nachinayushhih\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Python\\\"],\\\"id\\\":[0,\\\"dGVybTo2NA==\\\"],\\\"uri\\\":[0,\\\"/tag/python/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjg0OTQ=\"],\"node\":[0,{\"date\":[0,\"2023-03-17T22:56:15\"],\"content\":[0,\"\\nВы хотите тестировать свои смарт-контракты Ethereum, не беспокоясь о том, что у вас закончатся эфиры? В этом руководстве мы покажем вам, как пополнить свой кошелек Metamask любым количеством бесплатных эфиров. Используя эту технику, вы сможете иметь обильный запас эфиров, доступных для использования в тестировании и разработке. Вам понадобится только NodeJs, расширение Chrome для Metamask и несколько простых шагов.
\\n\\n\\n\\nЧтобы следовать этому руководству и загрузить бесплатные эфиры в ваш Metamask, вам понадобятся следующие пакеты:
\\n\\n\\n\\nВы можете посмотреть видеоурок на YouTube с помощью видео ниже.
\\n\\n\\n\\nТеперь давайте рассмотрим шаги и методы, которые вам понадобятся, чтобы загрузить неограниченное количество бесплатных эфиров в кошелек Metamask.
\\n\\n\\n\\nБлагодаря своей гибкости, расширяемости и скорости, многие разработчики и профессионалы web3 приняли Hardhat в качестве основного фреймворка для разработки приложений в сети Ethereum.
\\n\\n\\n\\nНиже описаны шаги по загрузке Эфиров в Metamask с помощью Hardhat.
\\n\\n\\n\\nСоздайте проект под названием **freeTestEthers**, это может быть любой проект на JavaScript, например NodeJs, ReactJs, VueJs или даже проект NextJs. В данном примере мы будем использовать проект NodeJs.
\\n\\n\\n\\nДалее откройте папку проекта в терминале или просто перейдите в эту директорию и выполните следующие команды.
\\n\\n\\n\\ncd freeTestEthers\\nnpm init --y\\n
\\n\\n\\n\\nПриведенная выше команда инициирует папку как проект nodeJs. Смотрите изображение ниже.
\\n\\n\\n\\nУстановите пакеты Hardhat, которые позволят вам запустить сервер блокчейна, в терминале выполните следующие команды:
\\n\\n\\n\\nnpm install hardhat\\n
\\n\\n\\n\\nПосле установки выполните приведенную ниже команду hardhat.
\\n\\n\\n\\nnpx hardhat\\n
\\n\\n\\n\\n\\n\\n\\n\\nТеперь следуйте подсказкам, как показано на изображении ниже, чтобы завершить установку:
\\n\\n\\n\\nПосле завершения установки снова выполните эту команду, чтобы запустить блокчейн-сервер Hardhat:
\\n\\n\\n\\nnpx hardhat node\\n
\\n\\n\\n\\nПриведенная выше команда должна запустить сервер, похожий на тот, что показан на изображении выше. Обратите внимание на разницу между учетными записями и их приватными ключами. Позже мы будем использовать приватные ключи для импорта Эфиров в Metamask.
\\n\\n\\n\\n
Когда Metamask уже установлен, откройте браузер и перейдите по следующей ссылке, которая полностью откроет интерфейс расширения Metamask. Он должен выглядеть так, как показано на рисунке ниже.
Теперь нам нужно указать Metamask использовать сервер Hardhat, запущенный на шаге 3 этого раздела. Metamask обычно поставляется с сетью Localhost по умолчанию, в которой настроен Hardhat, поэтому нам не нужно настраивать сеть с нуля.
\\n\\n\\n\\nПерейдите на страницу сетей в Metamask и убедитесь, что ваша настройка находится на той же странице, что и моя.
\\n\\n\\n\\nВы заметили конфигурацию сети на изображении выше?
\\n\\n\\n\\n
Из шага 3 скопируйте первый закрытый ключ для нулевого (0) аккаунта, как показано на следующем изображении.
Теперь убедитесь, что вы выбрали Localhost в качестве предпочитаемой сети и нажмите на кнопку “импортировать учетную запись”, как показано на изображении ниже.
\\n\\n\\n\\nПоздравляем, вы смогли импортировать новый аккаунт, используя его закрытый ключ, теперь сравните, как через закрытый ключ адрес аккаунта 5 совпадает с тем, что изображен на картинке ниже.
\\n\\n\\n\\nТеперь вы можете повторить этот процесс, чтобы импортировать больше аккаунтов с вашего сервера Hardhat.
\\n\\n\\n\\nПосле реализации этого одноразового процесса при каждом запуске блокчейн-сервера Hardhat ваш счет будет пополняться свежим балансом в 10 000 ETH. Теперь вы можете использовать все эти эфиры для своих процессов разработки Hardhat.
\\n\\n\\n\\nTruffle – один из самых полных наборов инструментов для разработки смарт-контрактов. Для сервера блокчейна у них есть Ganache.
\\n\\n\\n\\nС Ganache вам не нужно устанавливать его на конкретный проект, вам просто нужно настроить его глобально один раз на вашей локальной машине. Вот шаги по загрузке Эфиров в Metamask с помощью Ganache.
\\n\\n\\n\\n
Чтобы установить Ganache глобально на вашей машине, выполните следующую команду в терминале:
npm install ganache --global //or\\nsudo npm install ganache --global\\n
\\n\\n\\n\\nПосле установки вы должны увидеть результат, подобный приведенному ниже изображению.
\\n\\n\\n\\nПосле завершения установки выполните приведенную ниже команду, чтобы запустить блокчейн-сервер Ganache:
\\n\\n\\n\\nganache -d\\n
\\n\\n\\n\\nС помощью вышеупомянутой команды необходимо создать сервер, похожий на тот, что показан на изображении выше. Обратите внимание на то, как различаются учетные записи и их приватные ключи. Закрытые ключи в конечном итоге будут использоваться для импорта Эфиров в Metamask так же, как мы это делали с Hardhat.
\\n\\n\\n\\n
Еще раз мы должны указать Metamask подключиться к серверу Ganache, который был активен в шаге 3 этого раздела. На этот раз совершенно новая сеть будет добавлена с нуля.
Убедитесь, что ваша конфигурация находится на той же странице, что и моя, на странице сетей Metamask.
\\n\\n\\n\\nТеперь следует знать, что единственным различием между серверами Hardhat и Ganache является их идентификатор цепи. В то время как Hardhat имеет идентификатор цепи 31337, Ganache имеет 1337. Убедитесь, что вы нажали кнопку сохранения, чтобы добавить его в список сетей.
\\n\\n\\n\\n
Из шага 3 скопируйте первый закрытый ключ для учетной записи ноль (0), как показано на следующем изображении.
Теперь убедитесь, что вы выбрали Localhost в качестве предпочитаемой сети и нажмите на кнопку “импортировать учетную запись”, как показано на изображении ниже.
\\n\\n\\n\\nПоздравляем, вы смогли импортировать новый аккаунт, используя его закрытый ключ, теперь сравните, как через закрытый ключ адрес аккаунта 5 совпадает с тем, что изображен на картинке ниже.
\\n\\n\\n\\nВы можете импортировать счета в свой кошелек Metamask таким образом. Выполнив эту процедуру сейчас, вы сможете импортировать больше аккаунтов сервера Ganache.
\\n\\n\\n\\nПосле завершения этой одноразовой процедуры каждый раз, когда вы включаете блокчейн-сервер Hardhat, на вашем счете будет обновляться баланс на 1 000 ETH. Все эти Эфиры теперь доступны для использования в ваших процедурах разработки Hardhat.
\\n\\n\\n\\nВ заключение, данное руководство предлагает два метода, Hardhat и Ganache, для добавления неограниченного количества бесплатных Эфиров на кошелек Metamask в целях тестирования и разработки. Оба метода требуют установки NodeJs, расширения Chrome для Metamask и использования фреймворка Hardhat или Ganache. Следуя шагам, описанным в руководстве, пользователи смогут легко загружать Эфиры на свой кошелек Metamask и иметь обильный запас для тестирования и разработки смарт-контрактов Ethereum.
\\n\\n\\n\\nНа этом мы закончили этот урок, спасибо за внимание, до встречи в следующем уроке!
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Введение Вы хотите тестировать свои смарт-контракты Ethereum, не беспокоясь о том, что у вас закончатся эфиры? В этом руководстве мы покажем вам, как пополнить свой кошелек Metamask любым количеством бесплатных эфиров. Используя эту технику, вы сможете иметь обильный запас эфиров, доступных для использования в тестировании и разработке. Вам понадобится только NodeJs, расширение Chrome для Metamask […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/kak-zagruzit-neogranichennoe-kolichestvo-besplatnyh-efirov-v-koshelek-metamask/\"],\"title\":[0,\"Как загрузить неограниченное количество бесплатных эфиров в кошелек Metamask - Gorlov.\"],\"breadcrumbTitle\":[0,\"Как загрузить неограниченное количество бесплатных эфиров в кошелек Metamask\"],\"description\":[0,\"Вы хотите тестировать свои смарт-контракты Ethereum, не беспокоясь о том, что у вас закончатся эфиры? В этом руководстве мы покажем вам, как пополнить свой\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Вы хотите тестировать свои смарт-контракты Ethereum, не беспокоясь о том, что у вас закончатся эфиры? В этом руководстве мы покажем вам, как пополнить свой\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Как загрузить неограниченное количество бесплатных эфиров в кошелек Metamask - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-17T22:56:16+00:00\"],\"url\":[0,\"http://igorlov.loc/kak-zagruzit-neogranichennoe-kolichestvo-besplatnyh-efirov-v-koshelek-metamask/\"]}]}],\"title\":[0,\"Как загрузить неограниченное количество бесплатных эфиров в кошелек Metamask\"],\"uri\":[0,\"/kak-zagruzit-neogranichennoe-kolichestvo-besplatnyh-efirov-v-koshelek-metamask/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"kak-zagruzit-neogranichennoe-kolichestvo-besplatnyh-efirov-v-koshelek-metamask\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"blockchain\\\"],\\\"id\\\":[0,\\\"dGVybToxNzM=\\\"],\\\"uri\\\":[0,\\\"/tag/blockchain/\\\"]}],[0,{\\\"name\\\":[0,\\\"ethereum\\\"],\\\"id\\\":[0,\\\"dGVybToxNzQ=\\\"],\\\"uri\\\":[0,\\\"/tag/ethereum/\\\"]}],[0,{\\\"name\\\":[0,\\\"metamask\\\"],\\\"id\\\":[0,\\\"dGVybToxNzI=\\\"],\\\"uri\\\":[0,\\\"/tag/metamask/\\\"]}],[0,{\\\"name\\\":[0,\\\"Web3\\\"],\\\"id\\\":[0,\\\"dGVybToxNzE=\\\"],\\\"uri\\\":[0,\\\"/tag/web3/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjgwNjE=\"],\"node\":[0,{\"date\":[0,\"2023-03-16T00:53:50\"],\"content\":[0,\"\\nКак веб-разработчик, безопасность всегда должна быть главным приоритетом при создании любого веб-приложения. Одна из наиболее распространенных уязвимостей безопасности, с которой сталкиваются веб-разработчики, называется межсайтовым скриптингом или XSS. В этой статье мы обсудим, что такое XSS, как он работает, а также лучшие методы предотвращения XSS-уязвимостей в ваших веб-приложениях.
\\n\\n\\n\\nМежсайтовый скриптинг (XSS) – это тип уязвимости безопасности, который позволяет злоумышленникам внедрять вредоносный код на веб-страницы, просматриваемые другими пользователями. Этот код может быть использован для кражи конфиденциальной информации, включая учетные данные для входа в систему, или для получения контроля над сеансами пользователей.
\\n\\n\\n\\nXSS-атаки обычно осуществляются через поля ввода в веб-формах, таких как окна поиска, разделы комментариев или страницы входа в систему.
\\n\\n\\n\\nСуществует три типа XSS-атак:
\\n\\n\\n\\nXSS-атаки обычно используют веб-приложения, которые не могут должным образом санировать пользовательский ввод перед его отображением на веб-странице. Это позволяет злоумышленникам внедрять вредоносный код, например, JavaScript, в веб-страницы, которые затем выполняются браузерами других пользователей.
\\n\\n\\n\\nВот пример веб-приложения, уязвимого к XSS:
\\n\\n\\n\\n<form>\\n <input type=\\\"text\\\" name=\\\"search\\\" placeholder=\\\"Search...\\\">\\n <button type=\\\"submit\\\">Search</button>\\n</form>\\n
\\n\\n\\n\\nЗлоумышленник может внедрить в окно поиска следующий вредоносный код:
\\n\\n\\n\\n<script>\\n alert('You have been hacked!');\\n</script>\\n
\\n\\n\\n\\nЕсли веб-приложение не сможет санитаризовать пользовательский ввод, вредоносный код будет выполнен браузером пользователя при просмотре страницы с результатами поиска.
\\n\\n\\n\\nПредотвращение XSS-уязвимостей в ваших веб-приложениях требует многоуровневого подхода, включающего защиту как на стороне сервера, так и на стороне клиента.
\\n\\n\\n\\nВот несколько лучших практик для предотвращения XSS-уязвимостей:
\\n\\n\\n\\n<script>
любые символы, используемые в функциях JavaScript или обработчиках событий.В заключение следует отметить, что XSS-атаки представляют собой серьезную угрозу безопасности, которая может привести к раскрытию пользовательских данных и компрометации веб-приложений. Применяя лучшие практики, рассмотренные в этой статье, веб-разработчики могут снизить риск XSS-уязвимостей и обеспечить безопасность своих приложений.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Как веб-разработчик, безопасность всегда должна быть главным приоритетом при создании любого веб-приложения. Одна из наиболее распространенных уязвимостей безопасности, с которой сталкиваются веб-разработчики, называется межсайтовым скриптингом или XSS. В этой статье мы обсудим, что такое XSS, как он работает, а также лучшие методы предотвращения XSS-уязвимостей в ваших веб-приложениях. Что такое межсайтовый скриптинг (XSS)? Межсайтовый скриптинг (XSS) […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/ponimanie-uyazvimosti-mezhsajtovogo-skriptinga-xss/\"],\"title\":[0,\"Понимание уязвимости межсайтового скриптинга (XSS) - Gorlov.\"],\"breadcrumbTitle\":[0,\"Понимание уязвимости межсайтового скриптинга (XSS)\"],\"description\":[0,\"Как веб-разработчик, безопасность всегда должна быть главным приоритетом при создании любого веб-приложения. Одна из наиболее распространенных уязвимостей\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Как веб-разработчик, безопасность всегда должна быть главным приоритетом при создании любого веб-приложения. Одна из наиболее распространенных уязвимостей\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Понимание уязвимости межсайтового скриптинга (XSS) - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-16T00:54:19+00:00\"],\"url\":[0,\"http://igorlov.loc/ponimanie-uyazvimosti-mezhsajtovogo-skriptinga-xss/\"]}]}],\"title\":[0,\"Понимание уязвимости межсайтового скриптинга (XSS)\"],\"uri\":[0,\"/ponimanie-uyazvimosti-mezhsajtovogo-skriptinga-xss/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"ponimanie-uyazvimosti-mezhsajtovogo-skriptinga-xss\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"JavaScript\\\"],\\\"id\\\":[0,\\\"dGVybTo0Mw==\\\"],\\\"uri\\\":[0,\\\"/tag/javascript/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjgxNDg=\"],\"node\":[0,{\"date\":[0,\"2023-03-15T20:46:40\"],\"content\":[0,\"\\nAmazon Simple Storage Service (S3) – это высокомасштабируемая, долговечная и малозамедленная служба хранения объектов, предоставляемая AWS. Она предназначена для хранения и извлечения любого объема данных, что делает ее важным компонентом для многих веб-приложений, озер данных и аналитики больших данных.
\\n\\n\\n\\nВ этом руководстве мы рассмотрим основы работы с Amazon S3, включая создание ведра S3, загрузку и извлечение объектов, а также настройку контроля доступа.
\\n\\n\\n\\nПеред началом работы вы должны иметь:
\\n\\n\\n\\nБакет — это контейнер для объектов, хранящихся в Amazon S3. Ведра служат фундаментальной единицей организации и контроля доступа к данным в S3.
\\n\\n\\n\\nЧтобы создать ведро с помощью AWS CLI, выполните следующую команду:
\\n\\n\\n\\naws s3api create-bucket --bucket YOUR_BUCKET_NAME --region YOUR_REGION --create-bucket-configuration LocationConstraint=YOUR_REGION\\n
\\n\\n\\n\\nЗамените YOUR_BUCKET_NAME на уникальное имя вашего bucket и YOUR_REGION на желаемый регион AWS.
\\n\\n\\n\\nЗагрузка и скачивание файлов в бакет S3 с помощью консоли довольно просты: для загрузки файла нажмите на кнопку Upload и выберите нужный файл, а для скачивания выберите файл из ведра S3 и нажмите на кнопку Download.
\\n\\n\\n\\nЧтобы загрузить локальный файл в S3 bucket с помощью AWS CLI, выполните следующую команду:
\\n\\n\\n\\naws s3 cp LOCAL_FILE_PATH s3://YOUR_BUCKET_NAME/DESTINATION_KEY\\n
\\n\\n\\n\\nЗамените LOCAL_FILE_PATH на путь к вашему локальному файлу, YOUR_BUCKET_NAME на имя вашего S3 bucket, а DESTINATION_KEY на ключ (путь), который вы хотите присвоить объекту в bucket.
\\n\\n\\n\\nЧтобы загрузить объект из вашего S3 bucket с помощью AWS CLI, выполните следующую команду:
\\n\\n\\n\\naws s3 cp s3://YOUR_BUCKET_NAME/SOURCE_KEY LOCAL_FILE_PATH\\n
\\n\\n\\n\\nЗамените YOUR_BUCKET_NAME на имя вашего ведра S3, SOURCE_KEY на ключ объекта, который вы хотите загрузить, а LOCAL_FILE_PATH на локальный путь, по которому вы хотите сохранить загруженный файл.
\\n\\n\\n\\nПолитики ведра – это документы JSON, определяющие правила предоставления прав доступа к вашему ведру S3. Вы можете использовать политику ведра для предоставления или запрета доступа к определенным действиям или ресурсам.
\\n\\n\\n\\nЧтобы прикрепить политику ведра с помощью консоли управления AWS Management Console:
\\n\\n\\n\\nВот и все! В этом руководстве для начинающих мы лишь поцарапали поверхность удивительного мира Amazon S3. Имея за плечами S3, вы уже на пути к созданию невероятных решений для хранения данных в ваших проектах. Помните, что практика делает совершенным, поэтому не бойтесь погружаться и изучать S3 дальше.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Amazon Simple Storage Service (S3) – это высокомасштабируемая, долговечная и малозамедленная служба хранения объектов, предоставляемая AWS. Она предназначена для хранения и извлечения любого объема данных, что делает ее важным компонентом для многих веб-приложений, озер данных и аналитики больших данных. В этом руководстве мы рассмотрим основы работы с Amazon S3, включая создание ведра S3, загрузку и […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/nachalo-raboty-s-amazon-s3/\"],\"title\":[0,\"Начало работы с Amazon S3 - Gorlov.\"],\"breadcrumbTitle\":[0,\"Начало работы с Amazon S3\"],\"description\":[0,\"Amazon Simple Storage Service (S3) - это высокомасштабируемая, долговечная и малозамедленная служба хранения объектов, предоставляемая AWS. Она предназначена\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Amazon Simple Storage Service (S3) - это высокомасштабируемая, долговечная и малозамедленная служба хранения объектов, предоставляемая AWS. Она предназначена\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Начало работы с Amazon S3 - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-15T20:46:42+00:00\"],\"url\":[0,\"http://igorlov.loc/nachalo-raboty-s-amazon-s3/\"]}]}],\"title\":[0,\"Начало работы с Amazon S3\"],\"uri\":[0,\"/nachalo-raboty-s-amazon-s3/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"nachalo-raboty-s-amazon-s3\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Amazon S3\\\"],\\\"id\\\":[0,\\\"dGVybToxNzA=\\\"],\\\"uri\\\":[0,\\\"/tag/amazon-s3/\\\"]}],[0,{\\\"name\\\":[0,\\\"AWS\\\"],\\\"id\\\":[0,\\\"dGVybToxNTI=\\\"],\\\"uri\\\":[0,\\\"/tag/aws/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjgxNTE=\"],\"node\":[0,{\"date\":[0,\"2023-03-15T20:32:55\"],\"content\":[0,\"\\nВ прошлой статье я рассказал об основах взаимодействия с базами данных DynamoDB с помощью CDK. В этой статье я расскажу о том, как хранить данные в виде файлов с помощью Amazon S3. Эта серия будет продолжаться! Следите за мной в twitter или DEV, чтобы получить уведомление о публикации следующей статьи!
\\n\\n\\n\\nДве недели назад я рассказал об основах взаимодействия с базами данных DynamoDB. Эти базы данных отлично подходят для хранения структурированных данных, состоящих из небольших элементов: предельный размер одного элемента составляет 400 КБ. Однако что, если вы хотите хранить большие файлы? В этом случае следует использовать Amazon S3, сервис, позволяющий хранить файлы в облаке.
\\n\\n\\n\\nAmazon S3 очень мощный, потому что он может хранить практически бесконечное количество данных и оставаться доступным 99,99999999999% времени. Это также очень дешево, поскольку вы платите только за используемое хранилище и объем передаваемых данных.
\\n\\n\\n\\nВместе мы собираемся создать небольшой клон dev.to, позволяющий пользователям публиковать, размещать и читать статьи. Содержимое статей, которое может быть довольно большим, мы будем хранить в Amazon S3, а метаданные (название статьи, автор и т.д.) – в DynamoDB: это будет отличный обзор предыдущей статьи!
\\n\\n\\n\\nВ Amazon S3 файлы хранятся в ведрах. Ведро – это контейнер для файлов, и оно имеет уникальное имя. Каждое ведро может содержать почти бесконечное количество файлов. Вы также можете создавать подпапки в ведре и хранить файлы в этих подпапках.
\\n\\n\\n\\nВот небольшая схема архитектуры, которую мы будем строить:
\\n\\n\\n\\nПриложение будет содержать 3 лямбда-функции, базу данных DynamoDB, ведро S3 и REST API, взаимодействующие между собой.
\\n\\n\\n\\nКак и в других статьях этого цикла, мы будем использовать AWS CDK для создания нашей инфраструктуры. Я начну с проекта, над которым работал в прошлой статье, и добавлю необходимый код для создания ведра S3. Если вы хотите следовать за мной, вы можете клонировать этот репозиторий и проверить ветку баз данных.
\\n\\n\\n\\nСоздать ведро очень просто, нужно лишь добавить следующий код в файл learn-serverless-stack.ts
, в конструктор:
// Previous code\\n\\nexport class LearnServerlessStack extends cdk.Stack {\\n // Previous code\\n constructor(scope: Construct, id: string, props?: cdk.StackProps) {\\n super(scope, id, props);\\n\\n // Previous code\\n const articlesBucket = new cdk.aws_s3.Bucket(this, 'articlesBucket', {});\\n }\\n}\\n
\\n\\n\\n\\nВидите, ничего сложного! Обратите внимание, что я не указал никакого имени для ведра, CDK автоматически сгенерирует его за меня. Если вы хотите указать имя, вы можете сделать это, передав его в качестве параметра, но имейте в виду, что имя должно быть уникальным в мире, иначе развертывание будет неудачным.
\\n\\n\\n\\nДавайте создадим таблицу DynamoDB для хранения метаданных наших статей. Мы также создадим три функции Lambda: одну для создания статьи, одну для списка всех статей и одну для чтения конкретной статьи.
\\n\\n\\n\\n// Previous code\\n\\n// Create the database\\nconst articlesDatabase = new cdk.aws_dynamodb.Table(this, 'articlesDatabase', {\\n partitionKey: {\\n name: 'PK',\\n type: cdk.aws_dynamodb.AttributeType.STRING,\\n },\\n sortKey: {\\n name: 'SK',\\n type: cdk.aws_dynamodb.AttributeType.STRING,\\n },\\n billingMode: cdk.aws_dynamodb.BillingMode.PAY_PER_REQUEST,\\n});\\n\\n// Create the publishArticle Lambda function\\nconst publishArticle = new cdk.aws_lambda_nodejs.NodejsFunction(this, 'publishArticle', {\\n entry: path.join(__dirname, 'publishArticle', 'handler.ts'),\\n handler: 'handler',\\n environment: {\\n BUCKET_NAME: articlesBucket.bucketName,\\n TABLE_NAME: articlesDatabase.tableName,\\n },\\n});\\n\\n// Create the listArticles Lambda function\\nconst listArticles = new cdk.aws_lambda_nodejs.NodejsFunction(this, 'listArticles', {\\n entry: path.join(__dirname, 'listArticles', 'handler.ts'),\\n handler: 'handler',\\n environment: {\\n BUCKET_NAME: articlesBucket.bucketName,\\n TABLE_NAME: articlesDatabase.tableName,\\n },\\n});\\n\\n// Create the getArticle Lambda function\\nconst getArticle = new cdk.aws_lambda_nodejs.NodejsFunction(this, 'getArticle', {\\n entry: path.join(__dirname, 'getArticle', 'handler.ts'),\\n handler: 'handler',\\n environment: {\\n BUCKET_NAME: articlesBucket.bucketName,\\n },\\n});\\n
\\n\\n\\n\\nЕсли вернуться к схеме архитектуры, то можно увидеть, что существуют взаимодействия между функциями Lambda и S3 Bucket и таблицей DynamoDB:
\\n\\n\\n\\npublishArticle
и getArticle
-> я передал имя моего нового ведра в качестве переменной окружения функциям Lambda.publishArticle
и listArticles
-> я передал имя моей новой таблицы в качестве переменной окружения функциям Lambda.Эти переменные окружения будут использоваться функциями Lambda для взаимодействия с S3 Bucket и таблицей DynamoDB.
\\n\\n\\n\\nРазрешения являются основой безопасности в приложениях AWS. Если вы не предоставите явных разрешений вашим функциям Lambda, они не смогут взаимодействовать с ведром S3 и таблицей DynamoDB. Мы будем использовать методы grantRead
и grantWrite для предоставления разрешений нашим Lambda-функциям.
// Previous code\\narticlesBucket.grantWrite(publishArticle);\\narticlesDatabase.grantWriteData(publishArticle);\\n\\narticlesDatabase.grantReadData(listArticles);\\n\\narticlesBucket.grantRead(getArticle);\\n
\\n\\n\\n\\nНаконец, давайте подключим наши функции Lambda к REST API. Судя по прошлым статьям, API уже существует, и нам просто нужно добавить к нему новый ресурс. Мы создадим новый ресурс под названием articles
и добавим к нему три метода: POST
, GET
и GET /{id}
.
// Previous code\\nconst articlesResource = myFirstApi.root.addResource('articles');\\n\\narticlesResource.addMethod('POST', new cdk.aws_apigateway.LambdaIntegration(publishArticle));\\narticlesResource.addMethod('GET', new cdk.aws_apigateway.LambdaIntegration(listArticles));\\narticlesResource.addResource('{id}').addMethod('GET', new cdk.aws_apigateway.LambdaIntegration(getArticle));\\n
\\n\\n\\n\\nИ мы закончили с инфраструктурой! Осталось написать код наших лямбда-функций (самая интересная часть 😎).
\\n\\n\\n\\nНачнем с лямбда-функции publishArticle
. Эта функция будет вызываться, когда пользователь захочет опубликовать статью. Она получит название, содержание и автора статьи из тела запроса, сохранит статью в S3 Bucket и ее метаданные в таблице DynamoDB.
import { DynamoDBClient, PutItemCommand } from '@aws-sdk/client-dynamodb';\\nimport { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';\\nimport { v4 as uuidv4 } from 'uuid';\\n\\nconst dynamoDBClient = new DynamoDBClient({});\\nconst s3Client = new S3Client({});\\n\\nexport const handler = async (event: { body: string }): Promise<{ statusCode: number; body: string }> => {\\n // parse the request body\\n const { title, content, author } = JSON.parse(event.body) as { title?: string; content?: string; author?: string };\\n\\n if (title === undefined || content === undefined || author === undefined) {\\n return Promise.resolve({ statusCode: 400, body: 'Missing title or content' });\\n }\\n\\n // generate a unique id for the article\\n const id = uuidv4();\\n\\n // store the article metadata in the database PK = article, SK = ${id}\\n await dynamoDBClient.send(\\n new PutItemCommand({\\n TableName: process.env.TABLE_NAME,\\n Item: {\\n PK: { S: `article` },\\n SK: { S: id },\\n title: { S: title },\\n author: { S: title },\\n },\\n }),\\n );\\n\\n // store the article content in the bucket\\n await s3Client.send(\\n new PutObjectCommand({\\n Bucket: process.env.BUCKET_NAME,\\n Key: id,\\n Body: content,\\n }),\\n );\\n\\n // return the id of the article\\n return { statusCode: 200, body: JSON.stringify({ id }) };\\n};\\n
\\n\\n\\n\\nВ приведенном выше коде я использовал пакеты @aws-sdk/client-dynamodb
и @aws-sdk/client-s3
для взаимодействия с таблицей DynamoDB и ведром S3. Я использовал команды PutItemCommand
и PutObjectCommand
для хранения метаданных и содержимого статьи в таблице DynamoDB и ведре S3.
Если вам нужно освежить в памяти, как взаимодействовать с DynamoDB, ознакомьтесь с моей последней статьей;
\\n\\n\\n\\nОбратите внимание, что я использовал переменные окружения process.env.TABLE_NAME
и process.env.BUCKET_NAME
для получения имени таблицы DynamoDB и ведра S3, эти переменные окружения были установлены в CDK ранее!
Лямбда-функция getArticle
будет вызываться, когда пользователь захочет получить статью. Она получит id статьи из параметров пути запроса и вернет содержимое статьи, хранящееся в S3 Bucket.
import { GetObjectCommand, GetObjectCommandOutput, S3Client } from '@aws-sdk/client-s3';\\n\\nconst client = new S3Client({});\\n\\nexport const handler = async ({\\n pathParameters: { id },\\n}: {\\n pathParameters: { id: string };\\n}): Promise<{ statusCode: number; body: string }> => {\\n let result: GetObjectCommandOutput | undefined;\\n\\n // get the article content from the bucket using the id as the key\\n try {\\n result = await client.send(\\n new GetObjectCommand({\\n Bucket: process.env.BUCKET_NAME,\\n Key: id,\\n }),\\n );\\n } catch {\\n result = undefined;\\n }\\n\\n if (result?.Body === undefined) {\\n return { statusCode: 404, body: 'Article not found' };\\n }\\n\\n // transform the body of the response to a string\\n const content = await result.Body.transformToString();\\n\\n // return the article content\\n return {\\n statusCode: 200,\\n body: JSON.stringify({ content }),\\n };\\n};\\n
\\n\\n\\n\\nВ приведенном выше коде я использовал пакет @aws-sdk/client-s3
для взаимодействия с S3 Bucket. Я использовал команду GetObjectCommand
для получения содержимого статьи из ведра S3. Указанный ключ id – это id статьи (помните, что я использовал этот id для создания объекта в PublishArticle).
Команда GetObjectCommand возвращает объект GetObjectCommandOutput
, который содержит тело ответа. Если запрос не встречает проблем, я использую метод transformToString, чтобы преобразовать тело в строку и вернуть ее.
Лямбда-функция listArticles
будет вызываться, когда пользователь захочет перечислить все статьи. Она вернет список метаданных статей, хранящихся в таблице DynamoDB. Пока что у нее не будет никаких параметров.
import { DynamoDBClient, QueryCommand } from '@aws-sdk/client-dynamodb';\\n\\nconst client = new DynamoDBClient({});\\n\\nexport const handler = async (): Promise<{ statusCode: number; body: string }> => {\\n // Query the list of the articles with the PK = 'article'\\n const { Items } = await client.send(\\n new QueryCommand({\\n TableName: process.env.TABLE_NAME,\\n KeyConditionExpression: 'PK = :pk',\\n ExpressionAttributeValues: {\\n ':pk': { S: 'article' },\\n },\\n }),\\n );\\n\\n if (Items === undefined) {\\n return { statusCode: 500, body: 'No articles found' };\\n }\\n\\n // map the results (un-marshall the DynamoDB attributes)\\n const articles = Items.map(item => ({\\n id: item.SK?.S,\\n title: item.title?.S,\\n author: item.author?.S,\\n }));\\n\\n // return the list of articles (title, id and author)\\n return {\\n statusCode: 200,\\n body: JSON.stringify({ articles }),\\n };\\n};\\n
\\n\\n\\n\\nЭта функция Lambda менее интересна, так как она работает только с DynamoDB, я использую команду QueryCommand для перечисления всех элементов таблицы с PK = ‘article’. (помните, что я установил PK = ‘article’ и SK = ‘${id}’, когда хранил метаданные статьи в PublishArticle).
\\n\\n\\n\\nСначала необходимо развернуть приложение. Для этого нужно выполнить следующую команду:
\\n\\n\\n\\nnpm run cdk deploy\\n
\\n\\n\\n\\nКак только вы закончите, перейдите в Postman и протестируйте ваш новый API!
\\n\\n\\n\\nДавайте создадим статью с помощью POST-вызова, содержащего правильное тело:
\\n\\n\\n\\nЗатем вы можете перечислить все статьи с помощью вызова GET:
\\n\\n\\n\\nИ, наконец, вы можете получить содержимое только что созданной статьи с помощью вызова GET:
\\n\\n\\n\\nНо теперь, чтобы увидеть силу S3, давайте создадим вторую статью с гораздо, гораздо, гораздо большим содержанием:
\\n\\n\\n\\nВы можете видеть, что список статей обновляется автоматически:
\\n\\n\\n\\nИ когда вы получаете содержимое второй статьи, вы видите, что полезная нагрузка намного больше, чем 800kB!!! Это никогда бы не поместилось в элемент DynamoDB! Вот в чем сила S3!
\\n\\n\\n\\nМы просто создали простой S3 Bucket, используя минимально возможную конфигурацию. Но мы можем улучшить качество нашего приложения, добавив некоторые функции:
\\n\\n\\n\\nДля этого давайте обновим конфигурацию нашего ведра S3:
\\n\\n\\n\\n// Previously, we had:\\nconst articlesBucket = new cdk.aws_s3.Bucket(this, 'articlesBucket', {});\\n\\n// Now, we have:\\nconst articlesBucket = new cdk.aws_s3.Bucket(this, 'articlesBucket', {\\n lifecycleRules: [\\n // Enable intelligent tiering\\n {\\n transitions: [\\n {\\n storageClass: cdk.aws_s3.StorageClass.INTELLIGENT_TIERING,\\n transitionAfter: cdk.Duration.days(0),\\n },\\n ],\\n },\\n ],\\n blockPublicAccess: cdk.aws_s3.BlockPublicAccess.BLOCK_ALL, // Enable block public access\\n encryption: cdk.aws_s3.BucketEncryption.S3_MANAGED, // Enable encryption\\n});\\n
\\n\\n\\n\\nСуществует множество других небольших улучшений, которые вы можете сделать не только с этим Bucket, но и с вашими Lambdas или API! Я создал инструмент под названием sls-mentor, который поможет вам улучшить качество вашего бессерверного приложения. Он проверит ваш код и вашу конфигурацию и даст вам рекомендации по улучшению вашего приложения!
\\n\\n\\n\\nПо сути, это большой облачный линтер, не стесняйтесь проверить его, чтобы узнать больше о AWS!
\\n\\n\\n\\nМы создали простое приложение для публикации и чтения статей. Но оно не идеально, есть некоторые вещи, которые мы можем улучшить:
\\n\\n\\n\\nВот это программа! Надеюсь, вам понравилась эта статья, и вы узнали что-то новое. Если у вас есть вопросы, не стесняйтесь обращаться ко мне!
\\n\\n\\n\\nПомните, что код, описанный в этой статье, вы можете найти в моем репозитории.
\\n\\n\\n\\nЯ планирую продолжать эту серию статей раз в два месяца. Я уже рассказал о создании простых лямбда-функций и REST API, а также о взаимодействии с базами данных DynamoDB. Вы можете следить за этим прогрессом на моем репозитории! Я буду освещать новые темы, такие как хранение файлов, создание приложений, управляемых событиями, и многое другое. Если у вас есть какие-либо предложения, не стесняйтесь обращаться ко мне!
\\n\\n\\n\\nЯ буду очень признателен, если вы отреагируете и поделитесь этой статьей со своими друзьями и коллегами. Это очень поможет мне расширить свою аудиторию. Также не забудьте подписаться на рассылку, чтобы быть в курсе, когда выйдет следующая статья!
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
В прошлой статье я рассказал об основах взаимодействия с базами данных DynamoDB с помощью CDK. В этой статье я расскажу о том, как хранить данные в виде файлов с помощью Amazon S3. Эта серия будет продолжаться! Следите за мной в twitter или DEV, чтобы получить уведомление о публикации следующей статьи! Бессерверное хранение файлов с помощью […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/izuchajte-serverless-na-aws-shag-za-shagom-fajlovoe-hranilishhe/\"],\"title\":[0,\"Изучайте Serverless на AWS шаг за шагом — Файловое хранилище - Gorlov.\"],\"breadcrumbTitle\":[0,\"Изучайте serverless на AWS шаг за шагом — Файловое хранилище\"],\"description\":[0,\"В прошлой статье я рассказал об основах взаимодействия с базами данных DynamoDB с помощью CDK. В этой статье я расскажу о том, как хранить данные в виде\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"В прошлой статье я рассказал об основах взаимодействия с базами данных DynamoDB с помощью CDK. В этой статье я расскажу о том, как хранить данные в виде\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Изучайте Serverless на AWS шаг за шагом — Файловое хранилище - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-15T20:33:12+00:00\"],\"url\":[0,\"http://igorlov.loc/izuchajte-serverless-na-aws-shag-za-shagom-fajlovoe-hranilishhe/\"]}]}],\"title\":[0,\"Изучайте serverless на AWS шаг за шагом — Файловое хранилище\"],\"uri\":[0,\"/izuchajte-serverless-na-aws-shag-za-shagom-fajlovoe-hranilishhe/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"izuchajte-serverless-na-aws-shag-za-shagom-fajlovoe-hranilishhe\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"AWS\\\"],\\\"id\\\":[0,\\\"dGVybToxNTI=\\\"],\\\"uri\\\":[0,\\\"/tag/aws/\\\"]}],[0,{\\\"name\\\":[0,\\\"Serverless\\\"],\\\"id\\\":[0,\\\"dGVybToxNjk=\\\"],\\\"uri\\\":[0,\\\"/tag/serverless/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjc0MTM=\"],\"node\":[0,{\"date\":[0,\"2023-03-07T23:06:30\"],\"content\":[0,\"\\nЗагрузка файлов – одна из распространенных функций, которую использует большинство приложений, и все же это одна из тех вещей, с которыми, как я вижу, многие люди испытывают трудности.
\\n\\n\\n\\nLaravel предлагает простой API для работы с локальной файловой системой:
\\n\\n\\n\\nStorage::putFileAs('images', $request->file('file'));\\n
\\n\\n\\n\\nЧасто пользователю необходимо обработать проверку файла, его размер, размеры, имя, видимость, путь, диск и т.д.
\\n\\n\\n\\nМы хотим создать форму, которая позволит нам загрузить файл и отправить его – а маршрут будет принимать эту форму, проверять вводимые данные и обрабатывать загрузку.
\\n\\n\\n\\nВ этой статье я сделаю пошаговое руководство по загрузке файлов на Laravel 10 с использованием пакета erlandmuchasaj/laravel-file-uploader.
В этом учебнике мы создадим 2 маршрута.
Один для создания формы, куда пользователь будет загружать файл, а другой маршрут для загрузки файла с помощью пакета.
Мы создадим простую форму, используя компоненты Bootstrap Form UI.
Прежде всего, создадим новый проект Laravel.
Откройте инструмент командной строки и выполните следующую команду, чтобы создать проект Laravel с нуля.
composer create-project laravel/laravel --prefer-dist laravel-file-uploader\\n
\\n\\n\\n\\nЗатем мы заходим в только что созданный каталог проекта:
\\n\\n\\n\\ncd laravel-file-uploader\\n
\\n\\n\\n\\nЗатем мы устанавливаем пакет laravel-file-uploader.
\\n\\n\\n\\ncomposer require erlandmuchasaj/laravel-file-uploader\\n
\\n\\n\\n\\nПосле этого мы создаем символическую ссылку для доступа к файлам, которые будут общедоступными.
По умолчанию публичный диск использует локальный драйвер и хранит свои файлы в storage/app/public.
Чтобы сделать эти файлы доступными из интернета, необходимо создать символическую ссылку с public/storage на storage/app/public.
\\n\\n\\n\\nДля создания символической ссылки можно использовать команду storage:link Artisan:
\\n\\n\\n\\nphp artisan storage:link\\n
\\n\\n\\n\\nПерейдите в route/web.php и создайте 2 дополнительных маршрута. Первый обрабатывает визуализацию формы, а второй – POST-запрос формы.
\\n\\n\\n\\nuse ErlandMuchasaj\\\\LaravelFileUploader\\\\FileUploader; // <= import the package\\nuse Illuminate\\\\Support\\\\Facades\\\\Route;\\nuse Illuminate\\\\Http\\\\Request;\\n\\n\\n// visualize the form\\nRoute::get('/files', function (Request $request) {\\n return view('files');\\n})->name('files');\\n\\n// handle the post request\\nRoute::post('/files', function (Request $request) {\\n\\n $max_size = (int) ini_get('upload_max_filesize') * 1000;\\n\\n $extensions = implode(',', FileUploader::images());\\n\\n $request->validate([\\n 'file' => [\\n 'required',\\n 'file',\\n 'image',\\n 'mimes:' . $extensions,\\n 'max:'.$max_size,\\n ]\\n ]);\\n\\n $file = $request->file('file');\\n\\n $response = FileUploader::store($file);\\n\\n return redirect()\\n ->back()\\n ->with('success','File has been uploaded.')\\n ->with('file', $response);\\n})->name('files.store');\\n
\\n\\n\\n\\nВ этом шаге мы создадим представление, в котором будет размещена форма загрузчика файлов.
Создайте новый файл в resources/views/files.blade.php и поместите в него следующее содержимое:
<!DOCTYPE html>\\n<html lang=\\\"{{ str_replace('_', '-', app()->getLocale()) }}\\\">\\n <head>\\n <meta charset=\\\"utf-8\\\">\\n <meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1\\\">\\n <title>File uploader</title>\\n <link href=\\\"https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css\\\" rel=\\\"stylesheet\\\" integrity=\\\"sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65\\\" crossorigin=\\\"anonymous\\\">\\n </head>\\n <body class=\\\"antialiased\\\">\\n <div class=\\\"container\\\">\\n <div class=\\\"row\\\">\\n <div class=\\\"col-12\\\">\\n @if ($message = Session::get('success'))\\n <div class=\\\"alert alert-success alert-dismissible fade show\\\" role=\\\"alert\\\">\\n <button type=\\\"button\\\" class=\\\"btn-close\\\" data-bs-dismiss=\\\"alert\\\" aria-label=\\\"Close\\\"></button>\\n <strong>{{ $message }}</strong>\\n </div>\\n @endif\\n @if (count($errors) > 0)\\n <div class=\\\"alert alert-danger alert-dismissible fade show\\\" role=\\\"alert\\\">\\n <button type=\\\"button\\\" class=\\\"btn-close\\\" data-bs-dismiss=\\\"alert\\\" aria-label=\\\"Close\\\"></button>\\n <ul class=\\\"mb-0 p-0\\\">\\n @foreach ($errors->all() as $error)\\n <li>{{ $error }}</li>\\n @endforeach\\n </ul>\\n </div>\\n @endif\\n </div>\\n <div class=\\\"col-12 py-5\\\">\\n <div class=\\\"card my-5\\\">\\n <div class=\\\"card-header\\\">\\n <h3>Laravel File Uploader</h3>\\n </div>\\n <div class=\\\"card-body\\\">\\n <form method=\\\"POST\\\" action=\\\"{{ route('files.store') }}\\\" enctype=\\\"multipart/form-data\\\">\\n @method('POST')\\n @csrf\\n <div class=\\\"mb-3\\\">\\n <label for=\\\"formFileLg\\\" class=\\\"form-label\\\">File input example</label>\\n <input name=\\\"file\\\" class=\\\"form-control form-control-lg\\\" id=\\\"formFileLg\\\"\\n type=\\\"file\\\">\\n </div>\\n <div class=\\\"mb-3\\\">\\n <button type=\\\"submit\\\" value=\\\"submit\\\" class=\\\"btn btn-primary\\\">Upload</button>\\n </div>\\n </form>\\n </div>\\n </div>\\n </div>\\n </div>\\n </div>\\n <script src=\\\"https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js\\\" integrity=\\\"sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4\\\" crossorigin=\\\"anonymous\\\"></script>\\n </body>\\n</html>\\n
\\n\\n\\n\\nЭто покажет пользователю форму для загрузки файлов. Форма в этом шаблоне представления указывает на маршрут с именем files.store, который мы создали ранее в файле routes/web.php.
\\n\\n\\n\\nЭто все для данного руководства.
\\n\\n\\n\\nЕсли вам нужна дополнительная информация об используемом пакете, вы можете прочитать ниже:
\\n\\n\\n\\nПростой, но мощный пакет Laravel для загрузки файлов
\\n\\n\\n\\nLaravel File Uploader предлагает простой способ загрузки файлов на различные диски.
Основная цель пакета – убрать повторяющийся и громоздкий код и упростить его до нескольких простых методов.
composer require erlandmuchasaj/laravel-file-uploader
\\n\\n\\n\\nДайте мне знать в разделе комментариев ниже, если вы когда-либо использовали этот пакет в каком-либо из своих проектов.
\\n\\n\\n\\nНе забудьте поставить лайк и прокомментировать.
\\n\\n\\n\\nСледите за мной, чтобы получить больше советов по веб-разработке, новые пакеты и многое другое.
\\n\\n\\n\\nСпасибо за чтение.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Загрузка файлов – одна из распространенных функций, которую использует большинство приложений, и все же это одна из тех вещей, с которыми, как я вижу, многие люди испытывают трудности. Laravel предлагает простой API для работы с локальной файловой системой: Часто пользователю необходимо обработать проверку файла, его размер, размеры, имя, видимость, путь, диск и т.д. Мы хотим […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/zagruzka-fajlov-v-laravel-10/\"],\"title\":[0,\"Загрузка файлов в Laravel 10 - Gorlov.\"],\"breadcrumbTitle\":[0,\"Загрузка файлов в Laravel 10\"],\"description\":[0,\"Загрузка файлов - одна из распространенных функций, которую использует большинство приложений, и все же это одна из тех вещей, с которыми, как я вижу, многие\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Загрузка файлов - одна из распространенных функций, которую использует большинство приложений, и все же это одна из тех вещей, с которыми, как я вижу, многие\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Загрузка файлов в Laravel 10 - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T22:32:05+00:00\"],\"url\":[0,\"http://igorlov.loc/zagruzka-fajlov-v-laravel-10/\"]}]}],\"title\":[0,\"Загрузка файлов в Laravel 10\"],\"uri\":[0,\"/zagruzka-fajlov-v-laravel-10/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"zagruzka-fajlov-v-laravel-10\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Laravel\\\"],\\\"id\\\":[0,\\\"dGVybTozMA==\\\"],\\\"uri\\\":[0,\\\"/tag/laravel/\\\"]}],[0,{\\\"name\\\":[0,\\\"Php\\\"],\\\"id\\\":[0,\\\"dGVybToxMzg=\\\"],\\\"uri\\\":[0,\\\"/tag/php/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjc0MDY=\"],\"node\":[0,{\"date\":[0,\"2023-03-07T22:59:42\"],\"content\":[0,\"\\nНаписано Пиюшем Sinha✏️
\\n\\n\\n\\nКак фронтенд-разработчику, мне часто приходится работать с изображениями. И иногда возникает сложность, когда изображение масштабируется и располагается по-разному в приложении. Например, на сайте электронной коммерции может потребоваться увеличенная версия изображения на странице товара и увеличенная версия того же изображения при отображении списка товаров.
\\n\\n\\n\\nДо выхода Chrome 104 для обрезки/масштабирования изображения я использовал его как background-image в div, а затем настраивал свойства background-position и background-size. Вот пример:
\\n\\n\\n\\n<div id=\\\"cropped\\\"></div>\\n
\\n\\n\\n\\n\\n\\n\\n\\n#cropped {\\n width: 500px;\\n aspect-ratio: 3/2;\\n background-image: url(\\\"https://images.unsplash.com/photo-1611604548018-d56bbd85d681?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2070&q=80\\\");\\n background-size: 1250px;\\n background-position: 66% 67%;\\n background-repeat: no-repeat;\\n}\\n
\\n\\n\\n\\n\\n\\n\\n\\nОн работает нормально, но, скажем так, это решение для обрезки/масштабирования изображений оставляет желать лучшего. Это не совсем то, что можно назвать опрятным. Кроме того, это не будет работать только с <img/>
тегом. Существуют и другие обходные пути, но ни один из них не является таким простым и чистым, как object-view-box.
В выпуске Chrome 104 появился собственный подход к масштабированию или панорамированию содержимого элемента. Свойство CSS object-view-box делает это возможным, задавая окно просмотра над элементом и позволяя нам настроить позиционирование и масштабирование в соответствии с нашими конкретными потребностями.
\\n\\n\\n\\nПроще говоря, подобно тому, как объектив камеры можно настроить для увеличения или уменьшения масштаба, или панорамирования по внешнему виду, свойство object-view-box позволяет нам увеличивать масштаб определенных частей элемента или панорамировать для отображения различных частей элемента.
\\n\\n\\n\\nЧтобы задать поле просмотра над элементом, object-view-box использует функцию inset() для управления четырьмя краями.
\\n\\n\\n\\ninset() – это сокращенный способ указать значения для свойств элемента top, right, bottom и left, в таком порядке. Она имеет тот же синтаксис, что и свойства padding и margin, что позволяет ей принимать от одного до четырех значений:
\\n\\n\\n\\nЭти значения могут быть выражены с помощью любой допустимой единицы длины CSS, например, пикселей (px), эм (em), рем (rem), процентов (%) и др.
\\n\\n\\n\\nДавайте применим это свойство к тому же изображению выше и попробуем добиться того же результата:
\\n\\n\\n\\n<img id=\\\"cropped\\\" src=\\\"https://images.unsplash.com/photo-1611604548018-d56bbd85d681?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2070&q=80\\\" alt=\\\"toys\\\">\\n
\\n\\n\\n\\n#cropped {\\n width: 500px;\\n object-view-box: inset(40% 20% 20% 40%);\\n}\\n
\\n\\n\\n\\nЕсли обрезанная версия изображения представляет собой квадрат, изображение будет выглядеть искаженным, т.е. растянутым или сжатым:
\\n\\n\\n\\n#cropped {\\n aspect-ratio: 1;\\n width: 500px;\\n object-view-box: inset(40% 20% 20% 40%);\\n}\\n
\\n\\n\\n\\nЗдесь мы можем воспользоваться помощью свойства object-fit, которое определяет, как элемент должен быть изменен по размеру, чтобы соответствовать своему контейнеру. Свойство может иметь одно из следующих значений: fill, contain, cover, none или scale-down.
\\n\\n\\n\\nДля нашего сценария мы можем использовать cover, которое изменяет размер изображения в соответствии с соотношением сторон контейнера, а если соотношение сторон изображения не совпадает с соотношением сторон контейнера, то оно будет обрезано:
\\n\\n\\n\\n#cropped-fit-cover {\\n aspect-ratio: 1;\\n width: 500px;\\n object-fit: cover;\\n object-view-box: inset(40% 20% 20% 40%);\\n}\\n
\\n\\n\\n\\nРазве это не удобный способ обрезать/масштабировать изображение? Для этого требуется только одно свойство, и его легко визуализировать. Никаких дополнительных свойств или элементов не требуется, в отличие от обходных путей.
\\n\\n\\n\\nИспользование свойства object-view-box – это оригинальное решение; браузер делает тяжелую работу, а разработчики получают чистое решение.
\\n\\n\\n\\nСреди разработчиков существуют популярные обходные пути, например, использование элемента HTML – например, <div/>
— и применения свойств CSS для получения обрезанного изображения. Но это все равно лишь обходной путь, нетрадиционное решение для преодоления ограничений браузера.
В этом обновлении браузер поработал над этим ограничением и предлагает встроенное решение.
\\n\\n\\n\\nСуществует опасение, что для того, чтобы это работало, необходимо знать точные размеры исходного и нового контейнера. Но разве это не является необходимым условием для обрезки изображения? Чтобы определить, сколько нужно обрезать, нам всегда нужна эта информация.
\\n\\n\\n\\nИтак, как это будет работать при изменении размеров контейнера (изменение области просмотра)?
\\n\\n\\n\\nПоскольку объект-видовое окно использует функцию inset() для рисования видового окна над изображением, обрезка всегда происходит по внутреннему размеру (исходной ширине и высоте) изображения. Чтобы сделать его отзывчивым, мы можем использовать это свойство вместе с медиа-запросами и обрезать соответствующим образом.
\\n\\n\\n\\nВозможность обрезать/масштабировать изображение может пригодиться во многих случаях:
\\n\\n\\n\\nКогда изображение необходимо масштабировать и позиционировать по-разному во всем приложении.
Интерактивная функция, когда пользователи могут увеличивать и панорамировать изображение, обычно встречается на сайтах электронной коммерции.
В небольших экранах просмотра изображения часто обрезаются. С помощью этого свойства и медиазапросов мы можем контролировать, какая часть изображения остается в поле зрения.
В прошлом существовали обходные пути для обрезки и масштабирования изображений, но я приветствую это оригинальное и удобное решение. Также, пожалуйста, имейте в виду, что это экспериментальный выпуск, и поэтому он может не поддерживаться всеми браузерами. Посетите сайт caniuse.com для получения актуальных таблиц поддержки браузеров.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Написано Пиюшем Sinha✏️ Как фронтенд-разработчику, мне часто приходится работать с изображениями. И иногда возникает сложность, когда изображение масштабируется и располагается по-разному в приложении. Например, на сайте электронной коммерции может потребоваться увеличенная версия изображения на странице товара и увеличенная версия того же изображения при отображении списка товаров. До выхода Chrome 104 для обрезки/масштабирования изображения я использовал […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/rukovodstvo-po-css-object-view-box/\"],\"title\":[0,\"Руководство по CSS Object-view-box - Gorlov.\"],\"breadcrumbTitle\":[0,\"Руководство по CSS object-view-box\"],\"description\":[0,\"Написано Пиюшем Sinha✏️\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Написано Пиюшем Sinha✏️\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Руководство по CSS Object-view-box - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T22:32:13+00:00\"],\"url\":[0,\"http://igorlov.loc/rukovodstvo-po-css-object-view-box/\"]}]}],\"title\":[0,\"Руководство по CSS object-view-box\"],\"uri\":[0,\"/rukovodstvo-po-css-object-view-box/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"rukovodstvo-po-css-object-view-box\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Css\\\"],\\\"id\\\":[0,\\\"dGVybTo1Nw==\\\"],\\\"uri\\\":[0,\\\"/tag/css/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjc0MDk=\"],\"node\":[0,{\"date\":[0,\"2023-03-07T22:41:41\"],\"content\":[0,\"\\n
Matplotlib – это популярная библиотека визуализации данных в Python, широко используемая для создания статических, интерактивных и анимированных визуализаций в Python. Мы можем представлять наши данные различными интерактивными способами, такими как графики, гистограммы, круговые диаграммы и т.д.
Он предоставляет широкий спектр возможностей настройки, чтобы сделать ваши графики более информативными и визуально привлекательными. Вот некоторые из опций настройки, доступных в Matplotlib:
Маркеры в Matplotlib используются для представления точек данных на графике с помощью символа, такого как круг, квадрат или треугольник. Мы можем выполнять различные функции и настройки, используя ключевое слово *marker*, например:
Изменение размера маркера
изменение цвета маркера
Изменение цвета и ширины края маркера
import matplotlib.pyplot as plt\\nimport pandas as pd\\n\\nypoints = [10,20,34,40,15]\\n\\nplt.plot(ypoints, marker=\\\"o\\\", markeredgecolor=\\\"black\\\", markersize=7, markerfacecolor=\\\"red\\\")\\nplt.show()\\n
\\n\\n\\n\\nВывод
\\n\\n\\n\\nМы можем представить наши данные в различных интерактивных формах, таких как:
Круговые диаграммы, Гистограммы, Штриховые диаграммы и т.д., используя вид ключевого слова.
Примечание
\\n\\n\\n\\nВид графика записывается в виде строки.
\\n\\n\\n\\nСинтаксис
\\n\\n\\n\\nimport matplotlib.pyplot as plt\\nimport pandas as pd\\n\\ndata = {'x': [1, 2, 3, 4, 5], 'y': [2, 4, 6, 8, 10]}\\ndf = pd.DataFrame(data)\\ngraph = df.plot(kind=\\\"bar\\\")\\nplt.show(graph)\\n
\\n\\n\\n\\nВывод:
\\n\\n\\n\\n
Метки и заголовки являются наиболее важными компонентами графика Matplotlib, поскольку они предоставляют информацию о визуализируемых данных. Они делают график более понятным. Мы можем добавить метки как по оси x, так и по оси y, в то время как заголовок дает графику название, которое становится более информативным.
Синтаксис
import matplotlib.pyplot as plt\\nimport pandas as pd\\n\\ndata = {'x': [1, 2, 3, 4, 5], 'y': [2, 4, 6, 8, 10]}\\ndf = pd.DataFrame(data)\\ngraph = df.plot(kind=\\\"bar\\\")\\nplt.title(\\\"Monthly Sales\\\")\\nplt.xlabel(\\\"Years\\\")\\nplt.ylabel(\\\"Sales\\\")\\nplt.show(graph)\\n
\\n\\n\\n\\nВывод
\\n\\n\\n\\nЛегенда используется для идентификации и различения различных графиков на рисунке. Мы можем изменить цвет нескольких столбцов, что делает наш график более интерактивным и легким для понимания.
\\n\\n\\n\\nСинтаксис
\\n\\n\\n\\nimport matplotlib.pyplot as plt\\nimport pandas as pd\\n\\ndata = {'x': [1, 2, 3, 4, 9], 'y': [2, 5, 6, 8, 10]}\\ndf = pd.DataFrame(data)\\ngraph = df.plot(kind=\\\"bar\\\")\\nplt.legend([\\\"blue\\\",\\\"orange\\\"])\\nplt.show(graph)\\n
\\n\\n\\n\\nВывод
\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Что такое Matplotlib Matplotlib – это популярная библиотека визуализации данных в Python, широко используемая для создания статических, интерактивных и анимированных визуализаций в Python. Мы можем представлять наши данные различными интерактивными способами, такими как графики, гистограммы, круговые диаграммы и т.д. Почему Matplotlib Он предоставляет широкий спектр возможностей настройки, чтобы сделать ваши графики более информативными и визуально […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/kastomizacziya-matplotlib-v-python/\"],\"title\":[0,\"Кастомизация Matplotlib в Python - Gorlov.\"],\"breadcrumbTitle\":[0,\"Кастомизация Matplotlib в Python\"],\"description\":[0,\"Matplotlib - это популярная библиотека визуализации данных в Python, широко используемая для создания статических, интерактивных и анимированных визуализаций\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Matplotlib - это популярная библиотека визуализации данных в Python, широко используемая для создания статических, интерактивных и анимированных визуализаций\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Кастомизация Matplotlib в Python - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T22:32:41+00:00\"],\"url\":[0,\"http://igorlov.loc/kastomizacziya-matplotlib-v-python/\"]}]}],\"title\":[0,\"Кастомизация Matplotlib в Python\"],\"uri\":[0,\"/kastomizacziya-matplotlib-v-python/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"kastomizacziya-matplotlib-v-python\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Python\\\"],\\\"id\\\":[0,\\\"dGVybTo2NA==\\\"],\\\"uri\\\":[0,\\\"/tag/python/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjc0MTI=\"],\"node\":[0,{\"date\":[0,\"2023-03-07T22:29:52\"],\"content\":[0,\"\\nУсловные операторы являются неотъемлемой частью программирования на Python. Они позволяют принимать решения на основе значений переменных или результатов сравнений.
\\n\\n\\n\\nВ этой статье мы рассмотрим, как использовать операторы if, else и elif в Python, а также примеры их практического применения.
\\n\\n\\n\\nОператор if позволяет выполнить блок кода, если определенное условие истинно. Вот основной синтаксис:
\\n\\n\\n\\nif condition:\\n # code to execute if condition is true\\n
\\n\\n\\n\\nУсловием может быть любое выражение, которое оценивается в булево значение (True или False). Если условие равно True, будет выполнен блок кода, отступ которого находится ниже оператора if. Если условие равно False, блок кода будет пропущен.
\\n\\n\\n\\nВот пример использования оператора if для проверки положительности числа:
\\n\\n\\n\\nnum = 5\\n\\nif num > 0:\\n print(\\\"The number is positive.\\\")\\n
\\n\\n\\n\\nВывод:
\\n\\n\\n\\nThe number is positive.\\n
\\n\\n\\n\\nВ этом примере мы используем оператор > для сравнения значения num с 0. Если num больше 0, будет выполнен блок кода, отступленный ниже оператора if, и выведено сообщение “Число положительное.”.
\\n\\n\\n\\nОператор else позволяет выполнить другой блок кода, если условие if равно False. Вот основной синтаксис:
\\n\\n\\n\\nif condition:\\n # code to execute if condition is true\\nelse:\\n # code to execute if condition is false\\n
\\n\\n\\n\\nЕсли условие равно True, будет выполнен блок кода, отступ которого находится под оператором if, а блок кода, отступ которого находится под оператором else, будет пропущен.
\\n\\n\\n\\nЕсли условие равно False, будет выполнен блок кода, отступ которого находится под оператором else, а блок кода, отступ которого находится под оператором if, будет пропущен.
\\n\\n\\n\\nВот пример использования оператора if-else для проверки того, является ли число положительным или отрицательным:
\\n\\n\\n\\nnum = -5\\n\\nif num > 0:\\n print(\\\"The number is positive.\\\")\\nelse:\\n print(\\\"The number is negative.\\\")\\n
\\n\\n\\n\\nВывод:
\\n\\n\\n\\nThe number is negative.\\n
\\n\\n\\n\\nВ этом примере мы используем оператор if-else, чтобы проверить, больше ли num 0. Если да, то выводится сообщение “Число положительное.”. Если нет (то есть num отрицательно или равно нулю), выводится сообщение “Число отрицательное.”.
\\n\\n\\n\\nОператор elif позволяет последовательно проверять несколько условий и выполнять различные блоки кода в зависимости от того, какое условие истинно. Вот основной синтаксис:
\\n\\n\\n\\nif condition1:\\n # code to execute if condition1 is true\\nelif condition2:\\n # code to execute if condition1 is false and condition2 is true\\nelif condition3:\\n # code to execute if condition1 and condition2 are false, and condition3 is true\\nelse:\\n # code to execute if all conditions are false\\n
\\n\\n\\n\\nОператор elif – это сокращение от “else if”, и его можно использовать несколько раз для проверки дополнительных условий.
\\n\\n\\n\\nВот пример использования оператора if-elif-else для проверки того, является ли число положительным, отрицательным или нулевым:
\\n\\n\\n\\nnum = 0\\n\\nif num > 0:\\n print(\\\"The number is positive.\\\")\\nelif num < \\n
\\n\\n\\n\\nnum = 4\\n\\nif num % 2 == 0:\\n print(\\\"The number is even.\\\")\\nelse:\\n print(\\\"The number is odd.\\\")\\n
\\n\\n\\n\\nВывод:
\\n\\n\\n\\nThe number is even.\\n
\\n\\n\\n\\nВ этом примере мы используем оператор модуля (%), чтобы проверить, делится ли num на 2.
\\n\\n\\n\\nЕсли остаток от деления числа num на 2 равен 0, условие num % 2 == 0 равно True, и будет выполнен блок кода, отступленный ниже оператора if. Будет выведено сообщение “Число четное”.
\\n\\n\\n\\nЕсли остаток не равен 0, условие равно False, и будет выполнен блок кода, отступленный под оператором else, который выведет сообщение “Число нечетное”.
\\n\\n\\n\\nscore = 85\\n\\nif score >= 90:\\n grade = \\\"A\\\"\\nelif score >= 80:\\n grade = \\\"B\\\"\\nelif score >= 70:\\n grade = \\\"C\\\"\\nelif score >= 60:\\n grade = \\\"D\\\"\\nelse:\\n grade = \\\"F\\\"\\n\\nprint(\\\"Your grade is:\\\", grade)\\n
\\n\\n\\n\\nВывод:
\\n\\n\\n\\nYour grade is: B\\n
\\n\\n\\n\\nВ этом примере мы используем оператор if-elif-else для присвоения буквенной оценки на основе числового балла.
\\n\\n\\n\\nОператор if проверяет, больше или равен ли балл 90. Если да, то оценка устанавливается в “A”. Если нет, то первый оператор elif проверяет, больше или равен ли балл 80. Если да, то выставляется оценка “B”. Если нет, то второй оператор elif проверяет, больше или равен ли балл 70, и так далее. Если ни одно из условий не выполняется, оператор else присваивает оценку “F”.
\\n\\n\\n\\nyear = 2000\\n\\nif year % 4 == 0:\\n if year % 100 == 0:\\n if year % 400 == 0:\\n print(year, \\\"is a leap year.\\\")\\n else:\\n print(year, \\\"is not a leap year.\\\")\\n else:\\n print(year, \\\"is a leap year.\\\")\\nelse:\\n print(year, \\\"is not a leap year.\\\")\\n
\\n\\n\\n\\nВывод:
\\n\\n\\n\\n2000 is a leap year.\\n
\\n\\n\\n\\nВ этом примере мы используем вложенные операторы if, чтобы проверить, является ли год високосным. Год является високосным, если он делится на 4, за исключением годов, которые делятся на 100, но не делятся на 400.
\\n\\n\\n\\nВнешний оператор if проверяет, делится ли год на 4. Если да, то внутренний оператор if проверяет, делится ли он также на 100. Если да, то самый внутренний оператор if проверяет, делится ли он на 400. Если да, то будет выполнен блок кода, отступленный ниже этого оператора, который выведет сообщение “год високосный”.
\\n\\n\\n\\nЕсли нет, то будет выполнен блок кода, отступленный под оператором else внутри внутреннего оператора if, который выведет сообщение “год не високосный”.
\\n\\n\\n\\nЕсли год не делится на 4, будет выполнен блок кода, отступленный под оператором else внешнего оператора if, который выведет сообщение “не високосный год”.
\\n\\n\\n\\nstring = \\\"hello, world\\\"\\nchar = \\\"w\\\"\\n\\nif char in string:\\n print(\\\"The string contains the character\\\", char)\\nelse:\\n print(\\\"The string does not contain the character\\\", char)\\n
\\n\\n\\n\\nРезультат:
\\n\\n\\n\\nThe string contains the character w\\n
\\n\\n\\n\\nВ этом примере мы используем оператор in, чтобы проверить, присутствует ли символ char в строке string. Если да, то условие char in string равно True, и будет выполнен блок кода, отступленный ниже оператора if, который выведет сообщение “Строка содержит символ”, а затем сам символ.
\\n\\n\\n\\nЕсли char не присутствует в строке, условие равно False, и блок кода, отступленный под оператором else, будет выполнен, выводя сообщение “Строка не содержит символ”, за которым следует сам символ.
\\n\\n\\n\\nУсловные операторы (if, else и elif) являются фундаментальными конструкциями программирования, позволяющими управлять ходом выполнения программы на основе заданных вами условий. Они позволяют принимать решения в вашей программе и выполнять различный код на основе этих решений.
\\n\\n\\n\\nВ этой статье мы рассмотрели несколько примеров использования этих операторов в Python, включая проверку четности или нечетности числа, присвоение буквенной оценки на основе числового балла, проверку того, является ли год високосным, и проверку того, содержит ли строка определенный символ.
\\n\\n\\n\\nОсвоив эти утверждения, вы сможете создавать более мощные и универсальные программы, способные решать широкий круг задач и сценариев.
\\n\\n\\n\\nВажно помнить, что правильный отступ имеет решающее значение при использовании условных операторов в Python, поскольку он определяет, какой блок кода будет выполняться в зависимости от условия.
\\n\\n\\n\\nС практикой вы приобретете навык использования этих операторов для создания более сложных и эффективных программ на Python.
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Условные операторы являются неотъемлемой частью программирования на Python. Они позволяют принимать решения на основе значений переменных или результатов сравнений. В этой статье мы рассмотрим, как использовать операторы if, else и elif в Python, а также примеры их практического применения. Как использовать оператор if в Python Оператор if позволяет выполнить блок кода, если определенное условие истинно. […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/kak-ispolzovat-uslovnye-vyrazheniya-v-python-primery-if-else-i-elif/\"],\"title\":[0,\"Как использовать условные выражения в Python - примеры If, Else и Elif - Gorlov.\"],\"breadcrumbTitle\":[0,\"Как использовать условные выражения в Python – примеры if, else и elif\"],\"description\":[0,\"Условные операторы являются неотъемлемой частью программирования на Python. Они позволяют принимать решения на основе значений переменных или результатов\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Условные операторы являются неотъемлемой частью программирования на Python. Они позволяют принимать решения на основе значений переменных или результатов\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Как использовать условные выражения в Python - примеры If, Else и Elif - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T22:32:50+00:00\"],\"url\":[0,\"http://igorlov.loc/kak-ispolzovat-uslovnye-vyrazheniya-v-python-primery-if-else-i-elif/\"]}]}],\"title\":[0,\"Как использовать условные выражения в Python – примеры if, else и elif\"],\"uri\":[0,\"/kak-ispolzovat-uslovnye-vyrazheniya-v-python-primery-if-else-i-elif/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"kak-ispolzovat-uslovnye-vyrazheniya-v-python-primery-if-else-i-elif\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Python\\\"],\\\"id\\\":[0,\\\"dGVybTo2NA==\\\"],\\\"uri\\\":[0,\\\"/tag/python/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjc0MTY=\"],\"node\":[0,{\"date\":[0,\"2023-03-07T22:20:27\"],\"content\":[0,\"\\nВ регулярных выражениях “S” – это метасимвол, обозначающий пробел.
\\n\\n\\n\\nМетасимвол строчной буквы “s” обозначает пробел, а заглавная буква “S” обозначает отсутствие пробела. Именно так работает шаблон для большинства метасимволов.
\\n\\n\\n\\nНапример, маленькая буква “d” является метасимволом для цифры, а заглавная буква “D” – для нецифры.
\\n\\n\\n\\nВ этой статье мы рассмотрим эти две вариации символа “S” в RegEx, их назначение и использование в движках RegEx и программировании.
\\n\\n\\n\\nЧтобы метасимволы работали, их необходимо экранировать.
\\n\\n\\n\\nПричина в том, что если вы вводите метасимвол “S”, “s” или “D” только в движке RegEx или при написании RegEx на языке программирования, он будет интерпретирован как эта буква.
\\n\\n\\n\\nПоэтому, чтобы заставить метасимволы работать в RegEx, их нужно экранировать обратным слешем (\\\\).
\\n\\n\\n\\nВ приведенном ниже примере я смог сопоставить символы пробела, потому что экранировал букву s:
\\n\\n\\n\\nВ приведенном ниже примере я смог сопоставить числа, потому что экранировал d:
Как я уже упоминал ранее, мета символ “S” имеет две формы — строчная буква “s” и заглавная буква “S”.
\\n\\n\\n\\nКогда он находится в строчной букве, он соответствует всем символам пробела, таким как пробел, табуляция и возврат каретки.
\\n\\n\\n\\nА когда он находится в заглавной букве, он соответствует всем символам, не являющимся пробелами, таким как цифры, символы и буквы.
\\n\\n\\n\\nКаждый из пробельных символов также имеет свои мета символы:
\\n\\n\\n\\nВы можете сопоставить все символы, не являющиеся пробелами, со скрытой заглавной буквой “S”:
\\n\\n\\n\\nВы можете сопоставить все пробельные символы со строчной буквой “s”:
Метасимволы \\\\s и \\\\S прекрасно работают в любом языке, который поддерживает RegEx.
\\n\\n\\n\\nВот пример на JavaScript:
\\n\\n\\n\\nlet regex1 = /\\\\S/g;\\nlet regex2 = /\\\\s/g;\\n\\nlet str1 = 'Allofthesearenonsspacecharacters';\\nlet str2 = `spacebar \\ntab \\nnewLine\\n\\n`;\\n\\nconsole.log(regex1.test(str1)); //true\\nconsole.log(regex2.test(str2)); // true\\n
\\n\\n\\n\\nВ этой статье вы узнали, что означает и делает символ “S” в RegEx.
\\n\\n\\n\\nМы рассмотрели, как он работает (для его работы требуется экранирование), его две формы, а также то, как он работает в механизмах RegEx и JavaScript.
\\n\\n\\n\\nСпасибо за прочтение. Счастливого кодирования!
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
В регулярных выражениях “S” – это метасимвол, обозначающий пробел. Метасимвол строчной буквы “s” обозначает пробел, а заглавная буква “S” обозначает отсутствие пробела. Именно так работает шаблон для большинства метасимволов. Например, маленькая буква “d” является метасимволом для цифры, а заглавная буква “D” – для нецифры. В этой статье мы рассмотрим эти две вариации символа “S” в […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Как закодить\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/kak-zakodit/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/chto-oznachaet-s-v-regex-probel-i-probelnye-metasimvoly/\"],\"title\":[0,\"Что означает S в Regex? Пробел и пробельные метасимволы - Gorlov.\"],\"breadcrumbTitle\":[0,\"Что означает \\\\S в Regex? Пробел и пробельные метасимволы\"],\"description\":[0,\"В регулярных выражениях "S" - это метасимвол, обозначающий пробел.\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"В регулярных выражениях "S" - это метасимвол, обозначающий пробел.\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Что означает S в Regex? Пробел и пробельные метасимволы - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T22:32:57+00:00\"],\"url\":[0,\"http://igorlov.loc/chto-oznachaet-s-v-regex-probel-i-probelnye-metasimvoly/\"]}]}],\"title\":[0,\"Что означает \\\\S в Regex? Пробел и пробельные метасимволы\"],\"uri\":[0,\"/chto-oznachaet-s-v-regex-probel-i-probelnye-metasimvoly/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"chto-oznachaet-s-v-regex-probel-i-probelnye-metasimvoly\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Regex\\\"],\\\"id\\\":[0,\\\"dGVybToxNjg=\\\"],\\\"uri\\\":[0,\\\"/tag/regex/\\\"]}],[0,{\\\"name\\\":[0,\\\"Как закодить\\\"],\\\"id\\\":[0,\\\"dGVybToyNg==\\\"],\\\"uri\\\":[0,\\\"/category/kak-zakodit/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjc0MjQ=\"],\"node\":[0,{\"date\":[0,\"2023-03-07T22:08:45\"],\"content\":[0,\"\\nВ этом посте мы рассмотрим несколько реальных примеров веб-скрейпинга с использованием Python и популярных библиотек BeautifulSoup и Scrapy.
\\n\\n\\n\\nДопустим, вы хотите построить модель машинного обучения для анализа настроений в новостных статьях. Для этого вам понадобится большой набор данных новостных статей с метками, указывающими на настроение каждой статьи. Вместо того чтобы вручную собирать и маркировать статьи, можно использовать веб-скрейпинг для автоматизации этого процесса.
\\n\\n\\n\\nОдним из популярных источников новостных статей является сайт New York Times. Вот некоторый код на языке Python, использующий BeautifulSoup для соскабливания заголовков и текста статей с сайта New York Times:
\\n\\n\\n\\nimport requests\\nfrom bs4 import BeautifulSoup\\n\\nurl=\\\"https://www.nytimes.com/\\\"\\nresponse = requests.get(url)\\nsoup = BeautifulSoup(response.text, 'html.parser')\\n\\narticles = []\\nfor article in soup.find_all('article'):\\nheadline = article.find('h2').text.strip()\\nbody = article.find('p').text.strip()\\narticles.append({'headline': headline, 'body': body})\\n\\n
\\n\\n\\n\\nВ этом примере мы сначала используем библиотеку requests для получения HTML-содержимого главной страницы New York Times. Затем мы создаем объект BeautifulSoup и используем его методы для извлечения заголовков и текста из каждой статьи на странице. Мы храним данные в списке словарей, каждый из которых представляет статью, ее заголовок и основной текст.
\\n\\n\\n\\nЕще один распространенный случай использования веб-скреппинга – сбор данных о ценах на товары с сайтов электронной коммерции. Это может быть полезно для исследования рынка, анализа конкурентов и многого другого.
\\n\\n\\n\\nДопустим, вы хотите сравнить цены на определенный товар на нескольких сайтах электронной коммерции. Вот некоторый код на языке Python с использованием Scrapy для сопоставления цен на товар с Amazon, Best Buy и Walmart:
\\n\\n\\n\\nimport scrapy\\n\\nclass ProductSpider(scrapy.Spider):\\n name=\\\"product_spider\\\"\\n start_urls = [\\n 'https://www.amazon.com/dp/B08J62XKJT', \\n 'https://www.bestbuy.com/site/sony-playstation-5- \\n console/6426149.p?skuId=6426149', \\n 'https://www.walmart.com/ip/Sony-PlayStation-5/363472942'\\n ]\\n def parse(self, response):\\n title = response.css('h1.a-text-normal::text').get()\\n price = response.css('span.a-offscreen::text').get()\\n yield {'title': title, 'price': price}\\n
\\n\\n\\n\\nВеб-скрейпинг можно также использовать для сбора данных о погоде с таких сайтов, как Weather Underground или Национальная метеорологическая служба. Эти данные можно использовать для моделирования климата, прогнозирования погоды и многого другого.
\\n\\n\\n\\nДопустим, вы хотите собрать данные о температуре в городе Матмата с сайта Weather Underground. Вот некоторый код на языке Python с использованием BeautifulSoup для сбора данных о температуре:
\\n\\n\\n\\nimport requests\\nfrom bs4 import BeautifulSoup\\n\\nurl=\\\"https://www.wunderground.com/weather/tn/matmata\\\"\\nresponse = requests.get(url)\\nsoup = BeautifulSoup(response.text, 'html.parser')\\n\\ntemperature = soup.find('span', {'class': 'wu-value wu-value-to'}).text.strip()\\nprint(f\\\"The current temperature in Matmata is {temperature} degrees Fahrenheit.\\\")\\n
\\n\\n\\n\\nВ этом примере мы используем запросы и BeautifulSoup для получения текущей температуры для города Матмата, Тунис, с сайта Weather Underground. Сначала мы отправляем GET-запрос на сайт и создаем объект BeautifulSoup. Затем мы используем CSS-селектор для извлечения данных о температуре со страницы и выводим их на консоль.
\\n\\n\\n\\nЭто лишь несколько примеров из множества реальных применений веб-скрейпинга с помощью Python. Независимо от того, собираете ли вы данные для научных или деловых целей, веб-скрейпинг поможет автоматизировать процесс и сэкономить драгоценное время и ресурсы.
\\n\\n\\n\\nДо встречи в следующем посте!
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
В этом посте мы рассмотрим несколько реальных примеров веб-скрейпинга с использованием Python и популярных библиотек BeautifulSoup и Scrapy. Пример 1: Скраппинг новостных статей Допустим, вы хотите построить модель машинного обучения для анализа настроений в новостных статьях. Для этого вам понадобится большой набор данных новостных статей с метками, указывающими на настроение каждой статьи. Вместо того чтобы […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/parsing-s-python-primery/\"],\"title\":[0,\"Парсинг с Python: примеры - Gorlov.\"],\"breadcrumbTitle\":[0,\"Парсинг с python: примеры\"],\"description\":[0,\"В этом посте мы рассмотрим несколько реальных примеров веб-скрейпинга с использованием Python и популярных библиотек BeautifulSoup и Scrapy.\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"В этом посте мы рассмотрим несколько реальных примеров веб-скрейпинга с использованием Python и популярных библиотек BeautifulSoup и Scrapy.\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"Парсинг с Python: примеры - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T22:15:03+00:00\"],\"url\":[0,\"http://igorlov.loc/parsing-s-python-primery/\"]}]}],\"title\":[0,\"Парсинг с python: примеры\"],\"uri\":[0,\"/parsing-s-python-primery/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"parsing-s-python-primery\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjY5MTg=\"],\"node\":[0,{\"date\":[0,\"2023-03-04T17:55:40\"],\"content\":[0,\"\\nПривет! 👋
\\n\\n\\n\\nСегодня мы рассмотрим 10 пользовательских функций JavaScript, которые могут пригодиться в большинстве ваших проектов.
\\n\\n\\n\\nДа, инструмент, который мы все любим и используем для печати, отладки и т.д. Так почему бы не сократить его, чтобы уменьшить набор текста и сэкономить немного времени?
\\n\\n\\n\\nconst { log } = console;\\n\\nlog(\\\"Hello world!\\\");\\n// Expected output: Hello world!\\n\\n// SAME AS //\\n\\nconsole.log(\\\"Hello world!\\\");\\n// Expected output: Hello world!\\n
\\n\\n\\n\\nОбъяснение: мы используем назначение деструктуризации, чтобы иметь возможность извлечь метод log из консоли.
\\n\\n\\n\\nquerySelector()
При работе с JavaScript вы могли слышать термин DOM Manipulation и использовать getElementById(), querySelector() и другие методы для доступа к элементам DOM. Итак, давайте упростим работу с ними.
\\n\\n\\n\\nconst select = (selector, scope = document) => {\\n return scope.querySelector(selector);\\n};\\n\\nconst title = select(\\\"h1\\\");\\nconst className = select(\\\".class\\\");\\nconst message = select(\\\"#message\\\", formElem);\\n\\n// SAME AS //\\n\\nconst title = document.querySelector(\\\"h1\\\");\\nconst className = document.querySelector(\\\".class\\\");\\nconst message = formElem.querySelector(\\\"#message\\\");\\n
\\n\\n\\n\\nОбъяснение: Мы передаем 2 параметра в функции select():
\\n\\n\\n\\n1-й: DOM-элемент, который вы хотите выбрать
2-й: Область, из которой вы получаете доступ к этому элементу (по умолчанию = document);
Обработка событий click, mousemove и других в основном реализуется с помощью метода addEventListener().
\\n\\n\\n\\nconst listen = (target, event, callback, ...options) => {\\n return target.addEventListener(event, callback, ...options);\\n};\\n\\nlisten(buttonElem, \\\"click\\\", () => console.log(\\\"Clicked!\\\"));\\n\\nlisten(document, \\\"mouseover\\\", () => console.log(\\\"Mouse over!\\\"));\\n\\nlisten(formElem, \\\"submit\\\", () => {\\n console.log(\\\"Form submitted!\\\");\\n }, { once: true }\\n);\\n
\\n\\n\\n\\nОбъяснение: Мы передаем 4 параметра в функции listen():
\\n\\n\\n\\n1-й: Элемент, на который вы хотите нацелиться (например, ‘window’, ‘document’ или конкретный элемент DOM).
2-й: Тип события (например, ‘click’, ‘submit’, ‘DOMContentLoaded’ и т.д.).
3-й: Функция обратного вызова
4-й: Оставшиеся необязательные опции (например, ‘capture’, ‘once’ и т.д.). Кроме того, мы используем синтаксис распространения, чтобы при необходимости можно было использовать другие опции. В противном случае их можно опустить, как и в методе addEventListener.
Вы, вероятно, знаете о функции Math.random(), которая генерирует случайные числа от 0 до 1. Вы также можете знать о других хаках, таких как Math.random() * 10, которая теперь должна генерировать случайные числа от 0 до 10. Однако проблема в том, что, несмотря на знание предела, у нас нет особого контроля над минимальным значением.
\\n\\n\\n\\nconst random = (min, max) => {\\n return Math.floor(Math.random() * (max - min + 1)) + min;\\n};\\n\\nrandom(5, 10);\\n// 7\\n
\\n\\n\\n\\nОбъяснение: Вот лучшее объяснение от MDN Docs
\\n\\n\\n\\nИногда мы сталкиваемся с необходимостью выполнить определенную функцию несколько раз.
\\n\\n\\n\\nКонечно, мы можем использовать setInterval() для запуска через каждый интервал времени, например, так:
\\n\\n\\n\\nsetInterval(() => {\\n randomFunction();\\n}, 5000); // runs every 5 seconds\\n
\\n\\n\\n\\nПроблема в том, что мы не можем указать, сколько раз мы хотим его запустить. Итак, давайте это исправим!
\\n\\n\\n\\nconst times = (func, n) => {\\n Array.from(Array(n)).forEach(() => {\\n func();\\n });\\n};\\n\\ntimes(() => {\\n randomFunction();\\n}, 3); // runs 3 times\\n
\\n\\n\\n\\nПояснение:
\\n\\n\\n\\nArray(n) – создает новый массив длиной n.
\\n\\n\\n\\nArray(5); // => [,,]\\n
\\n\\n\\n\\nArray.from() - создает неглубокую копию из массива Array(n). Это помогает нам сделать массив пригодным для использования, заполнив его 'undefined'. Вы также можете использовать метод Array.prototype.fill() для достижения того же результата.
Array.from(Array(3)); // => [undefined,undefined,undefined]\\n
\\n\\n\\n\\nПримечание: Исследуя эту служебную функцию, я понял, что некоторые программисты предпочитают сначала помещать параметр n, а затем функцию times(n, func). Но для меня это выглядело довольно странно, поэтому я решил поменять их местами, тем самым сделав синтаксис более похожим на синтаксис функции setInterval():
\\n\\n\\n\\nsetInterval(func, delay);\\n\\ntimes(func, n);\\n
\\n\\n\\n\\nКроме того, вы называете его setTimes() вместо times() для согласования с методами setInterval() и setTimeout() в зависимости от ваших предпочтений.
\\n\\n\\n\\nslugify()
Вы когда-нибудь сталкивались с необходимостью преобразования заголовков статей вашего блога в “URL-подобный” формат?
\\n\\n\\n\\nJS Utility Functions => js-utility-functions\\n
\\n\\n\\n\\nВот небольшая полезная функция, которая это делает:
\\n\\n\\n\\nconst slugify = (string, separator = \\\"-\\\") => {\\n return string\\n .toString() // Cast to string (optional)\\n .toLowerCase() // Convert the string to lowercase letters\\n .trim() // Remove whitespace from both sides of a string (optional)\\n .replace(/\\\\s+/g, separator) // Replace spaces with -\\n .replace(/[^\\\\w\\\\-]+/g, \\\"\\\") // Remove all non-word chars\\n .replace(/\\\\_/g, separator) // Replace _ with -\\n .replace(/\\\\-\\\\-+/g, separator) // Replace multiple - with single -\\n .replace(/\\\\-$/g, \\\"\\\"); // Remove trailing -\\n};\\n\\nslugify(\\\"Hello, World!\\\");\\n// Expected output: \\\"hello-world\\\"\\n\\nslugify(\\\"Hello, Universe!\\\", \\\"_\\\");\\n// Expected output: \\\"hello_universe\\\"\\n
\\n\\n\\n\\nПояснение: Вот обсуждение сообщества GitHub
\\n\\n\\n\\nvalidateEmail()
Когда вы работаете над небольшими проектами и пробуете валидацию электронной почты для вашей формы, вы можете использовать этот супер простой метод для достижения вашей цели. Кроме того, он может быть очень удобен для небольших тестов.
\\n\\n\\n\\nconst validateEmail = (email) => {\\n const regex = /^\\\\S+@\\\\S+\\\\.\\\\S+$/;\\n return regex.test(email);\\n};\\n\\nvalidateEmail(\\\"youremail@org.com\\\"); // true\\nvalidateEmail(\\\"youremail@com\\\"); // false\\nvalidateEmail(\\\"youremail.org@com\\\"); // false\\n
\\n\\n\\n\\nПояснение: Здесь вы можете поиграть с regex.
\\n\\n\\n\\nRegExp.test() проверяет, совпадает ли предоставленное выражение regex со строкой.
\\n\\n\\n\\nПримечание: Для больших проектов я бы рекомендовал использовать такие библиотеки, как validator.js, чтобы они выполняли тяжелую работу за вас.
\\n\\n\\n\\nВ JavaScript есть встроенные методы toUpperCase() и toLowerCase(). Однако у нас нет встроенной поддержки капитализации. Так давайте же создадим ее!
\\n\\n\\n\\nconst capitalize = (str) => {\\n const arr = str.trim().toLowerCase().split(\\\" \\\");\\n\\n for (let i = 0; i < arr.length; i++) {\\n arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1);\\n }\\n\\n return arr.join(\\\" \\\");\\n};\\n\\ncapitalize(\\\"hello, world!\\\");\\n// Expected output: \\\"Hello, World!\\\"\\n
\\n\\n\\n\\nПояснение:
\\n\\n\\n\\nsplit() – превращает строку в массив
\\n\\n\\n\\narr[i].charAt(0).toUpperCase() – переводит в верхний регистр первую букву каждого слова
\\n\\n\\n\\narr[i].slice(1) – возвращает оставшиеся буквы слова.
\\n\\n\\n\\narr.join(” “) – превращает массив обратно в строку
\\n\\n\\n\\nВы когда-нибудь слышали об атаках межсайтового скриптинга (XSS)? Если нет, то это тип атаки, который встречается на большинстве веб-сайтов. Например, при отправке формы злоумышленник может попытаться отправить вредоносные сценарии для взлома системы. Чтобы этого не произошло в ваших формах, вы можете использовать эту удобную функцию, которая “санирует” код скрипта.
\\n\\n\\n\\nconst sanitizeHTML = (str) => {\\n const div = document.createElement(\\\"div\\\");\\n div.textContent = str;\\n return div.innerHTML;\\n};\\n\\nsanitizeHTML(\\\"<h1>Hello, World!</h1>\\\");\\n// Expected output: \\\"&lt;h1&gt;Hello, World!&lt;/h1&gt;\\\"\\n
\\n\\n\\n\\nПояснения: В отличие от innerHTML, textContent не разбирает строку как HTML, в то время как innerText показывает только “человекочитаемые” элементы.
\\n\\n\\n\\nБолее того, использование textContent может предотвратить XSS-атаки. – MDN Docs
\\n\\n\\n\\nВозможно, вы использовали localStorage в своих приложениях для составления списка дел или любых других проектах для сохранения определенных данных в памяти компьютера пользователя. При получении и установке элементов приходится использовать методы JSON parse() и stringify() для достижения желаемого результата. Итак, давайте упростим работу с ними.
\\n\\n\\n\\nconst storage = {\\n get: (key, defaultValue = null) => {\\n const value = localStorage.getItem(key);\\n return value ? JSON.parse(value) : defaultValue;\\n },\\n set: (key, value) => localStorage.setItem(key, JSON.stringify(value)),\\n remove: (key) => localStorage.removeItem(key),\\n clear: () => localStorage.clear(),\\n};\\n\\nstorage.set(\\\"motto\\\", \\\"Eat, Sleep, Code, Repeat\\\");\\nstorage.get(\\\"motto\\\");\\n
\\n\\n\\n\\nПояснение: Если вы не знаете о методах JSON parse() и stringify(), посмотрите MDN Docs для лучшего объяснения.
\\n\\n\\n\\nПримечание: Мне было довольно сложно придумать хорошее название, которое имело бы гораздо больше смысла, чем просто хранилище. Потому что на первый взгляд разработчики могут не понять, относится ли это к ‘localStorage’ или к чему-то другому. Однако вы можете назвать его как угодно. Также, если вы нашли хорошие названия, пожалуйста, сообщите мне об этом в разделе комментариев.
\\n\\n\\n\\nЕсли у вас есть вопросы или предложения, раздел комментариев в вашем распоряжении. Возможно, мы сделаем вторую часть этой статьи с вашими предложениями.
\\n\\n\\n\\nСпасибо за чтение! 🙂
\\n\\n\\n\\n\\n\\n\\n\\n💸 Отблагодарить автора:
💰 https://www.donationalerts.com/c/woorg_
💰 BTC: 36dLKv5uRozphSQa55w2XgsF42AugPu2QT
💰 ETH: 0x442721192987047eDeEC69Ca1D4c706f9Adb16B3
💰 USDT (TRC20): TR121HxpTDF71TMm9idZkBaZxnjSMcCPWj
Привет! 👋 Сегодня мы рассмотрим 10 пользовательских функций JavaScript, которые могут пригодиться в большинстве ваших проектов. Да, инструмент, который мы все любим и используем для печати, отладки и т.д. Так почему бы не сократить его, чтобы уменьшить набор текста и сэкономить немного времени? console.log() Объяснение: мы используем назначение деструктуризации, чтобы иметь возможность извлечь метод log […]
\\n\"],\"featuredImage\":[0,null],\"seo\":[0,{\"fullHead\":[0,\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"],\"breadcrumbs\":[1,\"[[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Главная\\\"],\\\"url\\\":[0,\\\"https://igorlov.ru\\\"]}],[0,{\\\"isHidden\\\":[0,false],\\\"text\\\":[0,\\\"Учебник\\\"],\\\"url\\\":[0,\\\"http://igorlov.loc/category/uchebniki/\\\"]}]]\"],\"canonicalUrl\":[0,\"http://igorlov.loc/10-poleznyh-utilit-javascript/\"],\"title\":[0,\"10 полезных утилит JavaScript - Gorlov.\"],\"breadcrumbTitle\":[0,\"10 полезных утилит JavaScript\"],\"description\":[0,\"Привет! 👋\"],\"jsonLd\":[0,{\"raw\":[0,\"\\n\"]}],\"openGraph\":[0,{\"description\":[0,\"Привет! 👋\"],\"locale\":[0,\"EN_US\"],\"siteName\":[0,\"Gorlov.\"],\"title\":[0,\"10 полезных утилит JavaScript - Gorlov.\"],\"type\":[0,\"article\"],\"updatedTime\":[0,\"2023-03-19T22:42:16+00:00\"],\"url\":[0,\"http://igorlov.loc/10-poleznyh-utilit-javascript/\"]}]}],\"title\":[0,\"10 полезных утилит JavaScript\"],\"uri\":[0,\"/10-poleznyh-utilit-javascript/\"],\"status\":[0,\"publish\"],\"slug\":[0,\"10-poleznyh-utilit-javascript\"],\"categories\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}],\"terms\":[0,{\"nodes\":[1,\"[[0,{\\\"name\\\":[0,\\\"JavaScript\\\"],\\\"id\\\":[0,\\\"dGVybTo0Mw==\\\"],\\\"uri\\\":[0,\\\"/tag/javascript/\\\"]}],[0,{\\\"name\\\":[0,\\\"Учебник\\\"],\\\"id\\\":[0,\\\"dGVybToyOQ==\\\"],\\\"uri\\\":[0,\\\"/category/uchebniki/\\\"]}]]\"]}]}]}],[0,{\"cursor\":[0,\"YXJyYXljb25uZWN0aW9uOjY5MjA=\"],\"node\":[0,{\"date\":[0,\"2023-03-04T17:41:18\"],\"content\":[0,\"\\nDocker – это технология контейнеризации программного обеспечения, которая помогает разработчикам создавать и развертывать приложения на различных платформах – от настольных компьютеров до облачных вычислений.
\\n\\n\\n\\nСнимок – или чертеж – исходного кода, зависимостей и инструментов, необходимых для создания приложения в контейнере Docker, называется образом. Приложения Docker, которым требуются постоянные данные, могут полагаться на хранилища, называемые томами, которые не зависят от базовой операционной системы.
\\n\\n\\n\\nЭффективная организация образов, томов и контейнеров очень важна при использовании Docker. Неиспользуемые воплощения этих активов могут накапливаться, занимая ценное дисковое пространство и в конечном итоге влияя на производительность системы.
\\n\\n\\n\\nВ этой статье рассматриваются различные способы поддержания организации системы путем очистки образов (как по отдельности, так и всех сразу), томов и контейнеров. Для быстрого выполнения этих задач мы будем использовать интерфейс командной строки (CLI) docker.
\\n\\n\\n\\n