ETL แƒžแƒ แƒแƒชแƒ”แƒกแƒ˜ แƒ”แƒšแƒคแƒแƒกแƒขแƒ˜แƒ“แƒแƒœ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒกแƒแƒฆแƒ”แƒ‘แƒแƒ“ Apache Airflow-แƒจแƒ˜

ETL แƒžแƒ แƒแƒชแƒ”แƒกแƒ˜ แƒ”แƒšแƒคแƒแƒกแƒขแƒ˜แƒ“แƒแƒœ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒกแƒแƒฆแƒ”แƒ‘แƒแƒ“ Apache Airflow-แƒจแƒ˜

แƒ แƒแƒช แƒแƒ  แƒฃแƒœแƒ“แƒ แƒ’แƒแƒœแƒ•แƒ˜แƒ—แƒแƒ แƒ“แƒ”แƒก แƒขแƒ”แƒฅแƒœแƒแƒšแƒแƒ’แƒ˜แƒ, แƒ›แƒแƒซแƒ•แƒ”แƒšแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ›แƒ˜แƒ“แƒ’แƒแƒ›แƒ”แƒ‘แƒ˜แƒก แƒกแƒ”แƒ แƒ˜แƒ แƒงแƒแƒ•แƒ”แƒšแƒ—แƒ•แƒ˜แƒก แƒฉแƒแƒ›แƒแƒ แƒฉแƒ”แƒ‘แƒ แƒ’แƒแƒœแƒ•แƒ˜แƒ—แƒแƒ แƒ”แƒ‘แƒ˜แƒก แƒฃแƒ™แƒแƒœ. แƒ”แƒก แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒ’แƒแƒ›แƒแƒฌแƒ•แƒ”แƒฃแƒšแƒ˜ แƒ˜แƒงแƒแƒก แƒ’แƒšแƒฃแƒ•แƒ˜ แƒ’แƒแƒ“แƒแƒกแƒ•แƒšแƒ˜แƒ—, แƒแƒ“แƒแƒ›แƒ˜แƒแƒœแƒฃแƒ แƒ˜ แƒคแƒแƒฅแƒขแƒแƒ แƒ”แƒ‘แƒ˜แƒ—, แƒขแƒ”แƒฅแƒœแƒแƒšแƒแƒ’แƒ˜แƒฃแƒ แƒ˜ แƒกแƒแƒญแƒ˜แƒ แƒแƒ”แƒ‘แƒ”แƒ‘แƒ˜แƒ— แƒแƒœ แƒกแƒฎแƒ•แƒ แƒ แƒแƒ›แƒ˜แƒ—. แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒ“แƒแƒ›แƒฃแƒจแƒแƒ•แƒ”แƒ‘แƒ˜แƒก แƒกแƒคแƒ”แƒ แƒแƒจแƒ˜, แƒแƒ› แƒœแƒแƒฌแƒ˜แƒšแƒจแƒ˜ แƒงแƒ•แƒ”แƒšแƒแƒ–แƒ” แƒ’แƒแƒ›แƒแƒ•แƒšแƒ”แƒœแƒ˜แƒšแƒ˜แƒ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒฌแƒงแƒแƒ แƒแƒ”แƒ‘แƒ˜. แƒ แƒแƒช แƒแƒ  แƒฃแƒœแƒ“แƒ แƒ•แƒแƒชแƒœแƒ”แƒ‘แƒแƒ‘แƒ“แƒ”แƒ— แƒแƒ›แƒ˜แƒก แƒ—แƒแƒ•แƒ˜แƒ“แƒแƒœ แƒแƒชแƒ˜แƒšแƒ”แƒ‘แƒแƒ–แƒ”, แƒ›แƒแƒ’แƒ แƒแƒ› แƒฏแƒ”แƒ แƒฏแƒ”แƒ แƒแƒ‘แƒ˜แƒ— แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒœแƒแƒฌแƒ˜แƒšแƒ˜ แƒ˜แƒ’แƒ–แƒแƒ•แƒœแƒ”แƒ‘แƒ แƒ›แƒงแƒ˜แƒกแƒ˜แƒ”แƒ  แƒ›แƒ”แƒกแƒ˜แƒœแƒฏแƒ”แƒ แƒ”แƒ‘แƒกแƒ แƒ“แƒ แƒ”แƒš.แƒฌแƒ”แƒ แƒ˜แƒšแƒ”แƒ‘แƒจแƒ˜, แƒ แƒแƒ› แƒแƒฆแƒแƒ แƒแƒคแƒ”แƒ แƒ˜ แƒ•แƒ—แƒฅแƒ•แƒแƒ— แƒฃแƒคแƒ แƒ แƒแƒ แƒฅแƒแƒฃแƒš แƒคแƒแƒ แƒ›แƒแƒขแƒ”แƒ‘แƒจแƒ˜. แƒ›แƒ” แƒ’แƒ”แƒžแƒแƒขแƒ˜แƒŸแƒ”แƒ‘แƒ˜แƒ— แƒ“แƒแƒจแƒแƒšแƒแƒ— Apache Airflow-แƒ˜แƒก แƒ”แƒ แƒ—-แƒ”แƒ แƒ—แƒ˜ แƒ•แƒแƒ แƒ˜แƒแƒœแƒขแƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒแƒกแƒแƒฎแƒแƒ•แƒก, โ€‹โ€‹แƒ—แƒฃ แƒ แƒแƒ’แƒแƒ  แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒ›แƒ˜แƒ˜แƒฆแƒแƒ— แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜ แƒ”แƒšแƒคแƒแƒกแƒขแƒ˜แƒ“แƒแƒœ.

แƒฌแƒ˜แƒœแƒแƒ˜แƒกแƒขแƒแƒ แƒ˜แƒ

