āĻĒā§āĻ°āĻ¯ā§āĻā§āĻ¤āĻŋ āĻ¯āĻ¤āĻ āĻŦāĻŋāĻāĻļāĻŋāĻ¤ āĻšā§āĻ āĻ¨āĻž āĻā§āĻ¨, āĻĒā§āĻ°āĻžāĻ¨ā§ āĻĒāĻĻā§āĻ§āĻ¤āĻŋāĻ° āĻāĻāĻāĻŋ āĻ¸ā§āĻā§āĻ°āĻŋāĻ āĻ¸āĻ°ā§āĻŦāĻĻāĻž āĻŦāĻŋāĻāĻžāĻļā§āĻ° āĻĒāĻŋāĻāĻ¨ā§ āĻĨāĻžāĻā§āĨ¤ āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻŽāĻ¸ā§āĻŖ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨, āĻŽāĻžāĻ¨ā§āĻˇā§āĻ° āĻāĻžāĻ°āĻŖ, āĻĒā§āĻ°āĻ¯ā§āĻā§āĻ¤āĻŋāĻāĻ¤ āĻāĻžāĻšāĻŋāĻĻāĻž āĻŦāĻž āĻ āĻ¨ā§āĻ¯ āĻāĻŋāĻā§āĻ° āĻāĻžāĻ°āĻŖā§ āĻšāĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤ āĻĄā§āĻāĻž āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻāĻ°āĻŖā§āĻ° āĻā§āĻˇā§āĻ¤ā§āĻ°ā§, āĻĄā§āĻāĻž āĻāĻ¤ā§āĻ¸āĻā§āĻ˛āĻŋ āĻāĻ āĻ āĻāĻļā§ āĻ¸āĻŦāĻā§āĻ¯āĻŧā§ āĻŦā§āĻļāĻŋ āĻĒā§āĻ°āĻāĻžāĻļ āĻāĻ°ā§āĨ¤ āĻāĻŽāĻ°āĻž āĻāĻ° āĻĨā§āĻā§ āĻĒāĻ°āĻŋāĻ¤ā§āĻ°āĻžāĻŖ āĻĒāĻžāĻāĻ¯āĻŧāĻžāĻ° āĻ¸ā§āĻŦāĻĒā§āĻ¨ āĻ¯āĻ¤āĻ āĻĻā§āĻāĻŋ āĻ¨āĻž āĻā§āĻ¨, āĻ¤āĻŦā§ āĻāĻāĻ¨āĻ āĻĒāĻ°ā§āĻ¯āĻ¨ā§āĻ¤ āĻĄā§āĻāĻžāĻ° āĻāĻŋāĻā§ āĻ āĻāĻļ āĻ¤āĻžāĻ¤ā§āĻā§āĻˇāĻŖāĻŋāĻ āĻŦāĻžāĻ°ā§āĻ¤āĻžāĻŦāĻžāĻšāĻ āĻāĻŦāĻ āĻāĻŽā§āĻ˛āĻā§āĻ˛āĻŋāĻ¤ā§ āĻĒā§āĻ°ā§āĻ°āĻŖ āĻāĻ°āĻž āĻšāĻ¯āĻŧ, āĻāĻ°āĻ āĻĒā§āĻ°āĻžāĻā§āĻ¨ āĻŦāĻŋāĻ¨ā§āĻ¯āĻžāĻ¸ā§āĻ° āĻāĻ˛ā§āĻ˛ā§āĻ āĻ¨āĻž āĻāĻ°ā§āĨ¤ āĻāĻŽāĻŋ āĻāĻĒāĻ¨āĻžāĻā§ Apache Airflow āĻāĻ° āĻŦāĻŋāĻāĻ˛ā§āĻĒāĻā§āĻ˛āĻŋāĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻāĻāĻāĻŋāĻā§ āĻŦāĻŋāĻā§āĻāĻŋāĻ¨ā§āĻ¨ āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻŽāĻ¨ā§āĻ¤ā§āĻ°āĻŖ āĻāĻžāĻ¨āĻžāĻā§āĻāĻŋ, āĻāĻĒāĻ¨āĻŋ āĻā§āĻāĻžāĻŦā§ āĻāĻŽā§āĻ˛āĻā§āĻ˛āĻŋ āĻĨā§āĻā§ āĻĄā§āĻāĻž āĻ¨āĻŋāĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨ āĻ¤āĻž āĻŦā§āĻ¯āĻžāĻā§āĻ¯āĻž āĻāĻ°ā§ā§ˇ
āĻĒā§āĻ°āĻžāĻāĻāĻ¤āĻŋāĻšāĻžāĻ¸āĻŋāĻ
āĻāĻ¨ā§āĻ¤āĻāĻŦā§āĻ¯āĻā§āĻ¤āĻŋāĻ āĻ¯ā§āĻāĻžāĻ¯ā§āĻ āĻĨā§āĻā§ āĻā§āĻŽā§āĻĒāĻžāĻ¨āĻŋāĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻāĻ¨ā§āĻāĻžāĻ°āĻ ā§āĻ¯āĻžāĻāĻļāĻ¨ā§āĻ° āĻŽāĻžāĻ¨ āĻĒāĻ°ā§āĻ¯āĻ¨ā§āĻ¤ āĻ āĻ¨ā§āĻ āĻĄā§āĻāĻž āĻāĻāĻ¨āĻ āĻ-āĻŽā§āĻāĻ˛ā§āĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ¨ā§āĻ¤āĻ°āĻŋāĻ¤ āĻšāĻ¯āĻŧāĨ¤ āĻāĻāĻŋ āĻāĻžāĻ˛ āĻ¯āĻĻāĻŋ āĻĄā§āĻāĻž āĻĒāĻžāĻāĻ¯āĻŧāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ āĻāĻ¨ā§āĻāĻžāĻ°āĻĢā§āĻ¸ āĻ˛ā§āĻāĻž āĻ¸āĻŽā§āĻāĻŦ āĻšāĻ¯āĻŧ āĻŦāĻž āĻ āĻĢāĻŋāĻ¸ā§ āĻāĻŽāĻ¨ āĻ˛ā§āĻā§āĻĻā§āĻ° āĻ°āĻžāĻāĻž āĻ¯āĻžāĻ¯āĻŧ āĻ¯āĻžāĻ°āĻž āĻāĻ āĻ¤āĻĨā§āĻ¯āĻāĻŋ āĻāĻ°āĻ āĻ¸ā§āĻŦāĻŋāĻ§āĻžāĻāĻ¨āĻ āĻāĻ¤ā§āĻ¸āĻā§āĻ˛āĻŋāĻ¤ā§ āĻĒā§āĻ°āĻŦā§āĻļ āĻāĻ°āĻŦā§, āĻ¤āĻŦā§ āĻĒā§āĻ°āĻžāĻ¯āĻŧāĻļāĻ āĻāĻāĻŋ āĻ¸āĻŽā§āĻāĻŦ āĻ¨āĻžāĻ āĻšāĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤ āĻāĻŽāĻŋ āĻ¯ā§ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻāĻžāĻāĻāĻŋāĻ° āĻŽā§āĻā§āĻŽā§āĻāĻŋ āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛āĻžāĻŽ āĻ¤āĻž āĻšāĻ˛ āĻā§āĻā§āĻ¯āĻžāĻ¤ āĻ¸āĻŋāĻāĻ°āĻāĻŽ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽāĻāĻŋāĻā§ āĻĄā§āĻāĻž āĻā§āĻĻāĻžāĻŽā§āĻ° āĻ¸āĻžāĻĨā§ āĻāĻŦāĻ āĻ¤āĻžāĻ°āĻĒāĻ°ā§ āĻāĻāĻ˛āĻāĻĒāĻŋ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽā§āĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻāĻ¯ā§āĻā§āĻ¤ āĻāĻ°āĻžāĨ¤ āĻāĻāĻŋ āĻāĻ¤āĻŋāĻšāĻžāĻ¸āĻŋāĻāĻāĻžāĻŦā§ āĻāĻā§āĻā§ āĻ¯ā§ āĻāĻŽāĻžāĻĻā§āĻ° āĻā§āĻŽā§āĻĒāĻžāĻ¨āĻŋāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽā§āĻ° āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻŦā§āĻ¯āĻŦāĻ¸āĻžāĻ° āĻāĻāĻāĻŋ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻāĻ˛āĻžāĻāĻžāĻ¯āĻŧ āĻ¸ā§āĻŦāĻŋāĻ§āĻžāĻāĻ¨āĻ āĻāĻŋāĻ˛āĨ¤ āĻ āĻ¤āĻāĻŦ, āĻ¸āĻŦāĻžāĻ āĻ¸āĻ¤ā§āĻ¯āĻŋāĻ āĻāĻ āĻ¤ā§āĻ¤ā§āĻ¯āĻŧ āĻĒāĻā§āĻˇā§āĻ° āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻĨā§āĻā§ āĻĄā§āĻāĻž āĻĻāĻŋāĻ¯āĻŧā§ āĻāĻžāĻ āĻāĻ°āĻ¤ā§ āĻ¸āĻā§āĻˇāĻŽ āĻšāĻ¤ā§ āĻā§āĻ¯āĻŧā§āĻāĻŋāĻ˛āĨ¤ āĻĒā§āĻ°āĻĨāĻŽāĻ¤, āĻ āĻŦāĻļā§āĻ¯āĻ, āĻāĻāĻāĻŋ āĻā§āĻ˛āĻž API āĻĨā§āĻā§ āĻĄā§āĻāĻž āĻĒāĻžāĻāĻ¯āĻŧāĻžāĻ° āĻ¸āĻŽā§āĻāĻžāĻŦāĻ¨āĻž āĻ āĻ§ā§āĻ¯āĻ¯āĻŧāĻ¨ āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛āĨ¤ āĻĻā§āĻ°ā§āĻāĻžāĻā§āĻ¯āĻŦāĻļāĻ¤, āĻāĻĒāĻŋāĻāĻ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ā§āĻ¯āĻŧ āĻĄā§āĻāĻž āĻĒāĻžāĻāĻ¯āĻŧāĻžāĻā§ āĻāĻāĻžāĻ° āĻāĻ°ā§āĻ¨āĻŋ, āĻāĻŦāĻ, āĻ¸āĻšāĻ āĻāĻĨāĻžāĻ¯āĻŧ, āĻāĻāĻŋ āĻ āĻ¨ā§āĻ āĻāĻĒāĻžāĻ¯āĻŧā§ āĻāĻāĻāĻžāĻŦāĻžāĻāĻāĻž āĻāĻŋāĻ˛, āĻāĻŦāĻ āĻĒā§āĻ°āĻ¯ā§āĻā§āĻ¤āĻŋāĻāĻ¤ āĻ¸āĻšāĻžāĻ¯āĻŧāĻ¤āĻž āĻāĻ°āĻ āĻŦā§āĻ¯āĻžāĻĒāĻ āĻāĻžāĻ°ā§āĻ¯āĻāĻžāĻ°āĻŋāĻ¤āĻž āĻĒā§āĻ°āĻĻāĻžāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻ āĻ°ā§āĻ§ā§āĻ āĻĒāĻĨ āĻĒā§āĻ°āĻŖ āĻāĻ°āĻ¤ā§ āĻāĻžāĻ¯āĻŧāĻ¨āĻŋ āĻŦāĻž āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨āĻŋāĨ¤ āĻāĻŋāĻ¨ā§āĻ¤ā§ āĻāĻ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽāĻāĻŋ āĻĒāĻ°ā§āĻ¯āĻžāĻ¯āĻŧāĻā§āĻ°āĻŽā§ āĻāĻ°ā§āĻāĻžāĻāĻ āĻāĻ¨āĻ˛ā§āĻĄ āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ āĻ˛āĻŋāĻā§āĻ āĻāĻāĻžāĻ°ā§ āĻŽā§āĻ˛ā§āĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻ āĻ¨ā§āĻĒāĻ¸ā§āĻĨāĻŋāĻ¤ āĻĄā§āĻāĻž āĻĒāĻžāĻāĻ¯āĻŧāĻžāĻ° āĻ¸ā§āĻ¯ā§āĻ āĻĒā§āĻ°āĻĻāĻžāĻ¨ āĻāĻ°ā§āĨ¤
āĻāĻāĻŋ āĻāĻ˛ā§āĻ˛ā§āĻ āĻāĻ°āĻž āĻāĻāĻŋāĻ¤ āĻ¯ā§ āĻāĻāĻŋāĻ āĻāĻāĻŽāĻžāĻ¤ā§āĻ° āĻāĻāĻ¨āĻž āĻ¨āĻ¯āĻŧ āĻ¯ā§āĻāĻžāĻ¨ā§ āĻŦā§āĻ¯āĻŦāĻ¸āĻžāĻāĻŋ āĻāĻŽā§āĻ˛ āĻŦāĻž āĻ¤āĻžāĻ¤ā§āĻā§āĻˇāĻŖāĻŋāĻ āĻŽā§āĻ¸ā§āĻā§āĻāĻžāĻ° āĻĨā§āĻā§ āĻĄā§āĻāĻž āĻ¸āĻāĻā§āĻ°āĻš āĻāĻ°āĻ¤ā§ āĻā§āĻ¯āĻŧā§āĻāĻŋāĻ˛āĨ¤ āĻ¯āĻžāĻāĻšā§āĻ, āĻāĻ āĻā§āĻˇā§āĻ¤ā§āĻ°ā§, āĻāĻŽāĻ°āĻž āĻāĻāĻāĻŋ āĻ¤ā§āĻ¤ā§āĻ¯āĻŧ āĻĒāĻā§āĻˇā§āĻ° āĻā§āĻŽā§āĻĒāĻžāĻ¨āĻŋāĻā§ āĻĒā§āĻ°āĻāĻžāĻŦāĻŋāĻ¤ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°āĻŋāĻ¨āĻŋ āĻ¯āĻž āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻāĻāĻāĻžāĻŦā§ āĻĄā§āĻāĻžāĻ° āĻ āĻāĻļ āĻĒā§āĻ°āĻĻāĻžāĻ¨ āĻāĻ°ā§āĨ¤
āĻ ā§āĻ¯āĻžāĻĒāĻžāĻāĻŋ āĻāĻ¯āĻŧāĻžāĻ°āĻĢā§āĻ˛ā§
ETL āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻ¤ā§, āĻāĻŽāĻ°āĻž āĻĒā§āĻ°āĻžāĻ¯āĻŧāĻļāĻ Apache Airflow āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻŋāĨ¤ āĻ¯ā§ āĻĒāĻžāĻ āĻ āĻāĻ āĻĒā§āĻ°āĻ¯ā§āĻā§āĻ¤āĻŋāĻ° āĻ¸āĻžāĻĨā§ āĻ āĻĒāĻ°āĻŋāĻāĻŋāĻ¤ āĻ¤āĻž āĻāĻ°āĻ āĻāĻžāĻ˛āĻāĻžāĻŦā§ āĻŦā§āĻāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ¯ā§ āĻāĻāĻŋ āĻĒā§āĻ°ā§āĻā§āĻˇāĻžāĻĒāĻā§ āĻāĻŦāĻ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖāĻāĻžāĻŦā§ āĻā§āĻŽāĻ¨ āĻĻā§āĻāĻžāĻ¯āĻŧ, āĻāĻŽāĻŋ āĻāĻ¯āĻŧā§āĻāĻāĻŋ āĻĒāĻ°āĻŋāĻāĻžāĻ¯āĻŧāĻ āĻŦāĻ°ā§āĻŖāĻ¨āĻž āĻāĻ°āĻŦāĨ¤
Apache Airflow āĻšāĻ˛ āĻāĻāĻāĻŋ āĻŦāĻŋāĻ¨āĻžāĻŽā§āĻ˛ā§āĻ¯ā§āĻ° āĻĒā§āĻ˛ā§āĻ¯āĻžāĻāĻĢāĻ°ā§āĻŽ āĻ¯āĻž Python-āĻ ETL (Extract-Transform-Loading) āĻĒā§āĻ°āĻ¸ā§āĻ¸ āĻ¤ā§āĻ°āĻŋ, āĻāĻā§āĻ¸āĻŋāĻāĻŋāĻāĻ āĻāĻŦāĻ āĻ¨āĻŋāĻ°ā§āĻā§āĻˇāĻŖ āĻāĻ°āĻ¤ā§ āĻŦā§āĻ¯āĻŦāĻšā§āĻ¤ āĻšāĻ¯āĻŧāĨ¤ āĻŦāĻžāĻ¯āĻŧā§āĻĒā§āĻ°āĻŦāĻžāĻšā§āĻ° āĻŽā§āĻ˛ āĻ§āĻžāĻ°āĻŖāĻž āĻšāĻ˛ āĻāĻāĻāĻŋ āĻ¨āĻŋāĻ°ā§āĻĻā§āĻļāĻŋāĻ¤ āĻ ā§āĻ¯āĻžāĻ¸āĻžāĻāĻā§āĻ˛āĻŋāĻ āĻā§āĻ°āĻžāĻĢ, āĻ¯ā§āĻāĻžāĻ¨ā§ āĻā§āĻ°āĻžāĻĢā§āĻ° āĻļā§āĻ°ā§āĻˇāĻŦāĻŋāĻ¨ā§āĻĻā§āĻā§āĻ˛āĻŋ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻāĻŦāĻ āĻā§āĻ°āĻžāĻĢā§āĻ° āĻĒā§āĻ°āĻžāĻ¨ā§āĻ¤āĻā§āĻ˛āĻŋ āĻ¨āĻŋāĻ¯āĻŧāĻ¨ā§āĻ¤ā§āĻ°āĻŖ āĻŦāĻž āĻ¤āĻĨā§āĻ¯ā§āĻ° āĻĒā§āĻ°āĻŦāĻžāĻšāĨ¤ āĻāĻāĻāĻŋ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¸āĻšāĻāĻāĻžāĻŦā§ āĻ¯ā§āĻā§āĻ¨ āĻĒāĻžāĻāĻĨāĻ¨ āĻĢāĻžāĻāĻļāĻ¨āĻā§ āĻāĻ˛ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§, āĻ āĻĨāĻŦāĻž āĻāĻāĻāĻŋ āĻā§āĻ˛āĻžāĻ¸ā§āĻ° āĻĒā§āĻ°ā§āĻā§āĻˇāĻžāĻĒāĻā§ āĻā§āĻ°āĻŽāĻžāĻ¨ā§āĻ¸āĻžāĻ°ā§ āĻŦā§āĻļ āĻāĻ¯āĻŧā§āĻāĻāĻŋ āĻĢāĻžāĻāĻļāĻ¨āĻā§ āĻāĻ˛ āĻāĻ°āĻž āĻĨā§āĻā§ āĻāĻ°āĻ āĻāĻāĻŋāĻ˛ āĻ¯ā§āĻā§āĻ¤āĻŋ āĻĨāĻžāĻāĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤ āĻ¸āĻ°ā§āĻŦāĻžāĻ§āĻŋāĻ āĻāĻ¨ āĻāĻ¨ āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻāĻ˛āĻžāĻĒā§āĻ° āĻāĻ¨ā§āĻ¯, āĻāĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§āĻ āĻ āĻ¨ā§āĻāĻā§āĻ˛āĻŋ āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤-āĻ¤ā§āĻ°āĻŋ āĻāĻ¨ā§āĻ¨āĻ¯āĻŧāĻ¨ āĻ°āĻ¯āĻŧā§āĻā§ āĻ¯āĻž āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻšāĻŋāĻ¸āĻžāĻŦā§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻž āĻ¯ā§āĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤ āĻāĻ āĻ§āĻ°āĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¨āĻ¯āĻŧāĻ¨ āĻ āĻ¨ā§āĻ¤āĻ°ā§āĻā§āĻā§āĻ¤:
- āĻ āĻĒāĻžāĻ°ā§āĻāĻ° - āĻāĻ āĻāĻžāĻ¯āĻŧāĻāĻž āĻĨā§āĻā§ āĻ āĻ¨ā§āĻ¯ āĻāĻžāĻ¯āĻŧāĻāĻžāĻ¯āĻŧ āĻĄā§āĻāĻž āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ¨ā§āĻ¤āĻ° āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯, āĻāĻĻāĻžāĻšāĻ°āĻŖāĻ¸ā§āĻŦāĻ°ā§āĻĒ, āĻāĻāĻāĻŋ āĻĄāĻžāĻāĻžāĻŦā§āĻ¸ āĻā§āĻŦāĻŋāĻ˛ āĻĨā§āĻā§ āĻĄā§āĻāĻž āĻā§āĻĻāĻžāĻŽā§;
- āĻ¸ā§āĻ¨ā§āĻ¸āĻ° - āĻāĻāĻāĻŋ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻāĻāĻ¨āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ āĻĒā§āĻā§āĻˇāĻž āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻŦāĻ āĻā§āĻ°āĻžāĻĢā§āĻ° āĻĒāĻ°āĻŦāĻ°ā§āĻ¤ā§ āĻļā§āĻ°ā§āĻˇā§ āĻ¨āĻŋāĻ¯āĻŧāĻ¨ā§āĻ¤ā§āĻ°āĻŖā§āĻ° āĻĒā§āĻ°āĻŦāĻžāĻšāĻā§ āĻ¨āĻŋāĻ°ā§āĻĻā§āĻļ āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯;
- āĻšā§āĻ - āĻ¨āĻŋāĻŽā§āĻ¨-āĻ¸ā§āĻ¤āĻ°ā§āĻ° āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻāĻ˛āĻžāĻĒā§āĻ° āĻāĻ¨ā§āĻ¯, āĻāĻĻāĻžāĻšāĻ°āĻŖāĻ¸ā§āĻŦāĻ°ā§āĻĒ, āĻāĻāĻāĻŋ āĻĄāĻžāĻāĻžāĻŦā§āĻ¸ āĻā§āĻŦāĻŋāĻ˛ āĻĨā§āĻā§ āĻĄā§āĻāĻž āĻĒā§āĻ¤ā§ (āĻŦāĻŋāĻŦā§āĻ¤āĻŋāĻ¤ā§ āĻŦā§āĻ¯āĻŦāĻšā§āĻ¤ āĻšāĻ¯āĻŧ);
- āĻāĻŦāĻ āĻ¤āĻžāĻ āĻ āĻ¨
āĻāĻ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ā§ Apache Airflow āĻŦāĻŋāĻ¸ā§āĻ¤āĻžāĻ°āĻŋāĻ¤āĻāĻžāĻŦā§ āĻŦāĻ°ā§āĻŖāĻ¨āĻž āĻāĻ°āĻž āĻ
āĻ¨ā§āĻāĻŋāĻ¤ āĻšāĻŦā§āĨ¤ āĻ¸āĻāĻā§āĻˇāĻŋāĻĒā§āĻ¤ āĻā§āĻŽāĻŋāĻāĻž āĻĻā§āĻāĻž āĻ¯ā§āĻ¤ā§ āĻĒāĻžāĻ°ā§
āĻĄā§āĻāĻž āĻĒāĻžāĻāĻ¯āĻŧāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻšā§āĻ
āĻĒā§āĻ°āĻĨāĻŽāĻ¤, āĻ¸āĻŽāĻ¸ā§āĻ¯āĻž āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯, āĻāĻŽāĻžāĻĻā§āĻ° āĻāĻāĻāĻŋ āĻšā§āĻ āĻ˛āĻŋāĻāĻ¤ā§ āĻšāĻŦā§ āĻ¯āĻžāĻ° āĻ¸āĻžāĻšāĻžāĻ¯ā§āĻ¯ā§ āĻāĻŽāĻ°āĻž āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°āĻŋ:
- āĻāĻŽā§āĻ˛ā§āĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻāĻ¯ā§āĻ āĻāĻ°ā§āĻ¨
- āĻ¸āĻ āĻŋāĻ āĻāĻŋāĻ āĻŋ āĻā§āĻāĻā§āĻ¨
- āĻāĻŋāĻ āĻŋ āĻĨā§āĻā§ āĻ¤āĻĨā§āĻ¯ āĻā§āĻ°āĻšāĻŖ.
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 āĻ¸āĻāĻ¯ā§āĻ āĻĒāĻ°āĻžāĻŽāĻŋāĻ¤āĻŋ (āĻ˛āĻāĻāĻ¨, āĻĒāĻžāĻ¸āĻāĻ¯āĻŧāĻžāĻ°ā§āĻĄ, āĻ āĻŋāĻāĻžāĻ¨āĻž āĻāĻŦāĻ āĻ āĻ¨ā§āĻ¯āĻžāĻ¨ā§āĻ¯ āĻĒāĻ°āĻžāĻŽāĻŋāĻ¤āĻŋ) āĻ¸āĻā§āĻāĻ¯āĻŧ āĻāĻ°ā§ āĻ¯āĻž āĻāĻāĻāĻŋ āĻ¸ā§āĻā§āĻ°āĻŋāĻ āĻļāĻ¨āĻžāĻā§āĻ¤āĻāĻžāĻ°ā§ āĻĻā§āĻŦāĻžāĻ°āĻž āĻ ā§āĻ¯āĻžāĻā§āĻ¸ā§āĻ¸ āĻāĻ°āĻž āĻ¯ā§āĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤ āĻĻā§āĻļā§āĻ¯āĻ¤, āĻ¸āĻāĻ¯ā§āĻ āĻŦā§āĻ¯āĻŦāĻ¸ā§āĻĨāĻžāĻĒāĻ¨āĻž āĻāĻ āĻŽāĻ¤ āĻĻā§āĻāĻžāĻ¯āĻŧ
āĻ¤āĻĨā§āĻ¯ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻ āĻĒā§āĻā§āĻˇāĻž āĻāĻ°āĻ¤ā§ āĻ¸ā§āĻ¨ā§āĻ¸āĻ°
āĻ¯ā§āĻšā§āĻ¤ā§ āĻāĻŽāĻ°āĻž āĻāĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§āĻ āĻāĻžāĻ¨āĻŋ āĻāĻŋāĻāĻžāĻŦā§ āĻŽā§āĻ˛ āĻĨā§āĻā§ āĻĄā§āĻāĻž āĻ¸āĻāĻ¯ā§āĻ āĻāĻŦāĻ āĻā§āĻ°āĻšāĻŖ āĻāĻ°āĻ¤ā§ āĻšāĻ¯āĻŧ, āĻ¤āĻžāĻ āĻāĻŽāĻ°āĻž āĻāĻāĻ¨ āĻ¤āĻžāĻĻā§āĻ° āĻāĻ¨ā§āĻ¯ āĻ āĻĒā§āĻā§āĻˇāĻž āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ āĻ¸ā§āĻ¨ā§āĻ¸āĻ° āĻ˛āĻŋāĻāĻ¤ā§ āĻĒāĻžāĻ°āĻŋāĨ¤ āĻāĻŽāĻžāĻ° āĻā§āĻˇā§āĻ¤ā§āĻ°ā§, āĻ āĻŦāĻŋāĻ˛āĻŽā§āĻŦā§ āĻāĻāĻāĻŋ āĻ āĻĒāĻžāĻ°ā§āĻāĻ° āĻ˛ā§āĻāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻžāĻ āĻāĻ°ā§āĻ¨āĻŋ āĻ¯ā§āĻāĻŋ āĻĄā§āĻāĻž āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻāĻ°āĻŦā§, āĻ¯āĻĻāĻŋ āĻĨāĻžāĻā§, āĻāĻžāĻ°āĻŖ āĻ āĻ¨ā§āĻ¯āĻžāĻ¨ā§āĻ¯ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻā§āĻ˛āĻŋ āĻŽā§āĻ˛ āĻĨā§āĻā§ āĻĒā§āĻ°āĻžāĻĒā§āĻ¤ āĻĄā§āĻāĻžāĻ° āĻāĻĒāĻ° āĻāĻŋāĻ¤ā§āĻ¤āĻŋ āĻāĻ°ā§ āĻāĻžāĻ āĻāĻ°ā§, āĻ¯ā§āĻā§āĻ˛āĻŋ āĻ āĻ¨ā§āĻ¯āĻžāĻ¨ā§āĻ¯ āĻāĻ¤ā§āĻ¸ āĻĨā§āĻā§ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻāĻŋāĻ¤ āĻĄā§āĻāĻž āĻā§āĻ°āĻšāĻŖ āĻāĻ°ā§ (āĻāĻĒāĻŋāĻāĻ, āĻā§āĻ˛āĻŋāĻĢā§āĻ¨āĻŋ) , āĻāĻ¯āĻŧā§āĻŦ āĻŽā§āĻā§āĻ°āĻŋāĻā§āĻ¸, āĻāĻ¤ā§āĻ¯āĻžāĻĻāĻŋ) āĻāĻ¤ā§āĻ¯āĻžāĻĻāĻŋ)āĨ¤ āĻāĻŽāĻŋ āĻāĻĒāĻ¨āĻžāĻā§ āĻāĻāĻāĻŋ āĻāĻĻāĻžāĻšāĻ°āĻŖ āĻĻā§āĻŦ. āĻāĻāĻāĻŋ āĻ¨āĻ¤ā§āĻ¨ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°āĻāĻžāĻ°ā§ āĻ¸āĻŋāĻāĻ°āĻāĻŽ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽā§ āĻāĻĒāĻ¸ā§āĻĨāĻŋāĻ¤ āĻšāĻ¯āĻŧā§āĻā§ āĻāĻŦāĻ āĻāĻŽāĻ°āĻž āĻāĻāĻ¨āĻ āĻ¤āĻžāĻ° 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
āĻāĻŽāĻ°āĻž āĻĄā§āĻāĻž āĻā§āĻ°āĻšāĻŖ āĻāĻ°āĻŋ āĻāĻŦāĻ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻŋ
āĻĄā§āĻāĻž āĻā§āĻ°āĻšāĻŖ āĻāĻŦāĻ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯, āĻāĻĒāĻ¨āĻŋ āĻāĻāĻāĻŋ āĻĒā§āĻĨāĻ āĻ āĻĒāĻžāĻ°ā§āĻāĻ° āĻ˛āĻŋāĻāĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨, āĻāĻĒāĻ¨āĻŋ āĻ°ā§āĻĄāĻŋāĻŽā§āĻĄ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨āĨ¤ āĻ¯ā§āĻšā§āĻ¤ā§ āĻ¯ā§āĻā§āĻ¤āĻŋ āĻāĻāĻ¨āĻ āĻ¤ā§āĻā§āĻ - āĻāĻŋāĻ āĻŋ āĻĨā§āĻā§ āĻĄā§āĻāĻž āĻ¨ā§āĻāĻ¯āĻŧāĻžāĻ° āĻāĻ¨ā§āĻ¯, āĻāĻĻāĻžāĻšāĻ°āĻŖāĻ¸ā§āĻŦāĻ°ā§āĻĒ, āĻāĻŽāĻŋ āĻāĻĻāĻ°ā§āĻļ āĻĒāĻžāĻāĻĨāĻ¨ āĻ āĻĒāĻžāĻ°ā§āĻāĻ°ā§āĻ° āĻĒāĻ°āĻžāĻŽāĻ°ā§āĻļ āĻĻāĻŋāĻ
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 āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ° āĻĒāĻžāĻāĻĒāĻ˛āĻžāĻāĻ¨ā§ āĻāĻ°āĻ āĻāĻāĻŋāĻ¯āĻŧā§ āĻ¯āĻžāĻŦā§, āĻ¤āĻŦā§ āĻāĻāĻŋ āĻāĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§āĻ āĻ
āĻ¤āĻŋāĻā§āĻ°āĻŽ āĻāĻ°ā§āĻā§ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ā§āĻ° āĻ¸ā§āĻ¯ā§āĻāĨ¤ āĻ¯āĻĻāĻŋ āĻāĻāĻŋ āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻāĻŦāĻ āĻĻāĻ°āĻāĻžāĻ°ā§ āĻšāĻ¯āĻŧā§ āĻāĻ ā§, āĻ¤āĻŦā§ āĻāĻŽāĻŋ āĻāĻ¨āĻ¨ā§āĻĻā§āĻ° āĻ¸āĻžāĻĨā§ Apache Airflow āĻāĻ° āĻāĻ¨ā§āĻ¯ ETL āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ āĻāĻŦāĻ āĻ¤āĻžāĻĻā§āĻ° āĻ
āĻāĻļāĻā§āĻ˛āĻŋ āĻŦāĻ°ā§āĻŖāĻ¨āĻž āĻāĻ°āĻ¤ā§ āĻĨāĻžāĻāĻŦāĨ¤
āĻāĻ¤ā§āĻ¸: www.habr.com