
рд╣рд╛рдп, рд╣рдмреНрд░реЛрдЬрд╝рд┐рддреЗрд▓реА! рдпрд╣ рдиреЛрд╣рд╛ рдЙрдкрд╣рд╛рд░ рдкреБрд╕реНрддрдХ рдПрдЖрдИ, рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ, рдХреНрд▓рд╛рдЙрдб рдХрдВрдкреНрдпреВрдЯрд┐рдВрдЧ рдФрд░ рдбреЗрдЯрд╛ рд╡рд┐рд╖рдпреЛрдВ рдХреЗ рдХрд┐рд╕реА рднреА рд╕рдВрдпреЛрдЬрди рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрдиреЗ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рд╣реИред рджреЛрдиреЛрдВ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдФрд░ рдмрд╕ рджреЗрдЦрднрд╛рд▓ рдХрд░рдиреЗ рд╡рд╛рд▓реА рддрдХрдиреАрдХреЗрдВ рдпрд╣рд╛рдВ рдЙрдкрдпреЛрдЧреА рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреАред рдкрд╛рдпрдерди рдореЗрдВ рдХреЛрдб рдЙрджрд╛рд╣рд░рдг рджрд┐рдП рдЧрдП рд╣реИрдВред рдпрд╣ рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЗ рдЙрдкрдпреЛрдЧ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдбрдмреНрд▓реНрдпреВрдПрд╕, рдЬреАрд╕реАрдкреА рдФрд░ рдПрдЬрд╝реНрдпреЛрд░) рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдорд╢реАрди рд╕реАрдЦрдиреЗ рдХреА рддрдХрдиреАрдХ рдФрд░ рдПрдЖрдИ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд░реВрдк рдореЗрдВ рдРрд╕реЗ рдХрдИ рдЙрдиреНрдирдд рд╡рд┐рд╖рдпреЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рддрд╛ рд╣реИред рдЬреЗрдбреА рдЬреЛ рдкрд╛рдпрдерди рдореЗрдВ рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рд╣реИрдВ, рдХреНрд▓рд╛рдЙрдб рдХрдВрдкреНрдпреВрдЯрд┐рдВрдЧ, рдФрд░ рдПрдордПрд▓ рднреА рдЕрдкрдиреЗ рд▓рд┐рдП рдХрдИ рдЙрдкрдпреЛрдЧреА рд╡рд┐рдЪрд╛рд░ рдкрд╛рдПрдВрдЧреЗ рдЬреЛ рддреБрд░рдВрдд рдЕрдкрдиреЗ рд╡рд░реНрддрдорд╛рди рдХрд╛рдо рдореЗрдВ рдЖрд╡реЗрджрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╣рдо рдЖрдкрдХреЛ "рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рдореЗрдВ рдПрдХ рдЗрдВрдЯреЗрд▓рд┐рдЬреЗрдВрдЯ рд╕реНрд▓реИрдХ рдмреЙрдЯ рдмрдирд╛рдирд╛" рдкреБрд╕реНрддрдХ рдХреЗ рдПрдХ рдЕрдВрд╢ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдордВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред
рд▓реЛрдЧреЛрдВ рдиреЗ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ "рдХреГрддреНрд░рд┐рдо рдЬреАрд╡рди" рдмрдирд╛рдиреЗ рдХрд╛ рд╕рдкрдирд╛ рджреЗрдЦрд╛ рд╣реИред рдЬреНрдпрд╛рджрд╛рддрд░, рдЬрдмрдХрд┐ рдпрд╣ рдмреЙрдЯреНрд╕ рдмрдирд╛рдиреЗ рд╕реЗ рд╕рдВрднрд╡ рд╣реИред рдмреЙрдЯреНрд╕ рд╣рдорд╛рд░реЗ рджреИрдирд┐рдХ рдЬреАрд╡рди рдХрд╛ рддреЗрдЬреА рд╕реЗ рдЕрднрд┐рдиреНрди рд╣рд┐рд╕реНрд╕рд╛ рдмрди рд░рд╣реЗ рд╣реИрдВ, рд╡рд┐рд╢реЗрд╖рдХрд░ рдПрдкреНрдкрд▓ рдФрд░ рдПрд▓реЗрдХреНрд╕рд╛ рдХреЗ рдЕрдореЗрдЬрд╝реЕрди рд╕реЗ рд╕рд┐рд░реА рдХреЗ рдЖрдЧрдорди рдХреЗ рдмрд╛рдж рд╕реЗред рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ, рд╣рдо рдмреЙрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд╕рднреА рд░рд╣рд╕реНрдпреЛрдВ рдХреЛ рдкреНрд░рдХрдЯ рдХрд░реЗрдВрдЧреЗред
рд╡рдирд╕реНрдкрддрд┐ рдХрд╛ рдирд┐рд░реНрдорд╛рдг
рдмреЙрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкрд╛рдпрдерди рднрд╛рд╖рд╛ (https://github.com/slackapi/python-slackclient) рдХреЗ рд▓рд┐рдП рд╕реНрд▓реИрдХ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рд╕реНрд▓реИрдХ рдХреЗ рд╕рд╛рде рд╢реБрд░реБрдЖрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рдкрд╣рдЪрд╛рди рдЯреЛрдХрди рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдпрд╣ рдкрд░реНрдпрд╛рд╡рд░рдг рдорд╛рд░реНрдХрд░ рдХреЛ рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдРрд╕реЗ рдорд╛рд░реНрдХрд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред рдореИрдВ рдЕрдХреНрд╕рд░ virtualenv рдореЗрдВ рдРрд╕рд╛ рдХрд░рддрд╛ рд╣реВрдВ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╡рд░реНрддрдорд╛рди рдкрд░рд┐рд╡реЗрд╢ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рдкрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЗрд╕ рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╕рдХреНрд░рд┐рдп рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдХреЗ virtualenv рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЛ рдереЛрдбрд╝рд╛ "рджрд░рд╛рд░" рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд╕реНрд▓реИрдХ рд╡реИрд░рд┐рдПрдмрд▓ рдХреЛ ~ / .env / bin / рд╕рдХреНрд░рд┐рдп рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдирд┐рд░реНрдпрд╛рдд рдХрд░рддреЗ рд╕рдордп, рдпрд╣ рдиреАрдЪреЗ рдХреА рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛ред
рдФрд░ рд╕рд┐рд░реНрдл рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рдирд╡реАрдирддрдо рдирд╡рд╛рдЪрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдмрдиреЗ рд░рд╣рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЗ рдкреНрд░рдмрдВрдзрди рдХреЗ рд▓рд┐рдП рдирдП, рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдкрд╛рдпрдерди рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЬрд╛рддреА рд╣реИ - pipenv (https://github.com/pypa/pipenv):
_OLD_VIRTUAL_PATH="$PATH" PATH="$VIRTUAL_ENV/bin:$PATH" export PATH SLACK_API_TOKEN=<Your Token Here> export SLACK_API_TOKEN
рдкрд░рд┐рд╡реЗрд╢ рдЪрд░ рд╕реЗрдЯ рд╣реИ рдпрд╛ рдирд╣реАрдВ рдпрд╣ рдЬрд╛рдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП OS X рдФрд░ Linux рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ Printenv рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рдЖрдк рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ рдХреЗ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рдирд┐рдореНрди рд▓рдШреБ рд▓рд┐рдкрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
import os from slackclient import SlackClient slack_token = os.environ["SLACK_API_TOKEN"] sc = SlackClient(slack_token) sc.api_call( "chat.postMessage", channel="#general", text="Hello from my bot! :tada:" )
рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ pipenv рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдПрдХ рдШрдЯрдХ рдореЗрдВ pip рдФрд░ virtualenv рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХреЗ рд╕рдВрдпреЛрдЬрди рдХреЗ рд▓рд┐рдП рдЕрдиреБрд╢рдВрд╕рд┐рдд рд╕рдорд╛рдзрд╛рди рд╣реИред рдпрд╣ рдПрдХ рдирдпрд╛ рдорд╛рдирдХ рдмрди рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдкреИрдХреЗрдЬ рдкреНрд░рдмрдВрдзрди рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рдЗрд╕реЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред
рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдореЗрдВ рдмрджрд▓реЗрдВ
рдЗрд╕ рдкреБрд╕реНрддрдХ рдХреЗ рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рддрд░рд╣, рдирдП рд╡рд┐рдЪрд╛рд░реЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдХреЛрдб рдХреЛ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИред рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдХрдИ рдиреМрд╕рд┐рдЦрд┐рдП рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЕрдХреНрд╕рд░ рдХрдорд╛рдВрдб-рд▓рд╛рдЗрди рдЯреВрд▓реНрд╕ рдирд╣реАрдВ рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдиреНрдп рд╕рдорд╛рдзрд╛рди, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡реЗ рдмрд╕ рдмреГрд╣рд╕реНрдкрддрд┐ рдиреЛрдЯрдмреБрдХ рдореЗрдВ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред рдореИрдВ рдереЛрдбрд╝реЗ рд╕рдордп рдХреЗ рд▓рд┐рдП рд╢реИрддрд╛рди рдХреЗ рд╡рдХреАрд▓ рдХреА рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рдКрдВрдЧрд╛ рдФрд░ рдПрдХ рд╕рд╡рд╛рд▓ рдкреВрдЫреВрдВрдЧрд╛, рдЬреЛ рдкрд╛рдардХреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ: тАЬрд╣рдореЗрдВ рдмреГрд╣рд╕реНрдкрддрд┐ рдкреБрд╕реНрддрд┐рдХрд╛рдУрдВ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдХрдорд╛рдВрдб-рд▓рд╛рдЗрди рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ? рдХреНрдпрд╛ рдХрдорд╛рдВрдб рд╢реЗрд▓ рдФрд░ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдХреЛ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмреГрд╣рд╕реНрдкрддрд┐ рдиреЛрдЯрдкреИрдб рдХреА рдмрд╛рдд рдирд╣реАрдВ рд╣реИ? тАЭ рдХрд┐рд╕реА рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдЬреЛрдбрд╝рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЖрдкрдХреЛ рд╡рд┐рднрд┐рдиреНрди рдЗрдирдкреБрдЯ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рдЖрдЬрд╝рдорд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдмреГрд╣рд╕реНрдкрддрд┐ рдиреЛрдЯрдмреБрдХ рдХреЛрдб рдмреНрд▓реЙрдХ рдЗрдирдкреБрдЯ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдПрдХ рдЕрд░реНрде рдореЗрдВ, рдпреЗ рд╣рд╛рд░реНрдб-рд╡рд╛рдпрд░реНрдб рдбреЗрдЯрд╛ рд╡рд╛рд▓реА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИрдВред
GCP рдФрд░ AWS рджреЛрдиреЛрдВ рдкреНрд▓реЗрдЯрдлрд╛рд░реНрдореЛрдВ рдкрд░ рдХрдИ рдХрдорд╛рдВрдб-рд▓рд╛рдЗрди рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ рд╕рдВрдпреЛрдЧ рд╕реЗ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИрдВ: рд╡реЗ рд▓рдЪреАрд▓реЗрдкрди рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдПрдБ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдЪрд┐рддреНрд░рдордп рдЗрдВрдЯрд░рдлреЗрд╕ рдкрд░ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИрдВред рд╡рд┐рдЬреНрдЮрд╛рди рдХрдерд╛ рд▓реЗрдЦрдХ рдиреАрд▓ рд╕реНрдЯреАрдлреЗрдВрд╕рди рджреНрд╡рд╛рд░рд╛ рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдирд┐рдмрдВрдзреЛрдВ рдХрд╛ рдПрдХ рдЕрджреНрднреБрдд рд╕рдВрдЧреНрд░рд╣ "рдЗрди рдж рдмрд┐рдЧрд┐рдирд┐рдВрдЧ ... рдПрдХ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдерд╛" рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдореЗрдВ, рд╕реНрдЯреАрд╡реЗрдиреНрд╕рди рдХрд╣рддреЗ рд╣реИрдВ: "GUIs рд╣рд░ рдЕрддрд┐рд░рд┐рдХреНрдд, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╕рдмрд╕реЗ рдЫреЛрдЯреЗ, рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдШрдЯрдХ рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрддрд┐рд░рд┐рдХреНрдд рдУрд╡рд░рд╣реЗрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд╡рд╛рддрд╛рд╡рд░рдг рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдмрджрд▓ рджреЗрддреА рд╣реИред" рд╡рд╣ рд╢рдмреНрджреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдЧреНрд░рд╣ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ: тАЬ... рдЬреАрд╡рди рдмрд╣реБрдд рдХрдард┐рди рдФрд░ рдХрдард┐рди рдмрд╛рдд рд╣реИ; рдХреЛрдИ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдирд╣реАрдВ рдмрджрд▓реЗрдЧрд╛; рдФрд░ рдЬреЛ рдХреЛрдИ рднреА рд╕реЛрдЪрддрд╛ рд╣реИ рдХрд┐ рд╡рд╣ рдПрдХ рд╕рд░рд▓ рд╣реИ ... "рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рд▓реЗрдХрд┐рди рдореЗрд░рд╛ рдЕрдиреБрднрд╡ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдХреЗ рд╕рд╛рде рдЬреАрд╡рди рдмреЗрд╣рддрд░ рд╣реЛ рд░рд╣рд╛ рд╣реИред рдЗрд╕реЗ рдЖрдЬрд╝рдорд╛рдПрдВ рдФрд░ рдЖрдк рдЬреАрдпреВрдЖрдИ рдореЗрдВ рд╡рд╛рдкрд╕ рдирд╣реАрдВ рдЬрд╛рдирд╛ рдЪрд╛рд╣рддреЗред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдХреНрд▓рд┐рдХ рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдирдП рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрджреЗрд╢ рднреЗрдЬрдирд╛ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИред
./clibot.py send --message "from cli" sending message from cli to #general
рдЪрд┐рддреНрд░рд╛ 7.1 рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рд╕реАрдПрд▓рдЖрдИ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╕реЗ рдХрд╕реНрдЯрдо рд╕рдВрджреЗрд╢ рджрд┐рдЦрд╛рддрд╛ рд╣реИред
#!/usr/bin/env python import os import click from slackclient import SlackClient SLACK_TOKEN = os.environ["SLACK_API_TOKEN"] def send_message(channel="#general", message="Hello from my bot!"): """ """ slack_client = SlackClient(SLACK_TOKEN) res = slack_client.api_call( "chat.postMessage", channel=channel, text=message ) return res @click.group() @click.version_option("0.1") def cli(): """ """ @cli.command("send") @click.option("--message", default="Hello from my bot!", help="text of message") @click.option("--channel", default="#general", help="general channel") def send(channel, message): click.echo(f"sending message {message} to {channel}") send_message(channel, message=message) if __name__ == '__main__': cli()
рд╣рдо рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд╕реНрдЯреЗрдк рдлрдВрдХреНрд╢рдВрд╕ рд╕реЗрд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреЙрдЯ рдХреЛ рдПрдХ рдирдП рд╕реНрддрд░ рдкрд░ рд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВ
рд╕реНрд▓реИрдХ рдХреЛ рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдЪрд╛рд░ рдЪреИрдирд▓ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рд╣рдорд╛рд░реЗ рдХреЛрдб рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рддреН: рдЗрд╕реЗ рдПрдХ рд╢реЗрдбреНрдпреВрд▓ рдкрд░ рдЪрд▓рд╛рдПрдВ рдФрд░ рдХрд┐рд╕реА рднреА рдЙрдкрдпреЛрдЧреА рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред AWS рд╕реНрдЯреЗрдк рдлрдВрдХреНрд╢рдиреНрд╕ рд╕рд░реНрд╡рд┐рд╕ рдЗрд╕рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдЪреНрдЫреА рд╣реИред рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ, рд╣рдорд╛рд░реЗ рд╕реНрд▓реИрдХ рдмреЙрдЯ рдпрд╛рд╣реВ рдХреЗ рдЦреЗрд▓ рдкреГрд╖реНрдареЛрдВ рдХреЛ рд╕реНрдХреНрд░реИрдк рдХрд░рдирд╛ рд╕реАрдЦреЗрдВрдЧреЗ! рдПрдирдмреАрдП рдЦрд┐рд▓рд╛рдбрд╝реА, рдЕрдкрдиреЗ рдЬрдиреНрдорд╕реНрдерд╛рди рдХреЛ рдкреБрдирдГ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЗрд╕ рдбреЗрдЯрд╛ рдХреЛ рд╕реНрд▓реИрдХ рдореЗрдВ рднреЗрдЬрддреЗ рд╣реИрдВред
рдЪрд┐рддреНрд░ 7.2 рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ рдПрдХ рддреИрдпрд╛рд░ рдХрд┐рдП рдЧрдП рдЪрд░рдг-рджрд░-рдЪрд░рдг рдлрд╝рдВрдХреНрд╢рди рдХреЛ рджрд┐рдЦрд╛рддрд╛ рд╣реИред рдкрд╣рд▓рд╛ рдХрджрдо рдПрдирдмреАрдП рдЦрд┐рд▓рд╛рдбрд╝реА рдкреНрд░реЛрдлрд╛рдЗрд▓ рдпреВрдЖрд░рдПрд▓ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ, рдФрд░ рджреВрд╕рд░рд╛ рдкреНрд░рддреНрдпреЗрдХ рдЦрд┐рд▓рд╛рдбрд╝реА рдХреЗ рдЬрдиреНрдорд╕реНрдерд╛рди рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрдВрджрд░ рд╕реВрдк рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред рдЪрд░рдг-рджрд░-рдЪрд░рдг рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдкрд░, рдкрд░рд┐рдгрд╛рдо рд╡рд╛рдкрд╕ рд╕реНрд▓реИрдХ рдореЗрдВ рднреЗрдЬреЗ рдЬрд╛рдПрдВрдЧреЗред

AWS рд▓реИрдореНрдмреНрдбрд╛ рдФрд░ рдЪрд╛рд▓рд┐рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХ рдЪрд░рдг рдлрд╝рдВрдХреНрд╢рди рдХреЗ рднреАрддрд░ рдХрд╛рдо рдХреЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЗ рд╕рдордиреНрд╡рдп рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд▓реИрдореНрдмреНрдбрд╛ (https://aws.amazon.com/lambda/) рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ AWS рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдЪрд╛рд▓рд┐рд╕ рдлреНрд░реЗрдорд╡рд░реНрдХ (http://chalice.readthedocs.io/en/latest/) рдЖрдкрдХреЛ рдкрд╛рдпрдерди рдореЗрдВ рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдХреБрдЫ рдЖрд╡рд╢реНрдпрдХ рд╢рд░реНрддреЗрдВ рд╣реИрдВ:
- рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдкрд╛рд╕ AWS рдЦрд╛рддрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
- рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ;
- рд▓реИрдореНрдмреНрдбрд╛ рднреВрдорд┐рдХрд╛ (рдЪрд╛рд▓рд┐рд╕ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдИ рдЧрдИ) рдХреЗ рдкрд╛рд╕ S3 рдЬреИрд╕реА рд╕рдВрдмрдВрдзрд┐рдд AWS рд╕реЗрд╡рд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╡рд┐рд╢реЗрд╖рд╛рдзрд┐рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдиреАрддрд┐ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред
IAM рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ
AWS рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╕реНрддреГрдд рдирд┐рд░реНрджреЗрд╢
boto3.readthedocs.io/en/latest/guide/configuration.html рдкрд░
рджреЗрдЦреЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред рд╡рд┐рдВрдбреЛрдЬ рдФрд░ рд▓рд┐рдирдХреНрд╕ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рдЪрд░ рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА
рдпрд╣рд╛рдВ рдкрд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИ ред рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреЗ рдХрдИ рддрд░реАрдХреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди virtualenv рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ AWS рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓реНрд╕ рдХреЛ рд╕реНрдерд╛рдиреАрдп рд╡рд░реНрдЪреБрдЕрд▓ рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ / рдмрд┐рди / рд╕рдХреНрд░рд┐рдп рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВ:
# AWS AWS_DEFAULT_REGION=us-east-1 AWS_ACCESS_KEY_ID=xxxxxxxx AWS_SESSION_TOKEN=xxxxxxxx
# export AWS_DEFAULT_REGION export AWS_ACCESS_KEY_ID export AWS_DEFAULT_REGION
рдЪрд╛рд▓рд┐рд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВред рдХрдИ рдЖрджреЗрд╢реЛрдВ рдХреЗ рд╕рд╛рде рдЪрд╛рд▓рд┐рд╕ рдХреА рдПрдХ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╣реИ:
Usage: chalice [OPTIONS] COMMAND [ARGS]... Options: --version Show the version and exit. --project-dir TEXT The project directory. Defaults to CWD --debug / --no-debug Print debug logs to stderr. --help Show this message and exit. Commands: delete deploy gen-policy generate-pipeline Generate a cloudformation template for a... generate-sdk local logs new-project package url
App.py рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рдЕрдВрджрд░ рдХреЛрдб рд▓реИрдореНрдмреНрдбрд╛ рд╕реЗрд╡рд╛ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред AWS рдЪрд╛рд▓рд┐рд╕ рдЗрд╕рдореЗрдВ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдХрд┐ рдпрд╣ рд╡реЗрдм рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, "рд╕реНрдЯреИрдВрдб-рдЕрд▓реЛрди" рд▓реИрдореНрдмрдбрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╡ рдмрдирд╛рддрд╛ рд╣реИред рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдЖрдк рдХрдИ рд▓реЗрдореНрдмрдбрд╛ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рдЪрд░рдг-рджрд░-рдЪрд░рдг рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рд▓реЗрдЧреЛ рдХреНрдпреВрдмреНрд╕ рдХреА рддрд░рд╣ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рд╛рде рд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХ рд╢реЗрдбреНрдпреВрд▓реНрдб рд▓реИрдореНрдмреНрдбрд╛ рдлрдВрдХреНрд╢рди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдХреЛрдИ рднреА рдПрдХреНрд╢рди рдХрд░реЗрдЧрд╛
@app.schedule(Rate(1, unit=Rate.MINUTES)) def every_minute(event): """, """ # Slack
рд╡реЗрдм рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдмреЙрдЯ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХрдИ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдлрд╝рд╛рдЗрд▓ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЖрдпрд╛рдд рд╣реЛрддреЗ рд╣реИрдВ рдФрд░ рдХрдИ рдЪрд░ рдШреЛрд╖рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ:
import logging import csv from io import StringIO import boto3 from bs4 import BeautifulSoup import requests from chalice import (Chalice, Rate) APP_NAME = 'scrape-yahoo' app = Chalice(app_name=APP_NAME) app.log.setLevel(logging.DEBUG)
рдПрд╕ 3 рдореЗрдВ рдбреЗрдЯрд╛ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмреЙрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред CSV рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рд╕рд╣реЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрди рдлрд╝рдВрдХреНрд╢рди Boto рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:
def create_s3_file(data, name="birthplaces.csv"): csv_buffer = StringIO() app.log.info(f"Creating file with {data} for name") writer = csv.writer(csv_buffer) for key, value in data.items(): writer.writerow([key,value]) s3 = boto3.resource('s3') res = s3.Bucket('aiwebscraping').\ put_object(Key=name, Body=csv_buffer.getvalue()) return res
Fetch_page рдлрд╝рдВрдХреНрд╢рди NBA рд╕рд╛рдВрдЦреНрдпрд┐рдХреА URL рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕реНрдерд┐рдд HTML рдкреГрд╖реНрда рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ
рд▓рд┐рдП рд╕реБрдВрджрд░ рд╕реВрдк рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛
рд╣реИ рдФрд░ рдПрдХ рд╕реВрдк рд▓реМрдЯрд╛рддрд╛ рд╣реИ:
def fetch_page(url="https://sports.yahoo.com/nba/stats/"): """ URL Yahoo""" # # Beautiful Soup app.log.info(f"Fetching urls from {url}") res = requests.get(url) soup = BeautifulSoup(res.content, 'html.parser') return soup
Get_player_links рдФрд░ fetch_player_urls рдлрд╝рдВрдХреНрд╢рдВрд╕ рдЦрд┐рд▓рд╛рдбрд╝реА рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ URL рдХреЗ рд▓рд┐рдВрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:
def get_player_links(soup): """ URL URL 'a' 'nba/players' """ nba_player_urls = [] for link in soup.find_all('a'): link_url = link.get('href') # if link_url: if "nba/players" in link_url: print(link_url) nba_player_urls.append(link_url) return nba_player_urls def fetch_player_urls(): """ URL """ soup = fetch_page() urls = get_player_links(soup) return urls
рдЗрд╕рдХреЗ рдмрд╛рдж, find_birthplaces рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рд╣рдо рдЗрди рдкреГрд╖реНрдареЛрдВ рдкрд░ рд╕реНрдерд┐рдд URL рд╕реЗ рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЗ рдЬрдиреНрдорд╕реНрдерд╛рди рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ:
def find_birthplaces(urls): """ NBA Yahoo""" birthplaces = {} for url in urls: profile = requests.get(url) profile_url = BeautifulSoup(profile.content, 'html.parser') lines = profile_url.text res2 = lines.split(",") key_line = [] for line in res2: if "Birth" in line: #print(line) key_line.append(line) try: birth_place = key_line[0].split(":")[-1].strip() app.log.info(f"birth_place: {birth_place}") except IndexError: app.log.info(f"skipping {url}") continue birthplaces[url] = birth_place app.log.info(birth_place) return birthplaces
рдЕрдм рд╣рдо рдЪрд╛рд▓рд┐рд╕ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рдПрдВрдЧреЗред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ: рдЪрд╛рд▓рд┐рд╕ рдврд╛рдВрдЪреЗ рдХреЗ рд▓рд┐рдП, рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкрде рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛:
# HTTP- @app.route('/') def index(): """ URL""" app.log.info(f"/ Route: for {APP_NAME}") return {'app_name': APP_NAME}
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓реИрдореНрдмреНрдбрд╛ рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдорд╛рд░реНрдЧ рд╣реИ рдЬреЛ HTTP URL рдХреЛ рдкрд╣рд▓реЗ рд▓рд┐рдЦреЗ рдЧрдП рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рдЬреЛрдбрд╝рддрд╛ рд╣реИ:
@app.route('/player_urls') def player_urls(): """ URL """ app.log.info(f"/player_urls Route: for {APP_NAME}") urls = fetch_player_urls() return {"nba_player_urls": urls}
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓реИрдореНрдмреНрдбрд╛ рдлрд╝рдВрдХреНрд╢рди рд╕реНрдЯреИрдВрдбрдЕрд▓реЛрди рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рдЪрд░рдг-рджрд░-рдЪрд░рдг рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
# Lambda @app.lambda_function() def return_player_urls(event, context): """ Lambda, URL """ app.log.info(f"standalone lambda 'return_players_urls'\ {APP_NAME} with {event} and {context}") urls = fetch_player_urls() return {"urls": urls} # Lambda @app.lambda_function() def birthplace_from_urls(event, context): """ """ app.log.info(f"standalone lambda 'birthplace_from_urls'\ {APP_NAME} with {event} and {context}") payload = event["urls"] birthplaces = find_birthplaces(payload) return birthplaces # Lambda @app.lambda_function() def create_s3_file_from_json(event, context): """ S3 JSON""" app.log.info(f"Creating s3 file with event data {event}\ and context {context}") print(type(event)) res = create_s3_file(data=event) app.log.info(f"response of putting file: {res}") return True
рдпрджрд┐ рдЖрдк рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдЪрд╛рд▓рд┐рд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рдирд┐рдореНрди рдкрд░рд┐рдгрд╛рдо рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрдВрдЧреЗ:
тЖТ scrape-yahoo git:(master) яА╖ chalice local Serving on 127.0.0.1:8000 scrape-yahoo - INFO - / Route: for scrape-yahoo 127.0.0.1 - - [12/Dec/2017 03:25:42] "GET / HTTP/1.1" 200 - 127.0.0.1 - - [12/Dec/2017 03:25:42] "GET /favicon.ico" scrape-yahoo - INFO - / Route: for scrape-yahoo 127.0.0.1 - - [12/Dec/2017 03:25:45] "GET / HTTP/1.1" 200 - 127.0.0.1 - - [12/Dec/2017 03:25:45] "GET /favicon.ico" scrape-yahoo - INFO - /player_urls Route: for scrape-yahoo scrape-yahoo - INFO - https://sports.yahoo.com/nba/stats/ https://sports.yahoo.com/nba/players/4563/ https://sports.yahoo.com/nba/players/5185/ https://sports.yahoo.com/nba/players/3704/ https://sports.yahoo.com/nba/players/5012/ https://sports.yahoo.com/nba/players/4612/ https://sports.yahoo.com/nba/players/5015/ https://sports.yahoo.com/nba/players/4497/ https://sports.yahoo.com/nba/players/4720/ https://sports.yahoo.com/nba/players/3818/ https://sports.yahoo.com/nba/players/5432/ https://sports.yahoo.com/nba/players/5471/ https://sports.yahoo.com/nba/players/4244/ https://sports.yahoo.com/nba/players/5464/ https://sports.yahoo.com/nba/players/5294/ https://sports.yahoo.com/nba/players/5336/ https://sports.yahoo.com/nba/players/4390/ https://sports.yahoo.com/nba/players/4563/ https://sports.yahoo.com/nba/players/3704/ https://sports.yahoo.com/nba/players/5600/ https://sports.yahoo.com/nba/players/4624/ 127.0.0.1 - - [12/Dec/2017 03:25:53] "GET /player_urls" 127.0.0.1 - - [12/Dec/2017 03:25:53] "GET /favicon.ico"
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЪрд╛рд▓рд┐рд╕ рддреИрдирд╛рддреА рдХрдорд╛рдВрдб рдЪрд▓рд╛рдПрдБ:
тЖТ scrape-yahoo git:(master) яА╖ chalice deploy Creating role: scrape-yahoo-dev Creating deployment package. Creating lambda function: scrape-yahoo-dev Initiating first time deployment. Deploying to API Gateway stage: api https://bt98uzs1cc.execute-api.us-east-1.amazonaws.com/api/
HTTP (https://github.com/jakubroztocil/httpie) рдХреЗ рд▓рд┐рдП рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рд╣рдо AWS рд╕реЗ HTTP рд░реВрдЯ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ / api / player_urls рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд▓рд┐рдВрдХ рдХреЛ рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ:
тЖТ scrape-yahoo git:(master) яА╖ http \ https://<a lambda route>.amazonaws.com/api/player_urls HTTP/1.1 200 OK Connection: keep-alive Content-Length: 941 Content-Type: application/json Date: Tue, 12 Dec 2017 11:48:41 GMT Via: 1.1 ba90f9bd20de9ac04075a8309c165ab1.cloudfront.net (CloudFront) X-Amz-Cf-Id: ViZswjo4UeHYwrc9e-5vMVTDhV_Ic0dhVIG0BrDdtYqd5KWcAuZKKQ== X-Amzn-Trace-Id: sampled=0;root=1-5a2fc217-07cc12d50a4d38a59a688f5c X-Cache: Miss from cloudfront x-amzn-RequestId: 64f24fcd-df32-11e7-a81a-2b511652b4f6 { "nba_player_urls": [ "https://sports.yahoo.com/nba/players/4563/", "https://sports.yahoo.com/nba/players/5185/", "https://sports.yahoo.com/nba/players/3704/", "https://sports.yahoo.com/nba/players/5012/", "https://sports.yahoo.com/nba/players/4612/", "https://sports.yahoo.com/nba/players/5015/", "https://sports.yahoo.com/nba/players/4497/", "https://sports.yahoo.com/nba/players/4720/", "https://sports.yahoo.com/nba/players/3818/", "https://sports.yahoo.com/nba/players/5432/", "https://sports.yahoo.com/nba/players/5471/", "https://sports.yahoo.com/nba/players/4244/", "https://sports.yahoo.com/nba/players/5464/", "https://sports.yahoo.com/nba/players/5294/", "https://sports.yahoo.com/nba/players/5336/", "https://sports.yahoo.com/nba/players/4390/", "https://sports.yahoo.com/nba/players/4563/", "https://sports.yahoo.com/nba/players/3704/", "https://sports.yahoo.com/nba/players/5600/", "https://sports.yahoo.com/nba/players/4624/" ] }
рд▓реИрдореНрдмреНрдбрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХрд╛ рдЙрдиреНрд╣реЗрдВ рд╕реАрдзреЗ рдХреНрд▓рд┐рдХ рдкреИрдХреЗрдЬ рдФрд░ рдкрд╛рдпрдерди рдмреЛрдЯреЛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реИред
рд╣рдо рдПрдХ рдирдИ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдХрд╛ рдирд╛рдо рд╣реИ wscli.py (рд╡реЗрдм-рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдХрдорд╛рдВрдб-рд▓рд╛рдЗрди рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд▓рд┐рдП рдЫреЛрдЯрд╛ - "рд╡реЗрдм рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЗрдВрдЯрд░рдлрд╝реЗрд╕")ред рдХреЛрдб рдХреЗ рдкрд╣рд▓реЗ рднрд╛рдЧ рдореЗрдВ, рд╣рдо рд▓реЙрдЧрд┐рдВрдЧ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рдЖрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВ:
#!/usr/bin/env python import logging import json import boto3 import click from pythonjsonlogger import jsonlogger # log = logging.getLogger(__name__) log.setLevel(logging.INFO) LOGHANDLER = logging.StreamHandler() FORMMATTER = jsonlogger.JsonFormatter() LOGHANDLER.setFormatter(FORMMATTER) log.addHandler(LOGHANDLER)
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддреАрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ invoke_lambda рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реИрдореНрдмреНрдбрд╛ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
### API Boto Lambda def lambda_connection(region_name="us-east-1"): """ Lambda""" lambda_conn = boto3.client("lambda", region_name=region_name) extra_msg = {"region_name": region_name, "aws_service": "lambda"} log.info("instantiate lambda client", extra=extra_msg) return lambda_conn def parse_lambda_result(response): """ Boto JSON""" body = response['Payload'] json_result = body.read() lambda_return_value = json.loads(json_result) return lambda_return_value def invoke_lambda(func_name, lambda_conn, payload=None, invocation_type="RequestResponse"): """ Lambda""" extra_msg = {"function_name": func_name, "aws_service": "lambda", "payload":payload} log.info("Calling lambda function", extra=extra_msg) if not payload: payload = json.dumps({"payload":"None"}) response = lambda_conn.invoke(FunctionName=func_name, InvocationType=invocation_type, Payload=payload ) log.info(response, extra=extra_msg) lambda_return_value = parse_lambda_result(response) return lambda_return_value
рд╣рдо рдХрдорд╛рдВрдб-рд▓рд╛рдЗрди рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Python рдкреИрдХреЗрдЬ рдХреЗ рд╕рд╛рде invoke_lambda рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд▓рдкреЗрдЯрддреЗ рд╣реИрдВред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдо --func рд╡рд┐рдХрд▓реНрдк рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдкрд╣рд▓реЗ рд▓реИрдВрдмрдбрд╛ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:
@click.group() @click.version_option("1.0") def cli(): """ -""" @cli.command("lambda") @click.option("--func", default="scrape-yahoo-dev-return_player_urls", help="name of execution") @click.option("--payload", default='{"cli":"invoke"}', help="name of payload") def call_lambda(func, payload): """ Lambda ./wscli.py lambda """ click.echo(click.style("Lambda Function invoked from cli:", bg='blue', fg='white')) conn = lambda_connection() lambda_return_value = invoke_lambda(func_name=func, lambda_conn=conn, payload=payload) formatted_json = json.dumps(lambda_return_value, sort_keys=True, indent=4) click.echo(click.style( "Lambda Return Value Below:", bg='blue', fg='white')) click.echo(click.style(formatted_json,fg="red")) if __name__ == "__main__": cli()
рдЗрд╕ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдкрд░рд┐рдгрд╛рдо HTTP рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд╕рдорд╛рди рд╣реИрдВ:
тЖТ X ./wscli.py lambda \ --func=scrape-yahoo-dev-birthplace_from_urls\ --payload '{"url":["https://sports.yahoo.com/nba/players/4624/",\ "https://sports.yahoo.com/nba/players/5185/"]}' Lambda Function invoked from cli: {"message": "instantiate lambda client", "region_name": "us-east-1", "aws_service": "lambda"} {"message": "Calling lambda function", "function_name": "scrape-yahoo-dev-birthplace_from_urls", "aws_service": "lambda", "payload": "{\"url\":[\"https://sports.yahoo.com/nba/players/4624/\", \"https://sports.yahoo.com/nba/players/5185/\"]}"} {"message": null, "ResponseMetadata": {"RequestId": "a6049115-df59-11e7-935d-bb1de9c0649d", "HTTPStatusCode": 200, "HTTPHeaders": {"date": "Tue, 12 Dec 2017 16:29:43 GMT", "content-type": "application/json", "content-length": "118", "connection": "keep-alive", "x-amzn-requestid": "a6049115-df59-11e7-935d-bb1de9c0649d", "x-amzn-remapped-content-length": "0", "x-amz-executed-version": "$LATEST", "x-amzn-trace-id": "root=1-5a3003f2-2583679b2456022568ed0682;sampled=0"}, "RetryAttempts": 0}, "StatusCode": 200, "ExecutedVersion": "$LATEST", "Payload": "<botocore.response.StreamingBody object at 0x10ee37dd8>", "function_name": "scrape-yahoo-dev-birthplace_from_urls", "aws_service": "lambda", "payload": "{\"url\":[\"https://sports.yahoo.com/nba/players/4624/\", \"https://sports.yahoo.com/nba/players/5185/\"]}"} Lambda Return Value Below: { "https://sports.yahoo.com/nba/players/4624/": "Indianapolis", "https://sports.yahoo.com/nba/players/5185/": "Athens" }
рдЪрд░рдг-рджрд░-рдЪрд░рдг рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдирд╛ рд╕рдорд╛рдкреНрдд рдХрд░реЗрдВ
рдЪрд░рдг-рджрд░-рдЪрд░рдг рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдиреЗ рдХрд╛ рдЕрдВрддрд┐рдо рдЪрд░рдг, рдЬреИрд╕рд╛ рдХрд┐ AWS рдкреНрд░рд▓реЗрдЦрди (https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-creating-activity-state-machine.html) рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИ, рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдирд╛ рд╣реИред рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рдиреЛрдЯреЗрд╢рди (JSON) рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд░рд╛рдЬреНрдп рдорд╢реАрди рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рд╡реЗрдм рдЗрдВрдЯрд░рдлрд╝реЗрд╕ред рдирд┐рдореНрди рдХреЛрдб рдЗрд╕ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдпрд╛рд╣реВ рдХреЛ рд╕реНрдХреНрд░реИрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореВрд▓ рд▓реИрдореНрдмреНрдбрд╛ рдХрд╛рд░реНрдпреЛрдВ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ!, рдПрдХ рдПрд╕ 3 рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЕрдВрдд рдореЗрдВ рд╕реНрд▓реИрдХ рдХреЛ рд╕рд╛рдордЧреНрд░реА рднреЗрдЬрддрд╛ рд╣реИ:
{ "Comment": "Fetch Player Urls", "StartAt": "FetchUrls", "States": { "FetchUrls": { "Type": "Task", "Resource": \ "arn:aws:lambda:us-east-1:561744971673:\ function:scrape-yahoo-dev-return_player_urls", "Next": "FetchBirthplaces" }, "FetchBirthplaces": { "Type": "Task", "Resource": \ "arn:aws:lambda:us-east-1:561744971673:\ function:scrape-yahoo-dev-birthplace_from_urls", "Next": "WriteToS3" }, "WriteToS3": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:\ 561744971673:function:scrape-yahoo-dev-create_s3_file_from_json", "Next": "SendToSlack" }, "SendToSlack": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:561744971673:\ function:send_message", "Next": "Finish" }, "Finish": { "Type": "Pass", "Result": "Finished", "End": true } } }
рдЕрдВрдЬреАрд░ рдореЗрдВред 7.2 рдЗрд╕ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЗ рдкрд╣рд▓реЗ рднрд╛рдЧ рдХрд╛ рдирд┐рд╖реНрдкрд╛рджрди рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд░рд╛рдЬреНрдп рдорд╢реАрди рдХреЗ рдордзреНрдпрд╡рд░реНрддреА рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рджреЗрдЦрдирд╛ рдмреЗрд╣рдж рдЙрдкрдпреЛрдЧреА рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд░рд╛рдЬреНрдп рдорд╢реАрди рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рднрд╛рдЧ рдХреА рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред
рдЪрд┐рддреНрд░ 7.3 рдПрд╕ 3 рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдФрд░ рд╕реНрд▓реИрдХ рдореЗрдВ рд╕рд╛рдордЧреНрд░реА рднреЗрдЬрдиреЗ рдХреЗ рдЪрд░рдгреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд╕рд╛рде рдПрдХ рдкреВрд░реНрдг рдкрд╛рдЗрдкрд▓рд╛рдЗрди рджрд┐рдЦрд╛рддрд╛ рд╣реИред рдпрд╣ рдХреЗрд╡рд▓ рдпрд╣ рддрдп рдХрд░рдирд╛ рдмрд╛рдХреА рд╣реИ рдХрд┐ рдЗрд╕ рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЛ рдХреИрд╕реЗ рдЪрд▓рд╛рдпрд╛ рдЬрд╛рдП - рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдордп рдЕрдВрддрд░рд╛рд▓ рдкрд░ рдпрд╛ рдХрд┐рд╕реА рдШрдЯрдирд╛ рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВред
рд╕рд╛рд░рд╛рдВрд╢
рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ, рдЖрдкрдХреЛ AI рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдХрдИ рдЕрджреНрднреБрдд рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдХрд░рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕рдиреЗ рд╕реНрд▓реИрдХ рдмреЙрдЯ рдФрд░ рд╡реЗрдм рд╕реНрдХреНрд░реИрдкрд┐рдВрдЧ рдпреВрдЯрд┐рд▓рд┐рдЯреА рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд┐рдпрд╛, рдЬреЛ рддрдм AWS рд╕реЗ рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рд╕реЗрд╡рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЬреБрдбрд╝реЗ рдереЗред рдЖрдк рдЗрд╕ рддрд░рд╣ рдХреЗ рд╢реБрд░реБрдЖрддреА рдврд╛рдВрдЪреЗ рдореЗрдВ рдмрд╣реБрдд рдХреБрдЫ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡реЗрдм рдкреГрд╖реНрдареЛрдВ рдХреЛ рдкрдврд╝рдиреЗ рдФрд░ рдЙрдирдХреА рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╕рд╛рдордЧреНрд░реА рдпрд╛ рд╢рд┐рдХреНрд╖рдХ рдХреЗ рдмрд┐рдирд╛ рдХреНрд▓рд╕реНрдЯрд░рд┐рдВрдЧ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рдХреГрддрд┐рдХ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рдЧреНрд░рдВрдереЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓реИрдВрдмрдбрд╛-рдлрд╝рдВрдХреНрд╢рди, рдЬреЛ рдирдП рдПрдирдмреАрдП рдЦрд┐рд▓рд╛рдбрд╝рд┐рдпреЛрдВ рдХреЛ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝ рджреЗрдЧрд╛ред
┬╗рдкреБрд╕реНрддрдХ рдХреА рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА
рдкреНрд░рдХрд╛рд╢рдХ рдХреА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рдкрд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИ
┬╗
рд╕рд╛рдордЧреНрд░реА┬╗
рдЕрдВрд╢рдХреВрдкрди рдХреЗ рд▓рд┐рдП рдХреВрдкрди рдкрд░ 20% рдХреА рдЫреВрдЯ -
рдЙрдкрд╣рд╛рд░рдкреБрдирд╢реНрдЪ: рдкреБрд╕реНрддрдХ рдХреА рд▓рд╛рдЧрдд рдХрд╛ 7% рдирдИ рдХрдВрдкреНрдпреВрдЯрд░ рдкреБрд╕реНрддрдХреЛрдВ рдХреЗ рдЕрдиреБрд╡рд╛рдж рдореЗрдВ рдЬрд╛рдПрдЧрд╛, рдЫрдкрд╛рдИ рдШрд░ рдХреЛ рд╕реМрдВрдкреА рдЧрдИ рдкреБрд╕реНрддрдХреЛрдВ рдХреА рд╕реВрдЪреА
рдпрд╣рд╛рдВ рд╣реИ ред