แƒ‘แƒ”แƒ•แƒ แƒ˜ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ˜ แƒ™แƒ•แƒšแƒแƒ• แƒ’แƒแƒ“แƒแƒ“แƒ˜แƒก แƒ”แƒšแƒ”แƒฅแƒขแƒ แƒแƒœแƒฃแƒšแƒ˜ แƒคแƒแƒกแƒขแƒ˜แƒ—, แƒ˜แƒœแƒขแƒ”แƒ แƒžแƒ”แƒ แƒกแƒแƒœแƒแƒšแƒฃแƒ แƒ˜ แƒ™แƒแƒ›แƒฃแƒœแƒ˜แƒ™แƒแƒชแƒ˜แƒ”แƒ‘แƒ˜แƒ“แƒแƒœ แƒ™แƒแƒ›แƒžแƒแƒœแƒ˜แƒ”แƒ‘แƒก แƒจแƒแƒ แƒ˜แƒก แƒฃแƒ แƒ—แƒ˜แƒ”แƒ แƒ—แƒฅแƒ›แƒ”แƒ“แƒ”แƒ‘แƒ˜แƒก แƒกแƒขแƒแƒœแƒ“แƒแƒ แƒขแƒ”แƒ‘แƒแƒ›แƒ“แƒ”. แƒ™แƒแƒ แƒ’แƒ˜แƒ, แƒ—แƒฃ แƒจแƒ”แƒกแƒแƒซแƒšแƒ”แƒ‘แƒ”แƒšแƒ˜แƒ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒ›แƒแƒกแƒแƒžแƒแƒ•แƒ”แƒ‘แƒšแƒแƒ“ แƒ˜แƒœแƒขแƒ”แƒ แƒคแƒ”แƒ˜แƒกแƒ˜แƒก แƒ“แƒแƒฌแƒ”แƒ แƒ แƒแƒœ แƒแƒคแƒ˜แƒกแƒจแƒ˜ แƒแƒ“แƒแƒ›แƒ˜แƒแƒœแƒ”แƒ‘แƒ˜แƒก แƒ’แƒแƒœแƒ—แƒแƒ•แƒกแƒ”แƒ‘แƒ, แƒ แƒแƒ›แƒšแƒ”แƒ‘แƒ˜แƒช แƒแƒ› แƒ˜แƒœแƒคแƒแƒ แƒ›แƒแƒชแƒ˜แƒแƒก แƒฃแƒคแƒ แƒ แƒ›แƒแƒกแƒแƒฎแƒ”แƒ แƒฎแƒ”แƒ‘แƒ”แƒš แƒฌแƒงแƒแƒ แƒแƒ”แƒ‘แƒจแƒ˜ แƒจแƒ”แƒ˜แƒขแƒแƒœแƒ”แƒœ, แƒ›แƒแƒ’แƒ แƒแƒ› แƒฎแƒจแƒ˜แƒ แƒแƒ“ แƒ”แƒก แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒฃแƒ‘แƒ แƒแƒšแƒแƒ“ แƒจแƒ”แƒฃแƒซแƒšแƒ”แƒ‘แƒ”แƒšแƒ˜ แƒ˜แƒงแƒแƒก. แƒ™แƒแƒœแƒ™แƒ แƒ”แƒขแƒฃแƒšแƒ˜ แƒแƒ›แƒแƒชแƒแƒœแƒ, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒ›แƒ” แƒฌแƒแƒ•แƒแƒฌแƒงแƒ“แƒ˜, แƒ˜แƒงแƒ แƒชแƒœแƒแƒ‘แƒ˜แƒšแƒ˜ CRM แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒ˜แƒก แƒ“แƒแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ”แƒ‘แƒ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒกแƒแƒฌแƒงแƒแƒ‘แƒ—แƒแƒœ, แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒ™แƒ˜ OLAP แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒแƒกแƒ—แƒแƒœ. แƒแƒกแƒ” แƒ›แƒแƒฎแƒ“แƒ แƒ˜แƒกแƒขแƒแƒ แƒ˜แƒฃแƒšแƒแƒ“, แƒ แƒแƒ› แƒฉแƒ•แƒ”แƒœแƒ˜ แƒ™แƒแƒ›แƒžแƒแƒœแƒ˜แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก แƒแƒ› แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ แƒ›แƒแƒกแƒแƒฎแƒ”แƒ แƒฎแƒ”แƒ‘แƒ”แƒšแƒ˜ แƒ˜แƒงแƒ แƒ‘แƒ˜แƒ–แƒœแƒ”แƒกแƒ˜แƒก แƒ™แƒแƒœแƒ™แƒ แƒ”แƒขแƒฃแƒš แƒกแƒคแƒ”แƒ แƒแƒจแƒ˜. แƒแƒ›แƒ˜แƒขแƒแƒ›, แƒงแƒ•แƒ”แƒšแƒแƒก แƒซแƒแƒšแƒ˜แƒแƒœ แƒกแƒฃแƒ แƒ“แƒ แƒแƒ› แƒ›แƒ”แƒกแƒแƒ›แƒ” แƒ›แƒฎแƒแƒ แƒ˜แƒก แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒ˜แƒก แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒ— แƒ›แƒฃแƒจแƒแƒแƒ‘แƒแƒช. แƒฃแƒžแƒ˜แƒ แƒ•แƒ”แƒšแƒ”แƒก แƒงแƒแƒ•แƒšแƒ˜แƒกแƒ, แƒ แƒ แƒ—แƒฅแƒ›แƒ แƒฃแƒœแƒ“แƒ, แƒจแƒ”แƒกแƒฌแƒแƒ•แƒšแƒ˜แƒšแƒ˜ แƒ˜แƒฅแƒœแƒ แƒฆแƒ˜แƒ API-แƒ“แƒแƒœ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ›แƒแƒžแƒแƒ•แƒ”แƒ‘แƒ˜แƒก แƒจแƒ”แƒกแƒแƒซแƒšแƒ”แƒ‘แƒšแƒแƒ‘แƒ. แƒกแƒแƒ›แƒฌแƒฃแƒฎแƒแƒ แƒแƒ“, API แƒแƒ  แƒ›แƒแƒ˜แƒชแƒแƒ•แƒ“แƒ แƒงแƒ•แƒ”แƒšแƒ แƒกแƒแƒญแƒ˜แƒ แƒ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ˜แƒก แƒ›แƒ˜แƒฆแƒ”แƒ‘แƒแƒก แƒ“แƒ, แƒ›แƒแƒ แƒขแƒ˜แƒ•แƒ˜ แƒกแƒ˜แƒขแƒงแƒ•แƒ”แƒ‘แƒ˜แƒ— แƒ แƒแƒ› แƒ•แƒ—แƒฅแƒ•แƒแƒ—, แƒ˜แƒก แƒ›แƒ แƒแƒ•แƒแƒšแƒ˜ แƒ—แƒ•แƒแƒšแƒกแƒแƒ–แƒ แƒ˜แƒกแƒ˜แƒ— แƒ›แƒชแƒ“แƒแƒ แƒ˜ แƒ˜แƒงแƒ แƒ“แƒ แƒขแƒ”แƒฅแƒœแƒ˜แƒ™แƒฃแƒ แƒ˜ แƒ›แƒฎแƒแƒ แƒ“แƒแƒญแƒ”แƒ แƒ แƒแƒ  แƒกแƒฃแƒ แƒ“แƒ แƒแƒœ แƒ•แƒ”แƒ  แƒฎแƒ•แƒ“แƒ”แƒ‘แƒแƒ“แƒ แƒจแƒฃแƒ แƒ’แƒ–แƒแƒ–แƒ” แƒฃแƒคแƒ แƒ แƒกแƒ แƒฃแƒšแƒงแƒแƒคแƒ˜แƒšแƒ˜ แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒแƒœแƒ˜แƒ แƒ”แƒ‘แƒ˜แƒก แƒฃแƒ–แƒ แƒฃแƒœแƒ•แƒ”แƒšแƒกแƒแƒงแƒแƒคแƒแƒ“. แƒ›แƒแƒ’แƒ แƒแƒ› แƒ”แƒก แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒ แƒกแƒแƒจแƒฃแƒแƒšแƒ”แƒ‘แƒแƒก แƒแƒซแƒšแƒ”แƒ•แƒ“แƒ แƒžแƒ”แƒ แƒ˜แƒแƒ“แƒฃแƒšแƒแƒ“ แƒ›แƒ˜แƒ”แƒฆแƒ แƒ“แƒแƒ™แƒแƒ แƒ’แƒฃแƒšแƒ˜ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜ แƒคแƒแƒกแƒขแƒ˜แƒ— แƒแƒ แƒฅแƒ˜แƒ•แƒ˜แƒก แƒ’แƒแƒ“แƒ›แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ˜แƒก แƒ‘แƒ›แƒฃแƒšแƒ˜แƒก แƒกแƒแƒฎแƒ˜แƒ—.

แƒฃแƒœแƒ“แƒ แƒแƒฆแƒ˜แƒœแƒ˜แƒจแƒœแƒแƒก, แƒ แƒแƒ› แƒ”แƒก แƒแƒ  แƒ˜แƒงแƒ แƒ”แƒ แƒ—แƒแƒ“แƒ”แƒ แƒ—แƒ˜ แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒ, แƒ แƒแƒ“แƒ”แƒกแƒแƒช แƒ‘แƒ˜แƒ–แƒœแƒ”แƒกแƒก แƒกแƒฃแƒ แƒ“แƒ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒจแƒ”แƒ’แƒ แƒแƒ•แƒ”แƒ‘แƒ แƒ”แƒš.แƒฌแƒ”แƒ แƒ˜แƒšแƒ”แƒ‘แƒ˜แƒ“แƒแƒœ แƒแƒœ แƒ›แƒงแƒ˜แƒกแƒ˜แƒ”แƒ แƒ˜ แƒ›แƒ”แƒกแƒ˜แƒœแƒฏแƒ”แƒ แƒ”แƒ‘แƒ˜แƒ“แƒแƒœ. แƒ—แƒฃแƒ›แƒชแƒ, แƒแƒ› แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒฉแƒ•แƒ”แƒœ แƒ•แƒ”แƒ  แƒ›แƒแƒ•แƒแƒฎแƒ”แƒ แƒฎแƒ”แƒ— แƒ’แƒแƒ•แƒšแƒ”แƒœแƒ แƒ›แƒ”แƒกแƒแƒ›แƒ” แƒ›แƒฎแƒแƒ แƒ˜แƒก แƒ™แƒแƒ›แƒžแƒแƒœแƒ˜แƒแƒ–แƒ”, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒ›แƒฎแƒแƒšแƒแƒ“ แƒแƒ› แƒ’แƒ–แƒ˜แƒ— แƒแƒฌแƒ•แƒ“แƒ˜แƒก แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒœแƒแƒฌแƒ˜แƒšแƒก.

แƒแƒžแƒแƒฉแƒ˜แƒก แƒฐแƒแƒ”แƒ แƒ˜แƒก แƒœแƒแƒ™แƒแƒ“แƒ˜

