{"id":392482,"date":"2024-06-29T10:26:09","date_gmt":"2024-06-29T10:26:09","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=392482"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=392482","title":{"rendered":"<span>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 ETL-\u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u0432 Apache Airflow<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f9d\/22b\/35d\/f9d22b35d521cd022a3d057b19065697.png\" width=\"780\" height=\"439\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f9d\/22b\/35d\/f9d22b35d521cd022a3d057b19065697.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u0420\u0443\u0441\u0442\u0435\u043c, IBM Senior DevOps Engineer \u0438 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043d\u0430\u0448\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0432 DataOps \u0438\u043d\u0436\u0435\u043d\u0438\u0440\u0438\u0438 \u2014 Apache Airflow. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c ETL-\u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d. \u041d\u0435 \u0431\u0443\u0434\u0435\u043c \u0442\u043e\u043c\u0438\u0442\u044c, \u0441\u0440\u0430\u0437\u0443 \u043a \u0434\u0435\u043b\u0443!<\/p>\n<p>\u0427\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f? \u0421\u0423\u0411\u0414 MySQL, Apache Airflow \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 Datahub. <a href=\"https:\/\/datahub.io\/core\/top-level-domain-names\/r\/top-level-domain-names.csv.csv\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 datahub<\/a>.<\/p>\n<h3>\u041d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430<\/h3>\n<p>\u041d\u0430\u0448\u0435\u0439 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0435\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u043e \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u0449\u0438\u0445 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u0438\u043c\u0435\u043d \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 MySQL. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438:<\/p>\n<ol>\n<li>\n<p>\u0418\u0437\u0432\u043b\u0435\u0447\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u0430 Datahub.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0432 \u00ab\u043e\u0431\u0449\u0438\u0435\u00bb \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0441\u043b\u0443\u0436\u0431\u0443 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u044b \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0447\u0435\u043d\u044c \u0431\u043b\u0438\u0437\u043a\u043e \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0435 ETL.<\/p>\n<p>\u041d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0448\u0430\u0433\u0430\u0445 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0434\u044b \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0432 Airflow.<\/p>\n<h3>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u00abExtract node\u00bb<\/h3>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u043b\u044e\u0431\u044b\u043c \u0434\u0440\u0443\u0433\u0438\u043c \u0448\u0430\u0433\u0430\u043c, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435. <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043a\u0430\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code>wget -c https:\/\/datahub.io\/core\/top-level-domain-names\/r\/top-level-domain-names.csv.csv -O \/root\/manual-extract-data.csv<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e0a\/6b6\/c49\/e0a6b6c49cd8833079742254964b7dfe.png\" width=\"1183\" height=\"368\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e0a\/6b6\/c49\/e0a6b6c49cd8833079742254964b7dfe.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c:<\/p>\n<pre><code>head \/root\/manual-extract-data.csv<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/23a\/6b4\/bfb\/23a6b4bfb0699599b8e501684da164ea.png\" width=\"1177\" height=\"339\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/23a\/6b4\/bfb\/23a6b4bfb0699599b8e501684da164ea.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u201cExtract node\u201d<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 Airflow. \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043e\u0434\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 wget \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \/root\/airflow-extract-data.csv.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f Bash Airflow Operator.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e airflow_demo \u0441 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c dags. \u0412\u043d\u0443\u0442\u0440\u0438 dags \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b airflow-extract-node.py.<\/p>\n<p>\u041e\u0442\u043a\u0440\u043e\u0435\u043c \u0444\u0430\u0439\u043b \u0438 \u0432\u0441\u0442\u0430\u0432\u0438\u043c \u0432 \u043d\u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code>from airflow import DAG  from airflow.operators.bash import BashOperator  from datetime import datetime  with DAG('extract_dag',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0schedule_interval=None,  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0start_date=datetime(2022, 1, 1),  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0catchup=False) as dag:  \u00a0\u00a0\u00a0\u00a0extract_task = BashOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='extract_task',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bash_command='wget -c https:\/\/datahub.io\/core\/top-level-domain-names\/r\/top-level-domain-names.csv.csv -O \/root\/airflow-extract-data.csv',  \u00a0\u00a0\u00a0\u00a0)  \u00a0\u00a0\u00a0\u00a0extract_task<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bcf\/f3f\/81a\/bcff3f81a7ff91c17e1e3c70ccc6e360.png\" width=\"740\" height=\"545\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bcf\/f3f\/81a\/bcff3f81a7ff91c17e1e3c70ccc6e360.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 DAG, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0436\u0434\u0430\u0442\u044c, \u043f\u043e\u043a\u0430 Airflow \u0441\u0430\u043c \u043f\u043e\u0434\u0445\u0432\u0430\u0442\u0438\u0442 \u0435\u0433\u043e:<\/p>\n<pre><code>airflow db init<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6ed\/767\/286\/6ed7672860b5b216b53f2af2450d7b87.png\" width=\"1166\" height=\"221\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6ed\/767\/286\/6ed7672860b5b216b53f2af2450d7b87.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0435\u0433\u043e \u0438 \u0432 \u043d\u0430\u0448\u0435\u043c UI<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/078\/8e0\/a3a\/0788e0a3a11147fd852ceeb1d1f17877.png\" alt=\"\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u00abTransform node\u00bb\" title=\"\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u00abTransform node\u00bb\" width=\"1600\" height=\"416\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/078\/8e0\/a3a\/0788e0a3a11147fd852ceeb1d1f17877.png\"\/><figcaption>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u00abTransform node\u00bb<\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0448\u0430\u0433\u0435 \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u044f \u0438\u0445 \u0432 \u00ab\u043e\u0431\u0449\u0438\u0435\u00bb \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f.<\/p>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e<\/h3>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043d\u0430\u0434 \u043f\u043e\u0434\u0442\u0430\u0441\u043e\u0432\u043a\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445. \u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c python3 \u0438 pandas.<\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 pandas \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code>pip3 install pandas<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8bf\/3f9\/a1d\/8bf3f9a1d511495decc4eb1dab4ddc39.png\" width=\"1175\" height=\"429\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8bf\/3f9\/a1d\/8bf3f9a1d511495decc4eb1dab4ddc39.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0442\u0440\u0438 \u043a\u043e\u043c\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code>python3Import pandas as pdFrom datetime import date<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0435\u043c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0434\u0430\u0442\u0430\u0444\u0440\u0435\u0439\u043c\u0435 \u043f\u0430\u043d\u0434:<\/p>\n<pre><code>df = pd.read_csv(\"\/root\/manual-extract-data.csv\")  df <\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac1\/d5e\/450\/ac1d5e450fcd528139da27cc127e37ad.png\" width=\"1084\" height=\"437\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ac1\/d5e\/450\/ac1d5e450fcd528139da27cc127e37ad.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u00ab\u043e\u0431\u0449\u0438\u0435\u00bb \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0441\u0442\u043e\u043b\u0431\u0446\u0435 type:<\/p>\n<pre><code>df[\"Type\"].unique()<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/24b\/bde\/e7d\/24bbdee7d8bc188586bfa0a447e16e9f.png\" width=\"853\" height=\"84\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/24b\/bde\/e7d\/24bbdee7d8bc188586bfa0a447e16e9f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0444\u0438\u043b\u044c\u0442\u0440:<\/p>\n<pre><code>generic_type_df = df[df[\"Type\"] == \"generic\"]<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/17d\/063\/ddb\/17d063ddbccbb9bb11ebd64c68e26aa8.png\" width=\"853\" height=\"111\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/17d\/063\/ddb\/17d063ddbccbb9bb11ebd64c68e26aa8.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u0435 \u0434\u0430\u0442\u044b \u0432 \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u0437\u043d\u0430\u043b\u0438, \u0432 \u043a\u0430\u043a\u043e\u0439 \u0434\u0435\u043d\u044c \u043e\u043d\u0438 \u0431\u044b\u043b\u0438 \u043e\u0447\u0438\u0449\u0435\u043d\u044b:<\/p>\n<pre><code>today = date.today()<\/code><\/pre>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/77d\/d58\/e6b\/77dd58e6b7399abc1b9b8d3f894006ee.png\" width=\"341\" height=\"60\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/77d\/d58\/e6b\/77dd58e6b7399abc1b9b8d3f894006ee.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u043e\u0442 \u0441\u0442\u043e\u043b\u0431\u0435\u0446. (<em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em>. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0430\u044e\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430: \u00abA value is trying to be set on a copy of a slice&#8230;.\u00bb. \u041d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0439\u0442\u0435 \u043d\u0430 \u043d\u0435\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435).<\/p>\n<pre><code>generic_type_df[\"Date\"] = today.strftime(\"%Y-%m-%d\")<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ef0\/375\/540\/ef037554072ede88185a8ce278bf7afa.png\" width=\"1182\" height=\"215\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ef0\/375\/540\/ef037554072ede88185a8ce278bf7afa.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u042d\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u043f\u0438\u0448\u0435\u043c \u044d\u0442\u043e:<\/p>\n<pre><code>generic_type_df.to_csv(\"\/root\/manual-transformed-data.csv\", index=False)<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/557\/7dd\/180\/5577dd180d606e85a0b9ef1a7d494dfa.png\" width=\"1031\" height=\"101\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/557\/7dd\/180\/5577dd180d606e85a0b9ef1a7d494dfa.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0432 \u043d\u0430\u0448 Shell<\/p>\n<p><code>Ctrl + C<\/code><\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435<\/p>\n<pre><code>head \/root\/manual-transformed-data.csv<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/555\/f22\/bef\/555f22befd67d42ab70667fd6a21cae9.png\" width=\"820\" height=\"600\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/555\/f22\/bef\/555f22befd67d42ab70667fd6a21cae9.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u201cTransform node\u201d<\/h3>\n<p>\u041a\u0430\u043a \u0438 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f, \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 Airflow, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 Python.<\/p>\n<p>DAG \u0447\u0438\u0442\u0430\u0435\u0442 \u0438\u0437 \/root\/airflow-extract-data.csv, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u0442\u043e\u0442 \u0436\u0435 \u0444\u0438\u043b\u044c\u0442\u0440 pandas, \u0447\u0442\u043e \u0438 \u0432\u044b\u0448\u0435, \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \/root\/airflow-transformed-data.csv.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 IDE \u0432 \u043e\u043a\u043d\u0435 Katacoda, \u0433\u0434\u0435 \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 airflow_demo \u0441 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c dags. \u0412\u043d\u0443\u0442\u0440\u0438 dags \u0432\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b airflow-transform-node.py \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043a\u043e\u0434\u043e\u043c:<\/p>\n<pre><code>from airflow import DAG  from airflow.operators.python import PythonOperator  import pandas as pd  from datetime import datetime, date  with DAG(  \u00a0\u00a0\u00a0\u00a0dag_id='transform_dag',  \u00a0\u00a0\u00a0\u00a0schedule_interval=None,  \u00a0\u00a0\u00a0\u00a0start_date=datetime(2022, 1, 1),  \u00a0\u00a0\u00a0\u00a0catchup=False,  ) as dag:  \u00a0\u00a0def transform_data():  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"\"\"Read in the file, and write a transformed file out\"\"\"  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0today = date.today()  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0df = pd.read_csv(\"\/root\/airflow-extract-data.csv\")  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df = df[df[\"Type\"] == \"generic\"]  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df[\"Date\"] = today.strftime(\"%Y-%m-%d\")  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df.to_csv(\"\/root\/airflow-transformed-data.csv\", index=False)  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print(f'Number of rows: {len(generic_type_df)}')  \u00a0\u00a0transform_task = PythonOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='transform_task',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0python_callable=transform_data,  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dag=dag)  \u00a0\u00a0transform_task<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/52c\/4e9\/218\/52c4e92185ddbcef4051291f32a48217.png\" width=\"805\" height=\"846\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/52c\/4e9\/218\/52c4e92185ddbcef4051291f32a48217.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 DAG:<\/p>\n<pre><code>airflow db init<\/code><\/pre>\n<p>\u0412\u0438\u0434\u0438\u043c \u0435\u0433\u043e \u0432 UI:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d47\/d65\/2f9\/d47d652f9810414391edffe323378da8.png\" width=\"1600\" height=\"404\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d47\/d65\/2f9\/d47d652f9810414391edffe323378da8.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u00abLoad\u00bb<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u044d\u0442\u0430\u043f\u0443, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432 \u0441\u0435\u0431\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0438\u0445 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 (\u043a\u0430\u043a \u0434\u043b\u044f \u0440\u0443\u0447\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447 Airflow)<\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043d\u043e\u0432\u0430 \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443 MySQL:<\/p>\n<p><code>mysql<\/code><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2f1\/5d9\/3f2\/2f15d93f2f3069b65b2f05074d57a269.png\" width=\"1056\" height=\"398\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2f1\/5d9\/3f2\/2f15d93f2f3069b65b2f05074d57a269.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0411\u0414 \u0434\u043b\u044f \u201c\u0440\u0443\u0447\u043d\u044b\u0445\u201d \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code>CREATE DATABASE manual_load_database;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1c6\/39f\/58c\/1c639f58c9c804ebfa9c55684ba7504b.png\" width=\"855\" height=\"205\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1c6\/39f\/58c\/1c639f58c9c804ebfa9c55684ba7504b.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u0411\u0414 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445 Airflow:<\/p>\n<pre><code>CREATE DATABASE airflow_load_database;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/06d\/9b8\/68b\/06d9b868b30e0762fcf91d4fc0115bda.png\" width=\"882\" height=\"218\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/06d\/9b8\/68b\/06d9b868b30e0762fcf91d4fc0115bda.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0423\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u0441 \u043d\u0430\u0448\u0438\u043c\u0438 \u0411\u0414 \u0432\u0441\u0435 \u0432\u043f\u043e\u0440\u044f\u0434\u043a\u0435:<\/p>\n<pre><code>SHOW DATABASES;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f02\/dea\/04e\/f02dea04e8e26c640d75b41d6169b912.png\" width=\"865\" height=\"474\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f02\/dea\/04e\/f02dea04e8e26c640d75b41d6169b912.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0411\u0414.<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 manual_load_database:<\/p>\n<pre><code>USE manual_load_database;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/183\/6a5\/659\/1836a5659fac0d970eaa93707a5ec904.png\" width=\"530\" height=\"135\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/183\/6a5\/659\/1836a5659fac0d970eaa93707a5ec904.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0448\u0430 \u0441\u0445\u0435\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: Domain,Type,Sponsoring Organisation<\/p>\n<p>\u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u00ab\u043e\u0431\u0449\u0438\u0435\u00bb \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043d\u0430\u0448\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0435\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u0438\u0444\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0430\u0446\u0438\u0438 \u0435\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0448\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0434\u043b\u044f \u0434\u0430\u0442\u044b:<\/p>\n<pre><code>CREATE TABLE top_level_domains(Domain VARCHAR(30), Type VARCHAR(30), SponsoringOrganization VARCHAR(30), Date DATE);<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cf3\/541\/18e\/cf354118e302eb283d4500881bbcf86d.png\" width=\"1170\" height=\"234\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cf3\/541\/18e\/cf354118e302eb283d4500881bbcf86d.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043d\u0430\u0448\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0443:<\/p>\n<pre><code>DESCRIBE top_level_domains;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9c2\/6e0\/d77\/9c26e0d77b9cee894ff6dd9e622d5178.png\" width=\"974\" height=\"428\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9c2\/6e0\/d77\/9c26e0d77b9cee894ff6dd9e622d5178.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u043c \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0434\u043b\u044f airflow_load_database:<\/p>\n<pre><code>USE airflow_load_database; CREATE TABLE top_level_domains(Domain VARCHAR(30), Type VARCHAR(30), SponsoringOrganization VARCHAR(30), Date DATE);<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/08f\/f45\/750\/08ff45750681489333ad6ef4a82401dd.png\" width=\"1186\" height=\"264\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/08f\/f45\/750\/08ff45750681489333ad6ef4a82401dd.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0430\u043a\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0438 \u0432\u044b\u0439\u0434\u0435\u043c:<\/p>\n<pre><code>SET GLOBAL local_infile=1;<\/code><\/pre>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/81b\/8cd\/fef\/81b8cdfef305509754d758934dccdafe.png\" width=\"488\" height=\"137\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/81b\/8cd\/fef\/81b8cdfef305509754d758934dccdafe.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0437\u0430\u0439\u0434\u0435\u043c \u0432 mysql \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>mysql --local-infile=1<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/833\/2c8\/899\/8332c8899f0d7400895487534e638d7e.png\" width=\"1069\" height=\"387\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/833\/2c8\/899\/8332c8899f0d7400895487534e638d7e.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u044b\u0431\u0435\u0440\u0435\u043c \u0411\u0414:<\/p>\n<pre><code>USE manual_load_database;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac8\/75c\/89f\/ac875c89f7a6f8a281f35f811d738c63.png\" width=\"950\" height=\"252\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ac8\/75c\/89f\/ac875c89f7a6f8a281f35f811d738c63.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435:<\/p>\n<pre><code>LOAD DATA LOCAL INFILE '\/root\/manual-transformed-data.csv' INTO TABLE top_level_domains FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' IGNORE 1 ROWS;<\/code><\/pre>\n<p>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u0447\u043a\u0430:<\/p>\n<pre><code>select * from top_level_domains;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a6a\/356\/81a\/a6a35681ad0a375e25c6382859f6dbcc.png\" width=\"1165\" height=\"566\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a6a\/356\/81a\/a6a35681ad0a375e25c6382859f6dbcc.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440, \u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430! \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 ETL \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<h3>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u201cLoad Node\u201d<\/h3>\n<p>\u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Airflow \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u0439 \u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u044b, \u0447\u0442\u043e \u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 MySql. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043c\u043e\u0449\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 Airflow \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0435\u0433\u043e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c. \u041e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u043c\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0432\u0438\u0434\u044b \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.<\/p>\n<p>\u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 MySQL:<\/p>\n<pre><code>pip3 install apache-airflow-providers-mysql<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f3b\/fe4\/f76\/f3bfe4f76ea716fef8179d25035cd38a.png\" width=\"1134\" height=\"263\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f3b\/fe4\/f76\/f3bfe4f76ea716fef8179d25035cd38a.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b airflow-load-node.py \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043a\u043e\u0434\u043e\u043c:<\/p>\n<pre><code>from datetime import datetime  from airflow import DAG  from airflow.providers.mysql.operators.mysql import MySqlOperator  with DAG('load_dag',  \u00a0\u00a0\u00a0\u00a0start_date=datetime(2022, 1, 1),  \u00a0\u00a0\u00a0\u00a0schedule_interval=None,  \u00a0\u00a0\u00a0\u00a0default_args={'mysql_conn_id': 'demo_local_mysql'},  \u00a0\u00a0\u00a0\u00a0catchup=False) as dag:  \u00a0\u00a0\u00a0\u00a0load_task = MySqlOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='load_task', sql=r\"\"\"  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0USE airflow_load_database;  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LOAD DATA LOCAL INFILE '\/root\/airflow-transformed-data.csv' INTO TABLE top_level_domains FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' IGNORE 1 ROWS;  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"\"\", dag=dag  \u00a0\u00a0\u00a0\u00a0)  \u00a0\u00a0\u00a0\u00a0load_task<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5ab\/f34\/a90\/5abf34a906739201729553a8936e09f0.png\" width=\"790\" height=\"620\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5ab\/f34\/a90\/5abf34a906739201729553a8936e09f0.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0418 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 DAG:<\/p>\n<pre><code>airflow db init<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/168\/032\/4f8\/1680324f8bbd32efabc32c0bbeaace74.png\" width=\"1600\" height=\"227\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/168\/032\/4f8\/1680324f8bbd32efabc32c0bbeaace74.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435<\/h3>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0442\u0440\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 DAG, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0434\u043d\u0443 \u0437\u0430\u0434\u0430\u0447\u0443: \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u043c \u0438\u0445 \u0432 \u043e\u0434\u0438\u043d DAG Airflow.<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u0435\u043c ETL DAG<\/h3>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b \u0441 \u0438\u043c\u0435\u043d\u0435\u043c basic-etl-dag.py \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043a\u043e\u0434\u043e\u043c:<\/p>\n<pre><code>from airflow import DAG  from airflow.operators.bash\u00a0 import BashOperator  from airflow.operators.python import PythonOperator  from airflow.providers.mysql.operators.mysql import MySqlOperator  import pandas as pd  from datetime import datetime, date  default_args = {  \u00a0\u00a0\u00a0\u00a0'mysql_conn_id': 'demo_local_mysql'  }  with DAG('basic_etl_dag',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0schedule_interval=None,  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0default_args=default_args,  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0start_date=datetime(2022, 1, 1),  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0catchup=False) as dag:  \u00a0\u00a0\u00a0\u00a0extract_task = BashOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='extract_task',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bash_command='wget -c https:\/\/datahub.io\/core\/top-level-domain-names\/r\/top-level-domain-names.csv.csv -O \/root\/airflow-extract-data.csv',  \u00a0\u00a0\u00a0\u00a0)  \u00a0\u00a0\u00a0\u00a0extract_task  \u00a0\u00a0\u00a0\u00a0def transform_data():  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"\"\"Read in the file, and write a transformed file out\"\"\"  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0today = date.today()  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0df = pd.read_csv(\"\/root\/airflow-extract-data.csv\")  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df = df[df[\"Type\"] == \"generic\"]  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df[\"Date\"] = today.strftime(\"%Y-%m-%d\")  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df.to_csv(\"\/root\/airflow-transformed-data.csv\", index=False)  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print(f'Number of rows: {len(generic_type_df)}')  \u00a0\u00a0\u00a0\u00a0transform_task = PythonOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='transform_task',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0python_callable=transform_data,  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dag=dag)  \u00a0\u00a0\u00a0\u00a0transform_task  \u00a0\u00a0\u00a0\u00a0load_task = MySqlOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='load_task', sql=r\"\"\"  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0USE airflow_load_database;  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LOAD DATA LOCAL INFILE '\/root\/airflow-transformed-data.csv' INTO TABLE top_level_domains FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' IGNORE 1 ROWS;  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"\"\", dag=dag  \u00a0\u00a0\u00a0\u00a0)  \u00a0\u00a0\u00a0\u00a0load_task  \u00a0\u00a0\u00a0\u00a0extract_task >> transform_task >> load_task<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/49f\/f8d\/ef7\/49ff8def7601e7b246922b4a21a04330.png\" width=\"839\" height=\"862\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/49f\/f8d\/ef7\/49ff8def7601e7b246922b4a21a04330.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 DAG: <code>airflow db init<\/code>. <\/p>\n<p>\u0418 \u0443\u0432\u0438\u0434\u0438\u043c \u0435\u0433\u043e \u0432 \u043d\u0430\u0448\u0435\u043c UI:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/92e\/a96\/2cb\/92ea962cb2100a7297a0df0bc0a75ac5.png\" width=\"1600\" height=\"573\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/92e\/a96\/2cb\/92ea962cb2100a7297a0df0bc0a75ac5.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 DAG.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d50\/7f9\/cf5\/d507f9cf5579267c208efe86ec1f9d9c.png\" width=\"1600\" height=\"521\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d50\/7f9\/cf5\/d507f9cf5579267c208efe86ec1f9d9c.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 DAG \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e.<\/p>\n<p>\u0412\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043e\u043b\u0436\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0435 \u0442\u0440\u0438 \u0437\u0435\u043b\u0435\u043d\u044b\u0445 \u043f\u043e\u043b\u044f \u0432 Airflow.<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0448\u0430\u0433\u043e\u043c \u0437\u0430\u0434\u0430\u0447\u0438 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0432 DAG \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 Datahub \u0432 \/root\/airflow-extract-data.csv. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0435\u0441\u0442\u044c:<\/p>\n<pre><code>head \/root\/airflow-extract-data.csv<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/14a\/b8c\/422\/14ab8c4222ad9f12ee374b7ac19be2bb.png\" width=\"1187\" height=\"324\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/14a\/b8c\/422\/14ab8c4222ad9f12ee374b7ac19be2bb.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f, \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043c\u043e\u0433\u043b\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435.<\/p>\n<p>\u0428\u0430\u0433 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0444\u0430\u0439\u043b \/root\/airflow-extract-data.csv, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0432 \u043d\u0435\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u0432 \/root\/airflow-transformed-data.csv.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0435\u0441\u0442\u044c:<\/p>\n<pre><code>head \/root\/airflow-transformed-data.csv<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1a6\/4bf\/b57\/1a64bfb57d2754662c5ea70dc74fc961.png\" width=\"803\" height=\"298\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1a6\/4bf\/b57\/1a64bfb57d2754662c5ea70dc74fc961.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u044d\u0442\u0438 \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435.<\/p>\n<p>\u041d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \/root\/airflow-transformed-data.csv \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 MySQL.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443 MySQL, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0442\u0430\u043c \u043d\u0430\u0448\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b:<\/p>\n<p><code>mysql<\/code><\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 DAG Airflow:<\/p>\n<pre><code>USE airflow_load_database;<\/code><\/pre>\n<p>\u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c SELECT \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b:<\/p>\n<pre><code>SELECT * FROM top_level_domains;<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/017\/362\/73f\/01736273f2b689d1accd1e727710154e.png\" width=\"1111\" height=\"582\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/017\/362\/73f\/01736273f2b689d1accd1e727710154e.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0430\u0448\u0430 DAG \u043f\u0440\u043e\u0448\u043b\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e!<\/p>\n<hr\/>\n<blockquote>\n<p>\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0430\u0435\u043c \u0432\u0441\u0435\u0445 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0445 \u043d\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u0437\u0430\u043d\u044f\u0442\u0438\u0435 <strong>\u00abMapReduce: \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb<\/strong>. \u041d\u0430 \u043d\u0435\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0431\u0435\u0437 \u043e\u0431\u0449\u0435\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 (Hadoop, Spark). \u041f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e\u0431 \u00ab\u0443\u0437\u043a\u0438\u0445 \u043c\u0435\u0441\u0442\u0430\u0445\u00bb \u0438 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0445. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0432 \u042f\u043d\u0434\u0435\u043a\u0441.\u041e\u0431\u043b\u0430\u043a\u0435. <a href=\"https:\/\/otus.pw\/fp3O\/\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0437\u0434\u0435\u0441\u044c.<\/a><\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 <a href=\"https:\/\/otus.pw\/HX8Q\/\">\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0439\u0442\u0435\u0441\u044c <\/a>\u043d\u0430 \u0437\u0430\u043d\u044f\u0442\u0438\u0435 \u043f\u043e \u0442\u0435\u043c\u0435 <strong>\u00ab\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0441\u0438\u0441\u0442\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445\u00bb<\/strong>.<\/p>\n<\/blockquote>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/679402\/\"> https:\/\/habr.com\/ru\/articles\/679402\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u0420\u0443\u0441\u0442\u0435\u043c, IBM Senior DevOps Engineer \u0438 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043d\u0430\u0448\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0432 DataOps \u0438\u043d\u0436\u0435\u043d\u0438\u0440\u0438\u0438 \u2014 Apache Airflow. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c ETL-\u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d. \u041d\u0435 \u0431\u0443\u0434\u0435\u043c \u0442\u043e\u043c\u0438\u0442\u044c, \u0441\u0440\u0430\u0437\u0443 \u043a \u0434\u0435\u043b\u0443!<\/p>\n<p>\u0427\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f? \u0421\u0423\u0411\u0414 MySQL, Apache Airflow \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 Datahub. <a href=\"https:\/\/datahub.io\/core\/top-level-domain-names\/r\/top-level-domain-names.csv.csv\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 datahub<\/a>.<\/p>\n<h3>\u041d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430<\/h3>\n<p>\u041d\u0430\u0448\u0435\u0439 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0435\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u043e \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u0449\u0438\u0445 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u0438\u043c\u0435\u043d \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 MySQL. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438:<\/p>\n<ol>\n<li>\n<p>\u0418\u0437\u0432\u043b\u0435\u0447\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u0430 Datahub.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0432 \u00ab\u043e\u0431\u0449\u0438\u0435\u00bb \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0441\u043b\u0443\u0436\u0431\u0443 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u044b \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0447\u0435\u043d\u044c \u0431\u043b\u0438\u0437\u043a\u043e \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0435 ETL.<\/p>\n<p>\u041d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0448\u0430\u0433\u0430\u0445 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0434\u044b \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0432 Airflow.<\/p>\n<h3>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u00abExtract node\u00bb<\/h3>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u043b\u044e\u0431\u044b\u043c \u0434\u0440\u0443\u0433\u0438\u043c \u0448\u0430\u0433\u0430\u043c, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435. <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043a\u0430\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code>wget -c https:\/\/datahub.io\/core\/top-level-domain-names\/r\/top-level-domain-names.csv.csv -O \/root\/manual-extract-data.csv<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c:<\/p>\n<pre><code>head \/root\/manual-extract-data.csv<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u201cExtract node\u201d<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 Airflow. \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043e\u0434\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 wget \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \/root\/airflow-extract-data.csv.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f Bash Airflow Operator.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e airflow_demo \u0441 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c dags. \u0412\u043d\u0443\u0442\u0440\u0438 dags \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b airflow-extract-node.py.<\/p>\n<p>\u041e\u0442\u043a\u0440\u043e\u0435\u043c \u0444\u0430\u0439\u043b \u0438 \u0432\u0441\u0442\u0430\u0432\u0438\u043c \u0432 \u043d\u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code>from airflow import DAG  from airflow.operators.bash import BashOperator  from datetime import datetime  with DAG('extract_dag',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0schedule_interval=None,  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0start_date=datetime(2022, 1, 1),  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0catchup=False) as dag:  \u00a0\u00a0\u00a0\u00a0extract_task = BashOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='extract_task',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bash_command='wget -c https:\/\/datahub.io\/core\/top-level-domain-names\/r\/top-level-domain-names.csv.csv -O \/root\/airflow-extract-data.csv',  \u00a0\u00a0\u00a0\u00a0)  \u00a0\u00a0\u00a0\u00a0extract_task<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 DAG, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0436\u0434\u0430\u0442\u044c, \u043f\u043e\u043a\u0430 Airflow \u0441\u0430\u043c \u043f\u043e\u0434\u0445\u0432\u0430\u0442\u0438\u0442 \u0435\u0433\u043e:<\/p>\n<pre><code>airflow db init<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0435\u0433\u043e \u0438 \u0432 \u043d\u0430\u0448\u0435\u043c UI<\/p>\n<figure class=\"full-width\"><figcaption>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u00abTransform node\u00bb<\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0448\u0430\u0433\u0435 \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u044f \u0438\u0445 \u0432 \u00ab\u043e\u0431\u0449\u0438\u0435\u00bb \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f.<\/p>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e<\/h3>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043d\u0430\u0434 \u043f\u043e\u0434\u0442\u0430\u0441\u043e\u0432\u043a\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445. \u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c python3 \u0438 pandas.<\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 pandas \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code>pip3 install pandas<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0442\u0440\u0438 \u043a\u043e\u043c\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code>python3Import pandas as pdFrom datetime import date<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0435\u043c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0434\u0430\u0442\u0430\u0444\u0440\u0435\u0439\u043c\u0435 \u043f\u0430\u043d\u0434:<\/p>\n<pre><code>df = pd.read_csv(\"\/root\/manual-extract-data.csv\")  df <\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u00ab\u043e\u0431\u0449\u0438\u0435\u00bb \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0441\u0442\u043e\u043b\u0431\u0446\u0435 type:<\/p>\n<pre><code>df[\"Type\"].unique()<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0444\u0438\u043b\u044c\u0442\u0440:<\/p>\n<pre><code>generic_type_df = df[df[\"Type\"] == \"generic\"]<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u0435 \u0434\u0430\u0442\u044b \u0432 \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u0437\u043d\u0430\u043b\u0438, \u0432 \u043a\u0430\u043a\u043e\u0439 \u0434\u0435\u043d\u044c \u043e\u043d\u0438 \u0431\u044b\u043b\u0438 \u043e\u0447\u0438\u0449\u0435\u043d\u044b:<\/p>\n<pre><code>today = date.today()<\/code><\/pre>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u043e\u0442 \u0441\u0442\u043e\u043b\u0431\u0435\u0446. (<em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em>. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0430\u044e\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430: \u00abA value is trying to be set on a copy of a slice&#8230;.\u00bb. \u041d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0439\u0442\u0435 \u043d\u0430 \u043d\u0435\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435).<\/p>\n<pre><code>generic_type_df[\"Date\"] = today.strftime(\"%Y-%m-%d\")<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u042d\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u043f\u0438\u0448\u0435\u043c \u044d\u0442\u043e:<\/p>\n<pre><code>generic_type_df.to_csv(\"\/root\/manual-transformed-data.csv\", index=False)<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0432 \u043d\u0430\u0448 Shell<\/p>\n<p><code>Ctrl + C<\/code><\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435<\/p>\n<pre><code>head \/root\/manual-transformed-data.csv<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u201cTransform node\u201d<\/h3>\n<p>\u041a\u0430\u043a \u0438 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f, \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 Airflow, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 Python.<\/p>\n<p>DAG \u0447\u0438\u0442\u0430\u0435\u0442 \u0438\u0437 \/root\/airflow-extract-data.csv, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u0442\u043e\u0442 \u0436\u0435 \u0444\u0438\u043b\u044c\u0442\u0440 pandas, \u0447\u0442\u043e \u0438 \u0432\u044b\u0448\u0435, \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \/root\/airflow-transformed-data.csv.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 IDE \u0432 \u043e\u043a\u043d\u0435 Katacoda, \u0433\u0434\u0435 \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 airflow_demo \u0441 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c dags. \u0412\u043d\u0443\u0442\u0440\u0438 dags \u0432\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b airflow-transform-node.py \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043a\u043e\u0434\u043e\u043c:<\/p>\n<pre><code>from airflow import DAG  from airflow.operators.python import PythonOperator  import pandas as pd  from datetime import datetime, date  with DAG(  \u00a0\u00a0\u00a0\u00a0dag_id='transform_dag',  \u00a0\u00a0\u00a0\u00a0schedule_interval=None,  \u00a0\u00a0\u00a0\u00a0start_date=datetime(2022, 1, 1),  \u00a0\u00a0\u00a0\u00a0catchup=False,  ) as dag:  \u00a0\u00a0def transform_data():  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"\"\"Read in the file, and write a transformed file out\"\"\"  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0today = date.today()  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0df = pd.read_csv(\"\/root\/airflow-extract-data.csv\")  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df = df[df[\"Type\"] == \"generic\"]  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df[\"Date\"] = today.strftime(\"%Y-%m-%d\")  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df.to_csv(\"\/root\/airflow-transformed-data.csv\", index=False)  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print(f'Number of rows: {len(generic_type_df)}')  \u00a0\u00a0transform_task = PythonOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='transform_task',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0python_callable=transform_data,  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dag=dag)  \u00a0\u00a0transform_task<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 DAG:<\/p>\n<pre><code>airflow db init<\/code><\/pre>\n<p>\u0412\u0438\u0434\u0438\u043c \u0435\u0433\u043e \u0432 UI:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u00abLoad\u00bb<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u044d\u0442\u0430\u043f\u0443, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432 \u0441\u0435\u0431\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0438\u0445 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 (\u043a\u0430\u043a \u0434\u043b\u044f \u0440\u0443\u0447\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447 Airflow)<\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043d\u043e\u0432\u0430 \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443 MySQL:<\/p>\n<p><code>mysql<\/code><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0411\u0414 \u0434\u043b\u044f \u201c\u0440\u0443\u0447\u043d\u044b\u0445\u201d \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code>CREATE DATABASE manual_load_database;<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u0411\u0414 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445 Airflow:<\/p>\n<pre><code>CREATE DATABASE airflow_load_database;<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0423\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u0441 \u043d\u0430\u0448\u0438\u043c\u0438 \u0411\u0414 \u0432\u0441\u0435 \u0432\u043f\u043e\u0440\u044f\u0434\u043a\u0435:<\/p>\n<pre><code>SHOW DATABASES;<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0411\u0414.<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 manual_load_database:<\/p>\n<pre><code>USE manual_load_database;<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0448\u0430 \u0441\u0445\u0435\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: Domain,Type,Sponsoring Organisation<\/p>\n<p>\u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u00ab\u043e\u0431\u0449\u0438\u0435\u00bb \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043d\u0430\u0448\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0435\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u0438\u0444\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0430\u0446\u0438\u0438 \u0435\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0448\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0434\u043b\u044f \u0434\u0430\u0442\u044b:<\/p>\n<pre><code>CREATE TABLE top_level_domains(Domain VARCHAR(30), Type VARCHAR(30), SponsoringOrganization VARCHAR(30), Date DATE);<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043d\u0430\u0448\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0443:<\/p>\n<pre><code>DESCRIBE top_level_domains;<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u043c \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0434\u043b\u044f airflow_load_database:<\/p>\n<pre><code>USE airflow_load_database; CREATE TABLE top_level_domains(Domain VARCHAR(30), Type VARCHAR(30), SponsoringOrganization VARCHAR(30), Date DATE);<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0430\u043a\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0438 \u0432\u044b\u0439\u0434\u0435\u043c:<\/p>\n<pre><code>SET GLOBAL local_infile=1;<\/code><\/pre>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0437\u0430\u0439\u0434\u0435\u043c \u0432 mysql \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>mysql --local-infile=1<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u044b\u0431\u0435\u0440\u0435\u043c \u0411\u0414:<\/p>\n<pre><code>USE manual_load_database;<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435:<\/p>\n<pre><code>LOAD DATA LOCAL INFILE '\/root\/manual-transformed-data.csv' INTO TABLE top_level_domains FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' IGNORE 1 ROWS;<\/code><\/pre>\n<p>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u0447\u043a\u0430:<\/p>\n<pre><code>select * from top_level_domains;<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440, \u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430! \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 ETL \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<h3>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u201cLoad Node\u201d<\/h3>\n<p>\u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Airflow \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u0439 \u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u044b, \u0447\u0442\u043e \u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 MySql. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043c\u043e\u0449\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 Airflow \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0435\u0433\u043e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c. \u041e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u043c\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0432\u0438\u0434\u044b \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.<\/p>\n<p>\u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 MySQL:<\/p>\n<pre><code>pip3 install apache-airflow-providers-mysql<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b airflow-load-node.py \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043a\u043e\u0434\u043e\u043c:<\/p>\n<pre><code>from datetime import datetime  from airflow import DAG  from airflow.providers.mysql.operators.mysql import MySqlOperator  with DAG('load_dag',  \u00a0\u00a0\u00a0\u00a0start_date=datetime(2022, 1, 1),  \u00a0\u00a0\u00a0\u00a0schedule_interval=None,  \u00a0\u00a0\u00a0\u00a0default_args={'mysql_conn_id': 'demo_local_mysql'},  \u00a0\u00a0\u00a0\u00a0catchup=False) as dag:  \u00a0\u00a0\u00a0\u00a0load_task = MySqlOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='load_task', sql=r\"\"\"  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0USE airflow_load_database;  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LOAD DATA LOCAL INFILE '\/root\/airflow-transformed-data.csv' INTO TABLE top_level_domains FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' IGNORE 1 ROWS;  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"\"\", dag=dag  \u00a0\u00a0\u00a0\u00a0)  \u00a0\u00a0\u00a0\u00a0load_task<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0418 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 DAG:<\/p>\n<pre><code>airflow db init<\/code><\/pre>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435<\/h3>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0442\u0440\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 DAG, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0434\u043d\u0443 \u0437\u0430\u0434\u0430\u0447\u0443: \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u043c \u0438\u0445 \u0432 \u043e\u0434\u0438\u043d DAG Airflow.<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u0435\u043c ETL DAG<\/h3>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b \u0441 \u0438\u043c\u0435\u043d\u0435\u043c basic-etl-dag.py \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043a\u043e\u0434\u043e\u043c:<\/p>\n<pre><code>from airflow import DAG  from airflow.operators.bash\u00a0 import BashOperator  from airflow.operators.python import PythonOperator  from airflow.providers.mysql.operators.mysql import MySqlOperator  import pandas as pd  from datetime import datetime, date  default_args = {  \u00a0\u00a0\u00a0\u00a0'mysql_conn_id': 'demo_local_mysql'  }  with DAG('basic_etl_dag',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0schedule_interval=None,  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0default_args=default_args,  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0start_date=datetime(2022, 1, 1),  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0catchup=False) as dag:  \u00a0\u00a0\u00a0\u00a0extract_task = BashOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='extract_task',  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bash_command='wget -c https:\/\/datahub.io\/core\/top-level-domain-names\/r\/top-level-domain-names.csv.csv -O \/root\/airflow-extract-data.csv',  \u00a0\u00a0\u00a0\u00a0)  \u00a0\u00a0\u00a0\u00a0extract_task  \u00a0\u00a0\u00a0\u00a0def transform_data():  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"\"\"Read in the file, and write a transformed file out\"\"\"  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0today = date.today()  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0df = pd.read_csv(\"\/root\/airflow-extract-data.csv\")  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df = df[df[\"Type\"] == \"generic\"]  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df[\"Date\"] = today.strftime(\"%Y-%m-%d\")  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0generic_type_df.to_csv(\"\/root\/airflow-transformed-data.csv\", index=False)  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print(f'Number of rows: {len(generic_type_df)}')  \u00a0\u00a0\u00a0\u00a0transform_task = PythonOperator(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0task_id='transform_task', <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-392482","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/392482","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=392482"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/392482\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=392482"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=392482"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=392482"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}