ETL แƒžแƒ แƒแƒชแƒ”แƒกแƒ”แƒ‘แƒ˜แƒก แƒจแƒ”แƒกแƒแƒฅแƒ›แƒœแƒ”แƒšแƒแƒ“, แƒฉแƒ•แƒ”แƒœ แƒงแƒ•แƒ”แƒšแƒแƒ–แƒ” แƒฎแƒจแƒ˜แƒ แƒแƒ“ แƒ•แƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ— Apache Airflow-แƒก. แƒ˜แƒ›แƒ˜แƒกแƒแƒ—แƒ•แƒ˜แƒก, แƒ แƒแƒ› แƒ›แƒ™แƒ˜แƒ—แƒฎแƒ•แƒ”แƒšแƒ›แƒ, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒแƒ  แƒ˜แƒชแƒœแƒแƒ‘แƒก แƒแƒ› แƒขแƒ”แƒฅแƒœแƒแƒšแƒแƒ’แƒ˜แƒแƒก, แƒฃแƒ™แƒ”แƒ— แƒ’แƒแƒ˜แƒ’แƒแƒก, แƒ แƒแƒ’แƒแƒ  แƒ’แƒแƒ›แƒแƒ˜แƒงแƒฃแƒ แƒ”แƒ‘แƒ แƒ˜แƒก แƒ™แƒแƒœแƒขแƒ”แƒฅแƒกแƒขแƒจแƒ˜ แƒ“แƒ แƒ–แƒแƒ’แƒแƒ“แƒแƒ“, แƒ›แƒ” แƒแƒฆแƒ•แƒฌแƒ”แƒ  แƒ แƒแƒ›แƒ“แƒ”แƒœแƒ˜แƒ›แƒ” แƒจแƒ”แƒกแƒแƒ•แƒแƒšแƒก.

Apache Airflow แƒแƒ แƒ˜แƒก แƒฃแƒคแƒแƒกแƒ แƒžแƒšแƒแƒขแƒคแƒแƒ แƒ›แƒ, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒ’แƒแƒ›แƒแƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ Python-แƒจแƒ˜ ETL (Extract-Transform-Loading) แƒžแƒ แƒแƒชแƒ”แƒกแƒ”แƒ‘แƒ˜แƒก แƒจแƒ”แƒกแƒแƒฅแƒ›แƒœแƒ”แƒšแƒแƒ“, แƒจแƒ”แƒกแƒแƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒšแƒแƒ“ แƒ“แƒ แƒ›แƒแƒœแƒ˜แƒขแƒแƒ แƒ˜แƒœแƒ’แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก. Airflow-แƒ˜แƒก แƒ›แƒ—แƒแƒ•แƒแƒ แƒ˜ แƒ™แƒแƒœแƒชแƒ”แƒคแƒชแƒ˜แƒ แƒแƒ แƒ˜แƒก แƒ›แƒ˜แƒ›แƒแƒ แƒ—แƒฃแƒšแƒ˜ แƒแƒชแƒ˜แƒ™แƒšแƒฃแƒ แƒ˜ แƒ’แƒ แƒแƒคแƒ˜แƒ™แƒ˜, แƒกแƒแƒ“แƒแƒช แƒ’แƒ แƒแƒคแƒ˜แƒก แƒฌแƒ•แƒ”แƒ แƒแƒ”แƒ‘แƒ˜ แƒแƒ แƒ˜แƒก แƒกแƒžแƒ”แƒชแƒ˜แƒคแƒ˜แƒ™แƒฃแƒ แƒ˜ แƒžแƒ แƒแƒชแƒ”แƒกแƒ”แƒ‘แƒ˜, แƒฎแƒแƒšแƒ แƒ’แƒ แƒแƒคแƒ˜แƒก แƒ™แƒ˜แƒ“แƒ”แƒ”แƒ‘แƒ˜ แƒแƒ แƒ˜แƒก แƒ™แƒแƒœแƒขแƒ แƒแƒšแƒ˜แƒก แƒแƒœ แƒ˜แƒœแƒคแƒแƒ แƒ›แƒแƒชแƒ˜แƒ˜แƒก แƒœแƒแƒ™แƒแƒ“แƒ˜. แƒžแƒ แƒแƒชแƒ”แƒกแƒก แƒจแƒ”แƒฃแƒซแƒšแƒ˜แƒ แƒฃแƒ‘แƒ แƒแƒšแƒแƒ“ แƒ’แƒแƒ›แƒแƒ˜แƒซแƒแƒฎแƒแƒก แƒžแƒ˜แƒ—แƒแƒœแƒ˜แƒก แƒœแƒ”แƒ‘แƒ˜แƒกแƒ›แƒ˜แƒ”แƒ แƒ˜ แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ, แƒแƒœ แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒฐแƒฅแƒแƒœแƒ“แƒ”แƒก แƒฃแƒคแƒ แƒ แƒ แƒ—แƒฃแƒšแƒ˜ แƒšแƒแƒ’แƒ˜แƒ™แƒ แƒ™แƒšแƒแƒกแƒ˜แƒก แƒ™แƒแƒœแƒขแƒ”แƒฅแƒกแƒขแƒจแƒ˜ แƒ แƒแƒ›แƒ“แƒ”แƒœแƒ˜แƒ›แƒ” แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ˜แƒก แƒ—แƒแƒœแƒ›แƒ˜แƒ›แƒ“แƒ”แƒ•แƒ แƒฃแƒšแƒ˜ แƒ’แƒแƒ›แƒแƒซแƒแƒฎแƒ”แƒ‘แƒ˜แƒกแƒ’แƒแƒœ. แƒงแƒ•แƒ”แƒšแƒแƒ–แƒ” แƒฎแƒจแƒ˜แƒ แƒ˜ แƒแƒžแƒ”แƒ แƒแƒชแƒ˜แƒ”แƒ‘แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก, แƒฃแƒ™แƒ•แƒ” แƒแƒ แƒกแƒ”แƒ‘แƒแƒ‘แƒก แƒ›แƒ แƒแƒ•แƒแƒšแƒ˜ แƒ›แƒ–แƒ แƒ’แƒแƒœแƒ•แƒ˜แƒ—แƒแƒ แƒ”แƒ‘แƒ, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒฃแƒš แƒ˜แƒฅแƒœแƒแƒก แƒ แƒแƒ’แƒแƒ แƒช แƒžแƒ แƒแƒชแƒ”แƒกแƒ”แƒ‘แƒ˜. แƒแƒกแƒ”แƒ—แƒ˜ แƒ›แƒแƒ•แƒšแƒ”แƒœแƒ”แƒ‘แƒ˜ แƒ›แƒแƒ˜แƒชแƒแƒ•แƒก:

  • แƒแƒžแƒ”แƒ แƒแƒขแƒแƒ แƒ”แƒ‘แƒ˜ - แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ”แƒ แƒ—แƒ˜ แƒแƒ“แƒ’แƒ˜แƒšแƒ˜แƒ“แƒแƒœ แƒ›แƒ”แƒแƒ แƒ”แƒ–แƒ” แƒ’แƒแƒ“แƒแƒกแƒแƒขแƒแƒœแƒแƒ“, แƒ›แƒแƒ’แƒแƒšแƒ˜แƒ—แƒแƒ“, แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒ‘แƒแƒ–แƒ˜แƒก แƒชแƒฎแƒ แƒ˜แƒšแƒ˜แƒ“แƒแƒœ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒกแƒแƒฌแƒงแƒแƒ‘แƒจแƒ˜;
  • แƒกแƒ”แƒœแƒกแƒแƒ แƒ”แƒ‘แƒ˜ - แƒ’แƒแƒ แƒ™แƒ•แƒ”แƒฃแƒšแƒ˜ แƒ›แƒแƒ•แƒšแƒ”แƒœแƒ˜แƒก แƒ›แƒแƒšแƒแƒ“แƒ˜แƒœแƒจแƒ˜ แƒ“แƒ แƒ™แƒแƒœแƒขแƒ แƒแƒšแƒ˜แƒก แƒœแƒแƒ™แƒแƒ“แƒ˜แƒก แƒ›แƒ˜แƒ›แƒแƒ แƒ—แƒฃแƒšแƒ”แƒ‘แƒ แƒ’แƒ แƒแƒคแƒ˜แƒก แƒจแƒ”แƒ›แƒ“แƒ’แƒแƒ› แƒฌแƒ•แƒ”แƒ แƒแƒ”แƒ‘แƒ–แƒ”;
  • hooks - แƒฅแƒ•แƒ”แƒ“แƒ แƒ“แƒแƒœแƒ˜แƒก แƒแƒžแƒ”แƒ แƒแƒชแƒ˜แƒ”แƒ‘แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก, แƒ›แƒแƒ’แƒแƒšแƒ˜แƒ—แƒแƒ“, แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒ‘แƒแƒ–แƒ˜แƒก แƒชแƒฎแƒ แƒ˜แƒšแƒ˜แƒ“แƒแƒœ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒกแƒแƒฆแƒ”แƒ‘แƒแƒ“ (แƒ’แƒแƒ›แƒแƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ แƒ’แƒแƒœแƒชแƒฎแƒแƒ“แƒ”แƒ‘แƒ”แƒ‘แƒจแƒ˜);
  • แƒ.แƒจ.

แƒแƒ› แƒกแƒขแƒแƒขแƒ˜แƒแƒจแƒ˜ Apache Airflow แƒ“แƒ”แƒขแƒแƒšแƒฃแƒ แƒแƒ“ แƒแƒฆแƒฌแƒ”แƒ แƒ แƒแƒ  แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒ›แƒ˜แƒ–แƒแƒœแƒจแƒ”แƒฌแƒแƒœแƒ˜แƒšแƒ˜. แƒ›แƒแƒ™แƒšแƒ” แƒจแƒ”แƒกแƒแƒ•แƒแƒšแƒ˜ แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒ˜แƒฎแƒ˜แƒšแƒแƒ— แƒแƒฅ แƒแƒœ แƒแƒฅ.

Hook แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒกแƒแƒฆแƒ”แƒ‘แƒแƒ“

แƒฃแƒžแƒ˜แƒ แƒ•แƒ”แƒšแƒ”แƒก แƒงแƒแƒ•แƒšแƒ˜แƒกแƒ, แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ˜แƒก แƒ’แƒแƒ“แƒแƒกแƒแƒญแƒ แƒ”แƒšแƒแƒ“, แƒฉแƒ•แƒ”แƒœ แƒฃแƒœแƒ“แƒ แƒ“แƒแƒ•แƒฌแƒ”แƒ แƒแƒ— แƒ™แƒแƒ™แƒแƒšแƒ˜, แƒ แƒแƒ›แƒšแƒ˜แƒ—แƒแƒช แƒจแƒ”แƒ’แƒ•แƒ˜แƒซแƒšแƒ˜แƒ:

  • แƒ“แƒแƒฃแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ“แƒ˜แƒ— แƒ”แƒš.แƒฌแƒ”แƒ แƒ˜แƒšแƒก
  • แƒ˜แƒžแƒแƒ•แƒœแƒ”แƒ— แƒกแƒฌแƒแƒ แƒ˜ แƒแƒกแƒ
  • แƒ›แƒ˜แƒ˜แƒฆแƒ”แƒ— แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜ แƒฌแƒ”แƒ แƒ˜แƒšแƒ˜แƒ“แƒแƒœ.

from airflow.hooks.base_hook import BaseHook
import imaplib
import logging

class IMAPHook(BaseHook):
    def __init__(self, imap_conn_id):
        """
           IMAP hook ะดะปั ะฟะพะปัƒั‡ะตะฝะธั ะดะฐะฝะฝั‹ั… ั ัะปะตะบั‚ั€ะพะฝะฝะพะน ะฟะพั‡ั‚ั‹

           :param imap_conn_id:       ะ˜ะดะตะฝั‚ะธั„ะธะบะฐั‚ะพั€ ะฟะพะดะบะปัŽั‡ะตะฝะธั ะบ ะฟะพั‡ั‚ะต
           :type imap_conn_id:        string
        """
        self.connection = self.get_connection(imap_conn_id)
        self.mail = None

    def authenticate(self):
        """ 
            ะŸะพะดะบะปัŽั‡ะฐะตะผัั ะบ ะฟะพั‡ั‚ะต
        """
        mail = imaplib.IMAP4_SSL(self.connection.host)
        response, detail = mail.login(user=self.connection.login, password=self.connection.password)
        if response != "OK":
            raise AirflowException("Sign in failed")
        else:
            self.mail = mail

    def get_last_mail(self, check_seen=True, box="INBOX", condition="(UNSEEN)"):
        """
            ะœะตั‚ะพะด ะดะปั ะฟะพะปัƒั‡ะตะฝะธั ะธะดะตะฝั‚ะธั„ะธะบะฐั‚ะพั€ะฐ ะฟะพัะปะตะดะฝะตะณะพ ะฟะธััŒะผะฐ, 
            ัƒะดะพะฒะปะตั‚ะฒะพั€ะฐััŽั‰ะตะณะพ ัƒัะปะพะฒะธัะผ ะฟะพะธัะบะฐ

            :param check_seen:      ะžั‚ะผะตั‡ะฐั‚ัŒ ะฟะพัะปะตะดะฝะตะต ะฟะธััŒะผะพ ะบะฐะบ ะฟั€ะพั‡ะธั‚ะฐะฝะฝะพะต
            :type check_seen:       bool
            :param box:             ะะฐะธะผะตะฝะพะฒะฐะฝะธั ัั‰ะธะบะฐ
            :type box:              string
            :param condition:       ะฃัะปะพะฒะธั ะฟะพะธัะบะฐ ะฟะธัะตะผ
            :type condition:        string
        """
        self.authenticate()
        self.mail.select(mailbox=box)
        response, data = self.mail.search(None, condition)
        mail_ids = data[0].split()
        logging.info("ะ’ ัั‰ะธะบะต ะฝะฐะนะดะตะฝั‹ ัะปะตะดัƒัŽั‰ะธะต ะฟะธััŒะผะฐ: " + str(mail_ids))

        if not mail_ids:
            logging.info("ะะต ะฝะฐะนะดะตะฝะพ ะฝะพะฒั‹ั… ะฟะธัะตะผ")
            return None

        mail_id = mail_ids[0]

        # ะตัะปะธ ั‚ะฐะบะธั… ะฟะธัะตะผ ะฝะตัะบะพะปัŒะบะพ
        if len(mail_ids) > 1:
            # ะพั‚ะผะตั‡ะฐะตะผ ะพัั‚ะฐะปัŒะฝั‹ะต ะฟั€ะพั‡ะธั‚ะฐะฝะฝั‹ะผะธ
            for id in mail_ids:
                self.mail.store(id, "+FLAGS", "\Seen")

            # ะฒะพะทะฒั€ะฐั‰ะฐะตะผ ะฟะพัะปะตะดะฝะตะต
            mail_id = mail_ids[-1]

        # ะฝัƒะถะฝะพ ะปะธ ะพั‚ะผะตั‚ะธั‚ัŒ ะฟะพัะปะตะดะฝะตะต ะฟั€ะพั‡ะธั‚ะฐะฝะฝั‹ะผ
        if not check_seen:
            self.mail.store(mail_id, "-FLAGS", "\Seen")

        return mail_id

แƒšแƒแƒ’แƒ˜แƒ™แƒ แƒแƒกแƒ”แƒ—แƒ˜แƒ: แƒฉแƒ•แƒ”แƒœ แƒ•แƒฃแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ“แƒ”แƒ‘แƒ˜แƒ—, แƒ•แƒžแƒแƒฃแƒšแƒแƒ‘แƒ— แƒ‘แƒแƒšแƒ แƒงแƒ•แƒ”แƒšแƒแƒ–แƒ” แƒแƒฅแƒขแƒฃแƒแƒšแƒฃแƒ  แƒแƒกแƒแƒก, แƒ—แƒฃ แƒแƒ แƒ˜แƒก แƒกแƒฎแƒ•แƒ, แƒ•แƒแƒ˜แƒ’แƒœแƒแƒ แƒ”แƒ‘แƒ— แƒ›แƒแƒ—. แƒ”แƒก แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ แƒ’แƒแƒ›แƒแƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ, แƒ แƒแƒ“แƒ’แƒแƒœ แƒจแƒ”แƒ›แƒ“แƒ’แƒแƒ›แƒ˜ แƒแƒกแƒแƒ”แƒ‘แƒ˜ แƒจแƒ”แƒ˜แƒชแƒแƒ•แƒก แƒแƒ“แƒ แƒ˜แƒœแƒ“แƒ”แƒš แƒงแƒ•แƒ”แƒšแƒ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒก. แƒ—แƒฃ แƒ”แƒก แƒแƒกแƒ” แƒแƒ  แƒแƒ แƒ˜แƒก, แƒ›แƒแƒจแƒ˜แƒœ แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒ“แƒแƒแƒ‘แƒ แƒฃแƒœแƒแƒ— แƒงแƒ•แƒ”แƒšแƒ แƒแƒกแƒแƒก แƒ›แƒแƒกแƒ˜แƒ•แƒ˜, แƒแƒœ แƒ“แƒแƒแƒ›แƒฃแƒจแƒแƒ•แƒแƒ— แƒžแƒ˜แƒ แƒ•แƒ”แƒšแƒ˜, แƒฎแƒแƒšแƒ แƒ“แƒแƒœแƒแƒ แƒฉแƒ”แƒœแƒ˜ แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒฃแƒฆแƒ”แƒšแƒขแƒ”แƒฎแƒ˜แƒšแƒ–แƒ”. แƒ–แƒแƒ’แƒแƒ“แƒแƒ“, แƒงแƒ•แƒ”แƒšแƒแƒคแƒ”แƒ แƒ˜, แƒ แƒแƒ’แƒแƒ แƒช แƒงแƒแƒ•แƒ”แƒšแƒ—แƒ•แƒ˜แƒก, แƒแƒ›แƒแƒชแƒแƒœแƒแƒ–แƒ”แƒ แƒ“แƒแƒ›แƒแƒ™แƒ˜แƒ“แƒ”แƒ‘แƒฃแƒšแƒ˜.

แƒฉแƒ•แƒ”แƒœ แƒ“แƒแƒ•แƒแƒ›แƒแƒขแƒ”แƒ‘แƒ— แƒแƒ  แƒ“แƒแƒ›แƒฎแƒ›แƒแƒ แƒ” แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒแƒก: แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒฉแƒแƒ›แƒแƒกแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒแƒ“ แƒ“แƒ แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒ’แƒแƒ“แƒ›แƒแƒกแƒแƒฌแƒ”แƒ แƒแƒ“ แƒ”แƒšแƒคแƒแƒกแƒขแƒ˜แƒก แƒ‘แƒ›แƒฃแƒšแƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒ—. แƒกแƒฎแƒ•แƒแƒ—แƒ แƒจแƒแƒ แƒ˜แƒก, แƒ›แƒแƒ—แƒ˜ แƒ’แƒแƒ“แƒแƒขแƒแƒœแƒ แƒจแƒ”แƒกแƒแƒซแƒšแƒ”แƒ‘แƒ”แƒšแƒ˜แƒ แƒแƒžแƒ”แƒ แƒแƒขแƒแƒ แƒ–แƒ”, แƒ”แƒก แƒ“แƒแƒ›แƒแƒ™แƒ˜แƒ“แƒ”แƒ‘แƒฃแƒšแƒ˜แƒ แƒแƒ› แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒก แƒกแƒ˜แƒฎแƒจแƒ˜แƒ แƒ”แƒ–แƒ”. แƒ™แƒ˜แƒ“แƒ”แƒ• แƒ แƒ แƒฃแƒœแƒ“แƒ แƒ“แƒแƒแƒ›แƒแƒขแƒแƒ— แƒ™แƒแƒฃแƒญแƒก, แƒ™แƒ•แƒšแƒแƒ• แƒ“แƒแƒ›แƒแƒ™แƒ˜แƒ“แƒ”แƒ‘แƒฃแƒšแƒ˜แƒ แƒ“แƒแƒ•แƒแƒšแƒ”แƒ‘แƒแƒ–แƒ”: แƒ—แƒฃ แƒคแƒแƒ˜แƒšแƒ”แƒ‘แƒ˜ แƒ›แƒ˜แƒ˜แƒฆแƒ”แƒ‘แƒ แƒ“แƒแƒฃแƒงแƒแƒ•แƒœแƒ”แƒ‘แƒšแƒ˜แƒ• แƒฌแƒ”แƒ แƒ˜แƒšแƒจแƒ˜, แƒ›แƒแƒจแƒ˜แƒœ แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒฉแƒแƒ›แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒแƒ— แƒฌแƒ”แƒ แƒ˜แƒšแƒ–แƒ” แƒ“แƒแƒœแƒแƒ แƒ—แƒ”แƒ‘แƒ˜, แƒ—แƒฃ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜ แƒ›แƒ˜แƒ˜แƒฆแƒ”แƒ‘แƒ แƒฌแƒ”แƒ แƒ˜แƒšแƒจแƒ˜, แƒ›แƒแƒจแƒ˜แƒœ แƒ—แƒฅแƒ•แƒ”แƒœ แƒฃแƒœแƒ“แƒ แƒ’แƒแƒแƒแƒœแƒแƒšแƒ˜แƒ–แƒแƒ— แƒแƒกแƒ, แƒ“แƒ แƒ.แƒจ. แƒฉแƒ”แƒ›แƒก แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒฌแƒ”แƒ แƒ˜แƒšแƒก แƒ›แƒแƒงแƒ•แƒ”แƒ‘แƒ แƒแƒ แƒฅแƒ˜แƒ•แƒ˜แƒก แƒ”แƒ แƒ—แƒ˜ แƒ‘แƒ›แƒฃแƒšแƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒฃแƒœแƒ“แƒ แƒ“แƒแƒ•แƒแƒงแƒ”แƒœแƒ แƒ’แƒแƒ แƒ™แƒ•แƒ”แƒฃแƒš แƒแƒ“แƒ’แƒ˜แƒšแƒแƒก แƒ“แƒ แƒ“แƒแƒ•แƒ˜แƒฌแƒงแƒ แƒจแƒ”แƒ›แƒ“แƒ’แƒแƒ›แƒ˜ แƒ“แƒแƒ›แƒฃแƒจแƒแƒ•แƒ”แƒ‘แƒ˜แƒก แƒžแƒ แƒแƒชแƒ”แƒกแƒ˜.

    def download_from_url(self, url, path, chunk_size=128):
        """
            ะœะตั‚ะพะด ะดะปั ัะบะฐั‡ะธะฒะฐะฝะธั ั„ะฐะนะปะฐ

            :param url:              ะะดั€ะตั ะทะฐะณั€ัƒะทะบะธ
            :type url:               string
            :param path:             ะšัƒะดะฐ ะฟะพะปะพะถะธั‚ัŒ ั„ะฐะนะป
            :type path:              string
            :param chunk_size:       ะŸะพ ัะบะพะปัŒะบะพ ะฑะฐะนั‚ะพะฒ ะฟะธัะฐั‚ัŒ
            :type chunk_size:        int
        """
        r = requests.get(url, stream=True)
        with open(path, "wb") as fd:
            for chunk in r.iter_content(chunk_size=chunk_size):
                fd.write(chunk)

    def download_mail_href_attachment(self, mail_id, path):
        """
            ะœะตั‚ะพะด ะดะปั ัะบะฐั‡ะธะฒะฐะฝะธั ั„ะฐะนะปะฐ ะฟะพ ััั‹ะปะบะต ะธะท ะฟะธััŒะผะฐ

            :param mail_id:         ะ˜ะดะตะฝั‚ะธั„ะธะบะฐั‚ะพั€ ะฟะธััŒะผะฐ
            :type mail_id:          string
            :param path:            ะšัƒะดะฐ ะฟะพะปะพะถะธั‚ัŒ ั„ะฐะนะป
            :type path:             string
        """
        response, data = self.mail.fetch(mail_id, "(RFC822)")
        raw_email = data[0][1]
        raw_soup = raw_email.decode().replace("r", "").replace("n", "")
        parse_soup = BeautifulSoup(raw_soup, "html.parser")
        link_text = ""

        for a in parse_soup.find_all("a", href=True, text=True):
            link_text = a["href"]

        self.download_from_url(link_text, path)

แƒ™แƒแƒ“แƒ˜ แƒ›แƒแƒ แƒขแƒ˜แƒ•แƒ˜แƒ, แƒแƒ›แƒ˜แƒขแƒแƒ› แƒ›แƒแƒก แƒแƒ  แƒกแƒญแƒ˜แƒ แƒ“แƒ”แƒ‘แƒ แƒ“แƒแƒ›แƒแƒขแƒ”แƒ‘แƒ˜แƒ—แƒ˜ แƒแƒฎแƒกแƒœแƒ. แƒ›แƒ” แƒฃแƒ‘แƒ แƒแƒšแƒแƒ“ แƒ’แƒ”แƒขแƒงแƒ•แƒ˜แƒ— แƒฏแƒแƒ“แƒแƒกแƒœแƒฃแƒ แƒ˜ แƒฎแƒแƒ–แƒ˜แƒก imap_conn_id. Apache Airflow แƒ˜แƒœแƒแƒฎแƒแƒ•แƒก แƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ˜แƒก แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ”แƒ‘แƒก (แƒจแƒ”แƒกแƒ•แƒšแƒ, แƒžแƒแƒ แƒแƒšแƒ˜, แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ˜ แƒ“แƒ แƒกแƒฎแƒ•แƒ แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ”แƒ‘แƒ˜), แƒ แƒแƒ›แƒšแƒ”แƒ‘แƒ–แƒ”แƒช แƒฌแƒ•แƒ“แƒแƒ›แƒ แƒจแƒ”แƒกแƒแƒซแƒšแƒ”แƒ‘แƒ”แƒšแƒ˜แƒ แƒกแƒ˜แƒ›แƒ”แƒ‘แƒ˜แƒแƒœแƒ˜ แƒ˜แƒ“แƒ”แƒœแƒขแƒ˜แƒคแƒ˜แƒ™แƒแƒขแƒแƒ แƒ˜แƒ—. แƒ•แƒ˜แƒ–แƒฃแƒแƒšแƒฃแƒ แƒแƒ“, แƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ˜แƒก แƒ›แƒ”แƒœแƒ”แƒฏแƒ›แƒ”แƒœแƒขแƒ˜ แƒแƒกแƒ” แƒ’แƒแƒ›แƒแƒ˜แƒงแƒฃแƒ แƒ”แƒ‘แƒ

ETL แƒžแƒ แƒแƒชแƒ”แƒกแƒ˜ แƒ”แƒšแƒคแƒแƒกแƒขแƒ˜แƒ“แƒแƒœ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒกแƒแƒฆแƒ”แƒ‘แƒแƒ“ Apache Airflow-แƒจแƒ˜

แƒกแƒ”แƒœแƒกแƒแƒ แƒ˜ แƒ”แƒšแƒแƒ“แƒ”แƒ‘แƒ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒก

แƒ•แƒ˜แƒœแƒแƒ˜แƒ“แƒแƒœ แƒฉแƒ•แƒ”แƒœ แƒฃแƒ™แƒ•แƒ” แƒ•แƒ˜แƒชแƒ˜แƒ— แƒ แƒแƒ’แƒแƒ  แƒ“แƒแƒ•แƒแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒแƒ— แƒ“แƒ แƒ›แƒ˜แƒ•แƒ˜แƒฆแƒแƒ— แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜ แƒคแƒแƒกแƒขแƒ˜แƒ“แƒแƒœ, แƒแƒฎแƒšแƒ แƒจแƒ”แƒ’แƒ•แƒ˜แƒซแƒšแƒ˜แƒ แƒ“แƒแƒ•แƒฌแƒ”แƒ แƒแƒ— แƒกแƒ”แƒœแƒกแƒแƒ แƒ˜, แƒ แƒแƒ› แƒ“แƒแƒ•แƒ”แƒšแƒแƒ“แƒแƒ— แƒ›แƒแƒ—. แƒฉแƒ”แƒ›แƒก แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒแƒ  แƒ’แƒแƒ›แƒแƒ“แƒ’แƒ”แƒ‘แƒ แƒแƒžแƒ”แƒ แƒแƒขแƒแƒ แƒ˜แƒก แƒ“แƒแƒฃแƒงแƒแƒ•แƒœแƒ”แƒ‘แƒšแƒแƒ“ แƒ“แƒแƒฌแƒ”แƒ แƒ, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒ“แƒแƒแƒ›แƒฃแƒจแƒแƒ•แƒ”แƒ‘แƒก แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒก, แƒแƒกแƒ”แƒ—แƒ˜แƒก แƒแƒ แƒกแƒ”แƒ‘แƒแƒ‘แƒ˜แƒก แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒ แƒแƒ“แƒ’แƒแƒœ แƒกแƒฎแƒ•แƒ แƒžแƒ แƒแƒชแƒ”แƒกแƒ”แƒ‘แƒ˜ แƒ›แƒฃแƒจแƒแƒแƒ‘แƒก แƒคแƒแƒกแƒขแƒ˜แƒ“แƒแƒœ แƒ›แƒ˜แƒฆแƒ”แƒ‘แƒฃแƒš แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ–แƒ” แƒ“แƒแƒงแƒ แƒ“แƒœแƒแƒ‘แƒ˜แƒ—, แƒ›แƒแƒ— แƒจแƒแƒ แƒ˜แƒก แƒ˜แƒกแƒ”แƒ—แƒ”แƒ‘แƒ˜แƒช, แƒ แƒแƒ›แƒšแƒ”แƒ‘แƒ˜แƒช แƒ˜แƒฆแƒ”แƒ‘แƒ”แƒœ แƒจแƒ”แƒกแƒแƒ‘แƒแƒ›แƒ˜แƒก แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒก แƒกแƒฎแƒ•แƒ แƒฌแƒงแƒแƒ แƒแƒ”แƒ‘แƒ˜แƒ“แƒแƒœ (API, แƒขแƒ”แƒšแƒ”แƒคแƒแƒœแƒ˜แƒ). , แƒ•แƒ”แƒ‘ แƒ›แƒ”แƒขแƒ แƒ˜แƒ™แƒ แƒ“แƒ แƒ.แƒจ.) แƒ“แƒ แƒ.แƒจ.). แƒ›แƒแƒ’แƒแƒšแƒ˜แƒ—แƒก แƒ›แƒแƒ’แƒ˜แƒงแƒ•แƒแƒœ. CRM แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒแƒจแƒ˜ แƒแƒฎแƒแƒšแƒ˜ แƒ›แƒแƒ›แƒฎแƒ›แƒแƒ แƒ”แƒ‘แƒ”แƒšแƒ˜ แƒ’แƒแƒ›แƒแƒฉแƒœแƒ“แƒ แƒ“แƒ แƒ›แƒ˜แƒกแƒ˜ UUID-แƒ˜แƒก แƒจแƒ”แƒกแƒแƒฎแƒ”แƒ‘ แƒฏแƒ”แƒ  แƒ™แƒ˜แƒ“แƒ”แƒ• แƒแƒ  แƒ•แƒ˜แƒชแƒ˜แƒ—. แƒจแƒ”แƒ›แƒ“แƒ”แƒ’, แƒ แƒแƒ“แƒ”แƒกแƒแƒช แƒ•แƒชแƒ“แƒ˜แƒšแƒแƒ‘แƒ— แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒฆแƒ”แƒ‘แƒแƒก SIP แƒขแƒ”แƒšแƒ”แƒคแƒแƒœแƒ˜แƒ“แƒแƒœ, แƒ›แƒ˜แƒ•แƒ˜แƒฆแƒ”แƒ‘แƒ— แƒ›แƒ˜แƒก UUID-แƒ—แƒแƒœ แƒ“แƒแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ”แƒ‘แƒฃแƒš แƒ–แƒแƒ แƒ”แƒ‘แƒก, แƒ›แƒแƒ’แƒ แƒแƒ› แƒ•แƒ”แƒ  แƒจแƒ”แƒ•แƒซแƒšแƒ”แƒ‘แƒ— แƒ›แƒแƒ— แƒกแƒฌแƒแƒ แƒแƒ“ แƒจแƒ”แƒœแƒแƒฎแƒ•แƒแƒก แƒ“แƒ แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒแƒก. แƒแƒกแƒ”แƒ— แƒกแƒแƒ™แƒ˜แƒ—แƒฎแƒ”แƒ‘แƒจแƒ˜ แƒ›แƒœแƒ˜แƒจแƒ•แƒœแƒ”แƒšแƒแƒ•แƒแƒœแƒ˜แƒ แƒ’แƒแƒ•แƒ˜แƒ—แƒ•แƒแƒšแƒ˜แƒกแƒฌแƒ˜แƒœแƒแƒ— แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ“แƒแƒ›แƒแƒ™แƒ˜แƒ“แƒ”แƒ‘แƒฃแƒšแƒ”แƒ‘แƒ, แƒ’แƒแƒœแƒกแƒแƒ™แƒฃแƒ—แƒ แƒ”แƒ‘แƒ˜แƒ— แƒ—แƒฃ แƒ˜แƒกแƒ˜แƒœแƒ˜ แƒกแƒฎแƒ•แƒแƒ“แƒแƒกแƒฎแƒ•แƒ แƒฌแƒงแƒแƒ แƒแƒ“แƒแƒœ แƒแƒ แƒ˜แƒแƒœ. แƒ”แƒก, แƒ แƒ แƒ—แƒฅแƒ›แƒ แƒฃแƒœแƒ“แƒ, แƒแƒ แƒแƒกแƒแƒ™แƒ›แƒแƒ แƒ˜แƒกแƒ˜ แƒ–แƒแƒ›แƒ”แƒ‘แƒ˜แƒ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒ›แƒ—แƒšแƒ˜แƒแƒœแƒแƒ‘แƒ˜แƒก แƒจแƒ”แƒกแƒแƒœแƒแƒ แƒฉแƒฃแƒœแƒ”แƒ‘แƒšแƒแƒ“, แƒ›แƒแƒ’แƒ แƒแƒ› แƒ–แƒแƒ’แƒ˜แƒ”แƒ แƒ— แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜ แƒ˜แƒกแƒ˜แƒœแƒ˜ แƒแƒฃแƒชแƒ˜แƒšแƒ”แƒ‘แƒ”แƒšแƒ˜แƒ. แƒ“แƒ˜แƒแƒฎ, แƒ“แƒ แƒ แƒ”แƒกแƒฃแƒ แƒกแƒ”แƒ‘แƒ˜แƒก แƒ“แƒแƒกแƒแƒ™แƒแƒ•แƒ”แƒ‘แƒšแƒแƒ“ แƒฃแƒกแƒแƒฅแƒ›แƒฃแƒ แƒแƒ‘แƒ แƒแƒกแƒ”แƒ•แƒ” แƒ˜แƒ แƒแƒชแƒ˜แƒแƒœแƒแƒšแƒฃแƒ แƒ˜แƒ.

แƒแƒ›แƒ แƒ˜แƒ’แƒแƒ“, แƒฉแƒ•แƒ”แƒœแƒ˜ แƒกแƒ”แƒœแƒกแƒแƒ แƒ˜ แƒ’แƒแƒ›แƒแƒฃแƒจแƒ•แƒ”แƒ‘แƒก แƒ’แƒ แƒแƒคแƒ˜แƒ™แƒ˜แƒก แƒจแƒ”แƒ›แƒ“แƒ’แƒแƒ› แƒฌแƒ•แƒ”แƒ แƒแƒ”แƒ‘แƒก, แƒ—แƒฃ แƒคแƒแƒกแƒขแƒแƒจแƒ˜ แƒแƒ แƒ˜แƒก แƒแƒฎแƒแƒšแƒ˜ แƒ˜แƒœแƒคแƒแƒ แƒ›แƒแƒชแƒ˜แƒ แƒ“แƒ แƒแƒกแƒ”แƒ•แƒ” แƒแƒฆแƒœแƒ˜แƒจแƒœแƒแƒ•แƒก แƒฌแƒ˜แƒœแƒ แƒ˜แƒœแƒคแƒแƒ แƒ›แƒแƒชแƒ˜แƒแƒก, แƒ แƒแƒ’แƒแƒ แƒช แƒจแƒ”แƒฃแƒกแƒแƒ‘แƒแƒ›แƒ.

from airflow.sensors.base_sensor_operator import BaseSensorOperator
from airflow.utils.decorators import apply_defaults
from my_plugin.hooks.imap_hook import IMAPHook

class MailSensor(BaseSensorOperator):
    @apply_defaults
    def __init__(self, conn_id, check_seen=True, box="Inbox", condition="(UNSEEN)", *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.conn_id = conn_id
        self.check_seen = check_seen
        self.box = box
        self.condition = condition

    def poke(self, context):
        conn = IMAPHook(self.conn_id)
        mail_id = conn.get_last_mail(check_seen=self.check_seen, box=self.box, condition=self.condition)

        if mail_id is None:
            return False
        else:
            return True

แƒฉแƒ•แƒ”แƒœ แƒ•แƒ˜แƒฆแƒ”แƒ‘แƒ— แƒ“แƒ แƒ•แƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ— แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒก

แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒกแƒแƒฆแƒ”แƒ‘แƒแƒ“ แƒ“แƒ แƒ“แƒแƒกแƒแƒ›แƒฃแƒจแƒแƒ•แƒ”แƒ‘แƒšแƒแƒ“ แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒ“แƒแƒฌแƒ”แƒ แƒแƒ— แƒชแƒแƒšแƒ™แƒ” แƒแƒžแƒ”แƒ แƒแƒขแƒแƒ แƒ˜, แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒ’แƒแƒ›แƒแƒ˜แƒงแƒ”แƒœแƒแƒ— แƒ›แƒ–แƒ. แƒ•แƒ˜แƒœแƒแƒ˜แƒ“แƒแƒœ แƒšแƒแƒ’แƒ˜แƒ™แƒ แƒฏแƒ”แƒ  แƒ™แƒ˜แƒ“แƒ”แƒ• แƒขแƒ แƒ˜แƒ•แƒ˜แƒแƒšแƒฃแƒ แƒ˜แƒ - แƒ›แƒแƒ’แƒแƒšแƒ˜แƒ—แƒแƒ“, แƒแƒกแƒแƒ“แƒแƒœ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒแƒฆแƒ”แƒ‘แƒ, แƒ›แƒ” แƒ’แƒ—แƒแƒ•แƒแƒ–แƒแƒ‘แƒ— แƒกแƒขแƒแƒœแƒ“แƒแƒ แƒขแƒฃแƒš PythonOperator-แƒก.

from airflow.models import DAG

from airflow.operators.python_operator import PythonOperator
from airflow.sensors.my_plugin import MailSensor
from my_plugin.hooks.imap_hook import IMAPHook

start_date = datetime(2020, 4, 4)

# ะกั‚ะฐะฝะดะฐั€ั‚ะฝะพะต ะบะพะฝั„ะธะณัƒั€ะธั€ะพะฒะฐะฝะธะต ะณั€ะฐั„ะฐ
args = {
    "owner": "example",
    "start_date": start_date,
    "email": ["[email protected]"],
    "email_on_failure": False,
    "email_on_retry": False,
    "retry_delay": timedelta(minutes=15),
    "provide_context": False,
}

dag = DAG(
    dag_id="test_etl",
    default_args=args,
    schedule_interval="@hourly",
)

# ะžะฟั€ะตะดะตะปัะตะผ ัะตะฝัะพั€
mail_check_sensor = MailSensor(
    task_id="check_new_emails",
    poke_interval=10,
    conn_id="mail_conn_id",
    timeout=10,
    soft_fail=True,
    box="my_box",
    dag=dag,
    mode="poke",
)

# ะคัƒะฝะบั†ะธั ะดะปั ะฟะพะปัƒั‡ะตะฝะธั ะดะฐะฝะฝั‹ั… ะธะท ะฟะธััŒะผะฐ
def prepare_mail():
    imap_hook = IMAPHook("mail_conn_id")
    mail_id = imap_hook.get_last_mail(check_seen=True, box="my_box")
    if mail_id is None:
        raise AirflowException("Empty mailbox")

    conn.download_mail_href_attachment(mail_id, "./path.zip")

prepare_mail_data = PythonOperator(task_id="prepare_mail_data", default_args=args, dag=dag, python_callable= prepare_mail)

# ะžะฟะธัะฐะฝะธะต ะพัั‚ะฐะปัŒะฝั‹ั… ะฒะตั€ัˆะธะฝ ะณั€ะฐั„ะฐ
...

# ะ—ะฐะดะฐะตะผ ัะฒัะทัŒ ะฝะฐ ะณั€ะฐั„ะต
mail_check_sensor >> prepare_mail_data
prepare_data >> ...
# ะžะฟะธัะฐะฝะธะต ะพัั‚ะฐะปัŒะฝั‹ั… ะฟะพั‚ะพะบะพะฒ ัƒะฟั€ะฐะฒะปะตะฝะธั

แƒกแƒฎแƒ•แƒแƒ—แƒ แƒจแƒแƒ แƒ˜แƒก, แƒ—แƒฃ แƒ—แƒฅแƒ•แƒ”แƒœแƒ˜ แƒ™แƒแƒ แƒžแƒแƒ แƒแƒขแƒ˜แƒฃแƒšแƒ˜ แƒคแƒแƒกแƒขแƒ แƒแƒกแƒ”แƒ•แƒ” แƒแƒ แƒ˜แƒก mail.ru-แƒ–แƒ”, แƒ›แƒแƒจแƒ˜แƒœ แƒ•แƒ”แƒ  แƒจแƒ”แƒซแƒšแƒ”แƒ‘แƒ— แƒฌแƒ”แƒ แƒ˜แƒšแƒ”แƒ‘แƒ˜แƒก แƒ›แƒแƒซแƒ˜แƒ”แƒ‘แƒแƒก แƒกแƒแƒ’แƒœแƒ˜แƒก, แƒ’แƒแƒ›แƒ’แƒ–แƒแƒ•แƒœแƒ˜แƒก แƒ“แƒ แƒ.แƒจ. แƒฏแƒ”แƒ  แƒ™แƒ˜แƒ“แƒ”แƒ• 2016 แƒฌแƒ”แƒšแƒก แƒ“แƒแƒฐแƒžแƒ˜แƒ แƒ“แƒœแƒ”แƒœ แƒ›แƒ˜แƒก แƒ“แƒแƒœแƒ”แƒ แƒ’แƒ•แƒแƒก, แƒ›แƒแƒ’แƒ แƒแƒ›, แƒ แƒแƒ’แƒแƒ แƒช แƒฉแƒแƒœแƒก, แƒ’แƒแƒ“แƒแƒ˜แƒคแƒ˜แƒฅแƒ แƒ”แƒก. แƒ›แƒ” แƒ’แƒแƒ“แƒแƒ•แƒฌแƒงแƒ•แƒ˜แƒขแƒ” แƒ”แƒก แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ แƒกแƒแƒญแƒ˜แƒ แƒ แƒแƒกแƒแƒ”แƒ‘แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก แƒชแƒแƒšแƒ™แƒ” แƒกแƒแƒฅแƒแƒฆแƒแƒšแƒ“แƒ˜แƒก แƒจแƒ”แƒฅแƒ›แƒœแƒ˜แƒ— แƒ“แƒ แƒคแƒแƒกแƒขแƒ˜แƒก แƒ•แƒ”แƒ‘ แƒ˜แƒœแƒขแƒ”แƒ แƒคแƒ”แƒ˜แƒกแƒจแƒ˜ แƒกแƒแƒญแƒ˜แƒ แƒ แƒแƒกแƒแƒ”แƒ‘แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก แƒคแƒ˜แƒšแƒขแƒ แƒ˜แƒก แƒ“แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒ—. แƒแƒ›แƒ แƒ˜แƒ’แƒแƒ“, แƒแƒ› แƒกแƒแƒฅแƒแƒฆแƒแƒšแƒ“แƒ”แƒจแƒ˜ แƒ›แƒฎแƒแƒšแƒแƒ“ แƒซแƒ˜แƒ”แƒ‘แƒ˜แƒก แƒกแƒแƒญแƒ˜แƒ แƒ แƒแƒกแƒแƒ”แƒ‘แƒ˜ แƒ“แƒ แƒžแƒ˜แƒ แƒแƒ‘แƒ”แƒ‘แƒ˜, แƒฉแƒ”แƒ›แƒก แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒฃแƒ‘แƒ แƒแƒšแƒแƒ“ (แƒ’แƒแƒฃแƒ แƒ™แƒ•แƒ”แƒ•แƒ”แƒšแƒ˜แƒ).

แƒจแƒ”แƒฏแƒแƒ›แƒ”แƒ‘แƒ˜แƒ—, แƒ’แƒ•แƒแƒฅแƒ•แƒก แƒจแƒ”แƒ›แƒ“แƒ”แƒ’แƒ˜ แƒ—แƒแƒœแƒ›แƒ˜แƒ›แƒ“แƒ”แƒ•แƒ แƒแƒ‘แƒ: แƒ•แƒแƒ›แƒแƒฌแƒ›แƒ”แƒ‘แƒ— แƒแƒ แƒ˜แƒก แƒ—แƒฃ แƒแƒ แƒ แƒแƒฎแƒแƒšแƒ˜ แƒแƒกแƒแƒ”แƒ‘แƒ˜, แƒ แƒแƒ›แƒšแƒ”แƒ‘แƒ˜แƒช แƒแƒ™แƒ›แƒแƒงแƒแƒคแƒ˜แƒšแƒ”แƒ‘แƒ”แƒœ แƒžแƒ˜แƒ แƒแƒ‘แƒ”แƒ‘แƒก, แƒ—แƒฃ แƒแƒ แƒ˜แƒก, แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒฉแƒแƒ›แƒแƒ•แƒขแƒ•แƒ˜แƒ แƒ—แƒแƒ•แƒ— แƒแƒ แƒฅแƒ˜แƒ•แƒก แƒ‘แƒแƒšแƒ แƒแƒกแƒแƒ“แƒแƒœ แƒ‘แƒ›แƒฃแƒšแƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒ—.
แƒ‘แƒแƒšแƒ แƒฌแƒ”แƒ แƒขแƒ˜แƒšแƒ”แƒ‘แƒ˜แƒก แƒฅแƒ•แƒ”แƒจ แƒ’แƒแƒ›แƒแƒขแƒแƒ•แƒ”แƒ‘แƒฃแƒšแƒ˜แƒ, แƒ แƒแƒ› แƒ”แƒก แƒแƒ แƒฅแƒ˜แƒ•แƒ˜ แƒ’แƒแƒ˜แƒฎแƒกแƒœแƒ”แƒ‘แƒ, แƒแƒ แƒฅแƒ˜แƒ•แƒ˜แƒ“แƒแƒœ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜ แƒ’แƒแƒกแƒฃแƒคแƒ—แƒแƒ•แƒ“แƒ”แƒ‘แƒ แƒ“แƒ แƒ“แƒแƒ›แƒฃแƒจแƒแƒ•แƒ“แƒ”แƒ‘แƒ แƒ“แƒ แƒจแƒ”แƒ“แƒ”แƒ’แƒแƒ“, แƒงแƒ•แƒ”แƒšแƒแƒคแƒ”แƒ แƒ˜ แƒฃแƒคแƒ แƒ แƒจแƒแƒ แƒก แƒฌแƒแƒ•แƒ ETL แƒžแƒ แƒแƒชแƒ”แƒกแƒ˜แƒก แƒ›แƒ˜แƒšแƒกแƒแƒ“แƒ”แƒœแƒแƒ›แƒ“แƒ”, แƒ›แƒแƒ’แƒ แƒแƒ› แƒ”แƒก แƒฃแƒ™แƒ•แƒ” แƒกแƒชแƒ˜แƒšแƒ“แƒ”แƒ‘แƒ. แƒกแƒขแƒแƒขแƒ˜แƒ˜แƒก แƒคแƒแƒ แƒ’แƒšแƒ”แƒ‘แƒ˜. แƒ—แƒฃ แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒ แƒ“แƒ แƒกแƒแƒกแƒแƒ แƒ’แƒ”แƒ‘แƒšแƒ แƒแƒฆแƒ›แƒแƒฉแƒœแƒ“แƒ, แƒ›แƒแƒจแƒ˜แƒœ แƒ›แƒ” แƒกแƒ˜แƒแƒ›แƒแƒ•แƒœแƒ”แƒ‘แƒ˜แƒ— แƒ’แƒแƒ•แƒแƒ’แƒ แƒซแƒ”แƒšแƒ”แƒ‘ ETL แƒ’แƒแƒ“แƒแƒฌแƒงแƒ•แƒ”แƒขแƒ˜แƒšแƒ”แƒ‘แƒ”แƒ‘แƒ˜แƒก แƒ“แƒ แƒ›แƒแƒ—แƒ˜ แƒœแƒแƒฌแƒ˜แƒšแƒ”แƒ‘แƒ˜แƒก แƒแƒฆแƒฌแƒ”แƒ แƒแƒก Apache Airflow-แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก.

แƒฌแƒงแƒแƒ แƒ: www.habr.com

แƒแƒฎแƒแƒšแƒ˜ แƒ™แƒแƒ›แƒ”แƒœแƒขแƒแƒ แƒ˜แƒก แƒ“แƒแƒ›แƒแƒขแƒ”แƒ‘แƒ