PyCon JP 2022 2022/10/14
業務改善の面白さ 毎日更新されるビジュアルコンテンツの差分を わかりやすくするためのプロトタイプを作るまで
1ۀվળͷ໘ന͞ຖߋ৽͞ΕΔϏδϡΞϧίϯςϯπͷࠩΛΘ͔Γ͘͢͢ΔͨΊͷϓϩτλΠϓΛ࡞Δ·Ͱຊܦࡁ৽ฉࣾɹத ສᣦಸPyCon JP 2022 2022/10/14
View Slide
2Marina Nakagawaຊܦࡁ৽ฉࣾͷΤϯδχΞܦϏδϡΞϧσʔλͷίϯςϯπ੍࡞ ΠϯϑϥपΓͷվળͳͲͳͲࣗಈԽ͕͖Ͱ͢ʂ
3ຊ͢͜ͱఆظతʹߋ৽͞ΕΔίϯςϯπͷ՝ܦϏδϡΞϧσʔλͱ123 ࠩݕͷϓϩτλΠϓΛ࡞Δ݁Ռͱ·ͱΊ4
4ܦϏδϡΞϧσʔλͱ1
5
6จষ ਤઆ σʔλ Πϥετ ࣸਅ͋ΒΏΔදݱΛۦͯ͠etc…χϡʔεΛΘ͔Γ͑͘͢Δ
7https://vdata.nikkei.com/newsgraphics/sanin2022-analysis/
8https://vdata.nikkei.com/newsgraphics/party-poll-votes-map/
9https://vdata.nikkei.com/newsgraphics/coronavirus-world-map/
10https://vdata.nikkei.com/newsgraphics/clear-accounting/clear-accounting/
11https://vdata.nikkei.com/
12ɾײతʹΘ͔Γ͘͢ɺ࣌ؒͰಡΊΔίϯςϯπɾैདྷͷใಓදݱΛਐԽͤ͞ΔࢼΈɾϢʔβʔʹͱཱͬͯͭίϯςϯπɾଉͷ͍ίϯςϯπɾطଘͷํ๏Ҏ֎ͷίϯςϯπͷྲྀ௨ํ๏ͱϊϋͦΕΒΛ࡞Δ͕ܦϏδϡΞϧσʔλ
13هऀ ͑Δ͖͜ͱσβΠφʔ͑ํΤϯδχΞ ͑ΔͨΊͷΈ
14هऀ ͑Δ͖͜ͱσβΠφʔ͑ํΤϯδχΞ ͑ΔͨΊͷΈ
15هऀ هࣄίϯςϯπͷ༰ɾσʔλσβΠφʔίϯςϯπͷઃܭɾσβΠϯΤϯδχΞ ৴ͷΈ Ϣʔβʔ͔ΒͷΠϯλϥΫγϣϯΛؚΉ࡞Γ
16هऀ σβΠφʔ ΤϯδχΞ
17ఆظతʹߋ৽͞ΕΔίϯςϯπͷ՝2
18ఆظతʹߋ৽͞ΕΔίϯςϯπͷجຊతͳ੍࡞ͷྲྀΕ
هऀνʔϜεϓϨουγʔτͰຖσʔλूܭˍνΣοΫهऀνʔϜͷऀ͕ެ։Λஅ$*Λ༻͍ͨσϓϩΠϑϩʔͱҟͳΔϑϩʔͰຊ൪ʹө
هऀνʔϜεϓϨουγʔτͰຖσʔλूܭˍνΣοΫهऀνʔϜͷऀ͕ެ։Λஅهऀ͕Λ࣋ͭσʔλجຊతʹຖߋ৽͞ΕΔ
σβΠφʔɾΤϯδχΞνʔϜվम͕͋Δ߹(JU)VCͰϦιʔεཧ$*ͰϦϦʔε
σβΠφʔɾΤϯδχΞνʔϜվम͕͋Δ߹(JU)VCͰϦιʔεཧ$*ͰϦϦʔε࣌ظʹΑͬͯݟͤΔσʔλݟͤํΛมߋ͢Δͱ͖ʹߋ৽
هऀνʔϜσβΠφʔɾΤϯδχΞνʔϜεϓϨουγʔτͰຖσʔλूܭˍνΣοΫվम͕͋Δ߹(JU)VCͰϦιʔεཧ$*ͰϦϦʔεهऀνʔϜͷσʔλͱσβΠφʔɾΤϯδχΞνʔϜͷՌ͕߹Θ͞Δͷຊ൪ڥ˞ͪΖΜ։ൃڥଘࡏ͢Δ
26
ࠓͷάϥϑߋ৽͞Ε͍ͯΔʁهࣄίϯςϯπͷࣈਖ਼͘͠දࣔ͞Ε͍ͯΔʁάϧʔϓԽ͞Εͨԣάϥϑେৎʁେ෯վमͨ͠ͱ͜Ζ͖ͪΜͱදࣔ͞Ε͍ͯΔʁߋ৽͞Ε͍ͯΔʁ
ࠓͷάϥϑߋ৽͞Ε͍ͯΔʁهࣄίϯςϯπͷࣈਖ਼͘͠දࣔ͞Ε͍ͯΔʁάϧʔϓԽ͞Εͨԣάϥϑେৎʁେ෯վमͨ͠ͱ͜Ζ͖ͪΜͱදࣔ͞Ε͍ͯΔʁຖߋ৽͞ΕΔσʔλܥߋ৽͞Ε͍ͯΔʁ
ࠓͷάϥϑߋ৽͞Ε͍ͯΔʁهࣄίϯςϯπͷࣈਖ਼͘͠දࣔ͞Ε͍ͯΔʁάϧʔϓԽ͞Εͨԣάϥϑେৎʁେ෯վमͨ͠ͱ͜Ζ͖ͪΜͱදࣔ͞Ε͍ͯΔʁվम࣌ʹߋ৽͞ΕΔܥ
ࠓͷάϥϑߋ৽͞Ε͍ͯΔʁهࣄίϯςϯπͷࣈਖ਼͘͠දࣔ͞Ε͍ͯΔʁάϧʔϓԽ͞Εͨԣάϥϑେৎʁେ෯վमͨ͠ͱ͜Ζ͖ͪΜͱදࣔ͞Ε͍ͯΔʁ֬ೝ͢ΔϙΠϯτ͕ଟ͍&ݟΔϙΠϯτ͕ҟͳΔใಓػؔͱͯ͠σʔλͷνΣοΫݫ͘͢͠Δඞཁ͕͋Δ͕ɾɾɾ
31
32
33diff!!!!(͜ΕσΟϨΫλʔ͕ਏ͍)
34diffؒҧ͍୳͠
35diffؒҧ͍୳͠
36࠷ऴతͳஅίϯϐϡʔλͰͳ͘ਓ͕ؒߦ͏͕ͤΊͯ֬ೝ͢ΔՕॴ͕໌֬ʹͳΕ͍͍ͷʹɾɾɾɾ
37ͦ͏ͩʂϏδϡΞϧϦάϨογϣϯςετΛԠ༻ͯ͠͏·͍͜ͱΈԽͰ͖ͳ͍ͩΖ͏͔ʁʁʁ
38ࠩݕͷϓϩτλΠϓΛ࡞Δ3
39Try1ϏδϡΞϧϦάϨογϣϯςετπʔϧreg-suitͰͬͯΈΑ͏
40https://github.com/reg-viz/reg-suitΑΓҾ༻
NBTUFSϒϥϯνNBTUFS͔Βͬͨ࣌ͷϖʔδQVTIͯ͠ߋ৽͞Εͨϖʔδൺֱͯࠩ͠Λग़͢
(JU)VCʹQVTI͢Δ$*্ͰϖʔδͷεΫϦʔϯγϣοτΛ࡞SFHTVJUͰεΫϦʔϯγϣοτೖͬͨσΟϨΫτϦΛࢦఆ4ʹੜͨ͠ϖʔδΛ্͛Δ(JU)VCͷίϝϯτʹ௨͕ඈͿ
(JU)VCʹQVTI͢Δ$*্ͰϖʔδͷεΫϦʔϯγϣοτΛ࡞SFHTVJUͰεΫϦʔϯγϣοτೖͬͨσΟϨΫτϦΛࢦఆ4ʹੜͨ͠ϖʔδΛ্͛Δ(JU)VCͷίϝϯτʹ௨͕ඈͿؤுͬͯίʔυΛॻ͘ͷ͚ͩ͜͜ʂ
(JU)VCʹQVTI͢Δ$*্ͰϖʔδͷεΫϦʔϯγϣοτΛ࡞SFHTVJUͰεΫϦʔϯγϣοτೖͬͨσΟϨΫτϦΛࢦఆ4ʹੜͨ͠ϖʔδΛ্͛Δ(JU)VCͷίϝϯτʹ௨͕ඈͿ͜ΕҎ߱SFHTVJU͕ࣗಈͰͬͯ͘Ε·͢
13্ʹϦάϨογϣϯςετͷ݁ՌΛදࣔ͢ΔػೳEJffͷϨϙʔτࣗಈੜͰ͖Δ
ઃఆͨ͠4ʹϨϙʔτ͕ੜ͞ΕΔҰཡͱͳͬͯΘ͔Γ͍͢
ࠩͷݟͤํύλʔϯ༻ҙ͞Ε͍ͯΔ
48͏·͍͔͘ͳ͔ͬͨϙΠϯτ1͜ͷίϯςϯπͰreg-suitΛ͑ͳ͍ࣄ͕͋ͬͨ
(JU)VCͰཧ͍ͯ͠ͳ͍ͷදࣔ͢Δσʔλࣗମ εϓϨουγʔτͰཧ(JU)VCͰཧ͍ͯ͠Δͷ)5.-$44ը૾ͳͲͷϦιʔε
هऀνʔϜσβΠφʔɾΤϯδχΞνʔϜεϓϨουγʔτͰຖσʔλूܭˍνΣοΫվम͕͋Δ߹(JU)VCͰϦιʔεཧ$JSDMF$*ͰϦϦʔεهऀνʔϜͷσʔλͱσβΠφʔɾΤϯδχΞνʔϜͷՌ͕߹Θ͞Δͷຊ൪ڥ˞ͪΖΜ։ൃڥଘࡏ͢ΔهऀνʔϜͷऀ͕ެ։Λஅ
هऀνʔϜσβΠφʔɾΤϯδχΞνʔϜεϓϨουγʔτͰຖσʔλूܭˍνΣοΫվम͕͋Δ߹(JU)VCͰϦιʔεཧ$JSDMF$*ͰϦϦʔεຖͷσʔλूܭͨ݁͠Ռ͕(JU)VCͰཧ͞Ε͍ͯͳ͍
هऀνʔϜσβΠφʔɾΤϯδχΞνʔϜεϓϨουγʔτͰຖσʔλूܭˍνΣοΫվम͕͋Δ߹(JU)VCͰϦιʔεཧ$JSDMF$*ͰϦϦʔεຊ൪ڥͷϖʔδͰࠓݱࡏදࣔ͞Ε͍ͯΔͷͱաڈදࣔ͞Ε͍ͯͨͷΛൺֱ͍ͨ͠
53͏·͍͔͘ͳ͔ͬͨϙΠϯτ2ຊʹͬͯΒ͑Δ͔࣮༻ੑͷݒ೦- GitHubʹ͔͠௨͕͜ͳ͍ɻ- هऀʹGitHubΞΧϯτ͕ඞཁ- ࠩΛݟΔ·Ͱͷ4ΫϦοΫͷนΛӽ͑Δ- Slack νϟϯωϧ,GitHubͷPR,reg-suit,reg-suitͷத
54͏·͍͔͘ͳ͔ͬͨϙΠϯτ2ຊʹͬͯΒ͑Δ͔࣮༻ੑͷݒ೦- GitHubʹ͔͠௨͕͜ͳ͍ɻ- هऀʹGitHubΞΧϯτ͕ඞཁ- ࠩΛݟΔ·Ͱͷ4ΫϦοΫͷนΛӽ͑Δ- Slack νϟϯωϧ,GitHubͷPR,reg-suit,reg-suitͷதຊʹճΫϦοΫͯ͘͠ΕΔʁʁʁΘ͟Θ͟ݟΔͷΊΜͲ͘͘͞ͳ͍ʁʁʁ
55͜͏ͳͬͨΒ͍͍ͳͱໝͯͨ͜͠ͱNikkei————————————————௨νϟϯωϧ௨bot1ClickͲΜͳ৬छͰ͚ͩ͜͜ݟ͓͚͍͍ͯʂͱ͍͏ঢ়ଶΛ࡞Γ͍ͨ————————————
56͜͏ͳͬͨΒ͍͍ͳͱໝͯͨ͜͠ͱNikkei————————————————௨νϟϯωϧ௨bot1ClickͲΜͳ৬छͰ͚ͩ͜͜ݟ͓͚͍͍ͯʂঢ়ଶΛ࡞Γ͍ͨ֬ೝ͢Δ͖Օॴ͕໌֬ʹʂ࠷ऴతͳਓؒͷஅͷิॿʹͳΔʂ(ͣ)
57ཁ݅Λߟ͑ΔɾهऀνʔϜଆ͕σʔλΛߋ৽͢Δͱ͖ʹɺࣗಈͰલͷঢ়ଶͱࠓͷঢ়ଶͱͦͷ͕ࠩදࣔ͢Δɾ৬छΘͣɺ୭͕ͦͷࠩΛ֬ೝ͢Δ͜ͱ͕Ͱ͖Δঢ়ଶʹ͢Δɾ࿈བྷखஈʹSlackΛར༻͍ͯ͠ΔͷͰɺͦͷ݁Ռ͕Slackʹ·ͱΊΒΕΔͱΑ͍
58αΫοͱϓϩτλΠϓΛ࡞ͬͯΈΔSFHTVJUͰֶΜͩ͜ͱΛ׆͔ͯ͠
59ࠩΛݕग़ͯ͠ɺSlackʹԼ͢Δ͘͠ΈΛߟ͑ͨ1.ར༻͢ΔπʔϧϥΠϒϥϦྨΛબఆ͢Δ2.࣮ߦํ๏ΛܾΊΔ3.ൺֱը૾Λ༻ҙ͢Δ4.ը૾ͷߴ͞Λἧ͑ͯɺൺֱՃ͘͢͢͠Δ5.ը૾ͷࠩΛݕग़͢ΔͨΊͷ४උΛ͢Δ6.ը૾ͷࠩΛݕग़͢Δ7.͕ࠩ͋Ε࡞ͨ͠εΫϦʔϯγϣοτΛS3ʹΞοϓϩʔυ͢Δ8.Slackߘ༻ʹը૾Λ߹͢Δ9.Slackʹߘ͢Δ
601.ར༻͢ΔπʔϧϥΠϒϥϦྨΛબఆ͢Δը૾ͰࠩΛݕग़͢ΔͳΒ →OpenCV͕͑ͯWebը૾ΛεΫγϣ͢ΔͳΒˠWebࣗಈԽπʔϧͰεΫγϣΛͱΖ͏աڈը૾Λอଘ͢ΔͳΒˠS3͕ྑͦ͞͏·͋ɺϓϩτλΠϓͩͬ͠͞ͱPythonͰࢼͦ͏ʂҰ୴Google ColaboratoryͰϛχϛχϓϩτλΠϓΛ࡞ͬͯΈΔ→ΠέΔʂΛ֬৴
612.࣮ߦํ๏ΛܾΊΔGoogle Colaboratory Ͱܾ·ͬͨ࣌ؒʹىಈͰ͖ͨΒ͍͍ͷʹࠓͷܖͩͱͰ͖ͳ͔ͬͨͷͰGitHubͱ࿈ܞ͍ͯ͠ΔCircleCIͰɺσʔλܗͱө͕ऴΘΔޕޙ̑࣌ʹ࣮ߦ͢Δ͜ͱʹ※Pro+ͩͱεέδϡʔϧػೳ͕͋Γ·͢(https://github.com/googlecolab/colabtools/wiki/Scheduled-notebooks)
$JSDMF$*ͰϖʔδͷεΫγϣΛੜ4͔Βલճߋ৽࣌ʹࡱӨͨ͠εΫγϣΛμϯϩʔυ623.ൺֱը૾Λ༻ҙ͢Δ
$JSDMF$*ͰϖʔδͷεΫγϣΛੜ4͔Βલճߋ৽࣌ʹࡱӨͨ͠εΫγϣΛμϯϩʔυ633.ൺֱը૾Λ༻ҙ͢Δ
64SCREENSHOT_WIDTH_SIZE = 800SCREENSHOT_HIGHT_SIZE = 12000TARGET_URL = "https://vdata.nikkei.com/newsgraphics/coronavirus-japan-vaccine-status/"WAIT_TIME = 10# ΣϒυϥΠόʔͱΦϓγϣϯͷઃఆoptions = webdriver.ChromeOptions()options.add_argument('--headless')options.add_argument('--incognito')options.add_argument('--no-sandbox')options.add_argument('--disable-dev-shm-usage')driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)driver.get(TARGET_URL)driver.set_window_size(SCREENSHOT_WIDTH_SIZE, SCREENSHOT_HIGHT_SIZE)time.sleep(WAIT_TIME)driver.save_screenshot("test-reports/current_page_screenshot.png")※ίʔυҰ෦ൈਮ
$JSDMF$*ͰϖʔδͷεΫγϣΛੜ4͔Βલճߋ৽࣌ʹࡱӨͨ͠εΫγϣΛμϯϩʔυ653.ൺֱը૾Λ༻ҙ͢Δ
66# S3ʹΞοϓϩʔυimport boto3# S3ͷϑΝΠϧμϯϩʔυɺΞοϓϩʔυͷઃఆclient = boto3.client('s3',aws_access_key_id= {AWS ΞΫηεΩʔID},aws_secret_access_key= {AWS γʔΫϨοτΩʔ},)client.download_file('{S3໊}','{S3ͷύε໊}/screenshot.png','test-reports/past_page_screenshot.png')※ίʔυҰ෦ൈਮ
Γͳ͍͞0QFO$7Ͱന৭෦ΛՃͯ͠ௐ4.ը૾ͷߴ͞Λἧ͑ͯɺൺֱՃ͘͢͢͠Δ
68#===============================================#ɹಉ͡αΠζʹͳΔΑ͏ʹԼʹۭനΛೖΕͯϦαΠζ#===============================================color = (255, 255, 255)if img_current.shape[0] <= img_past.shape[0]:bottom = img_past.shape[0] - img_current.shape[0]img_current = cv2.copyMakeBorder(img_current, 0,bottom, 0, 0,cv2.BORDER_CONSTANT,value=color,)else:bottom = img_current.shape[0] - img_past.shape[0]img_past = cv2.copyMakeBorder(img_past, 0, bottom, 0, 0,cv2.BORDER_CONSTANT,value=color,)※ίʔυҰ෦ൈਮ
มߋલͱมߋޙΛൺֱͯࠩ͠ϚεΫΛ࡞͢Δ5.ը૾ͷࠩΛݕग़͢ΔͨΊͷ४උΛ͢Δ
70#===============================================# ը૾ͷࠩΛ࡞Δ#===============================================fgbg = cv2.bgsegm.createBackgroundSubtractorMOG(history=2)#ϚεΫͷܭࢉfgmask = fgbg.apply(img_current)fgmask = fgbg.apply(img_past)cv2.imwrite('test-reports/mask.png', fgmask)※ίʔυҰ෦ൈਮ
6.ը૾ͷࠩΛΘ͔Γ͘͢͢ΔϚεΫ͚ͩͩͱ͕ࠩΘ͔Βͳ͍ͷͰը૾Λ҉ͯ͘͠ॏͶΔ
72#===============================================# ը૾Λ҉ͯࠩ͘͠ϚεΫΛॏͶɺ# ࠩͷݕग़ͷ݁Ռ͕͔ΔΑ͏ʹग़ྗ͢Δ#===============================================# ݱࡏͷεΫγϣΛগ͠҉͘͢Δimg_result = img_current // 4# ϚεΫͰࠩͷ͋Δͱ͜Ζ͚ͩΛࡌͤΔimg_result[fgmask==255] = (0, 255, 0)cv2.imwrite('test-reports/result.png', img_result)※ίʔυҰ෦ൈਮ
8.Slackߘ༻ʹը૾Λ߹͢Δ4MBDLͰ௨ͨ͠ͱ͖ʹΘ͔Γ͍͢Α͏ʹมߋલɺมߋޙɺࠩͷ̏ͭΛ͠߹ΘͤҰͭͷը૾ʹ͢Δ
8.Slackߘ༻ʹը૾Λ߹͢Δ͜͏ͳΔͱɺԿ͕Ͳ͏มΘ͍ͬͯΔͷ͔Θ͔Βͳ͍
75#=============================# ը૾ͷ߹(Slackߘ༻)#=============================percentage_to_resize = 0.5img_summary = cv2.hconcat([img_current, img_past, img_result])img_summary = cv2.resize(img_summary ,(int(img_summary.shape[1] * percentage_to_resize),int(img_summary.shape[0] * percentage_to_resize)))cv2.imwrite('test-reports/summary.png', img_summary)※ίʔυҰ෦ൈਮ
7.͕ࠩ͋Ε࣍ճͷൺֱ༻ʹ࡞ͨ͠εΫϦʔϯγϣοτΛS3ʹΞοϓϩʔυ͢ΔԿ͠ͳ͍ࠩ͋Γʂ4ࠩͳ͠ʂ
77#=======================================================# S3ʹը૾ΛΞοϓϩʔυ͢Δ#=======================================================client.upload_file('test-reports/current_page_screenshot.png','{S3໊}',‘{S3ͷύε໊}/screenshot.png')※ίʔυҰ෦ൈਮ
9.Slackʹߘ͢ΔҰຕʹ·ͱΊͨํ͕ݟ͍͢ʂ
มߋޙ มߋલ ࠩ
80diffؒҧ͍୳͠(αϙʔτ͖)
81#======================================================# ͕ࠩ͋Εfiles uploadAPIͰSlackʹ௨#======================================================def postMessageWithFiles(message, fileList, channel):slack_client = slack_sdk.WebClient(token=SLACK_TOKEN)for file in fileList:upload = slack_client.files_upload(file=file, filename=file)message = message + ”<“ + upload['file']['permalink'] + "| >"outPut = slack_client.chat_postMessage(channel = channel,text = message)#=======================================================# มߋΛݕͨ࣌͠#=======================================================if np.array_equal(img_current, img_past):postMessageWithFiles(message = " `ίϩφຊϫΫνϯίϯςϯπͷࠩΛݕ͠·ͨ͠ʂ”,fileList = ['test-reports/summary.png'],channel = "{௨͍ͨ͠νϟϯωϧ໊}",)※ίʔυҰ෦ൈਮ
82※ίʔυҰ෦ൈਮ͠ະདྷͰɺࠩΛݟ͍ͨϖʔδ͕ෳʹ૿͑ͨ࣌
83݁Ռͱ·ͱΊ3
84هऀ σβΠφʔ ΤϯδχΞศརͳΈΛ͋Γ͕ͱ͏͍͟͝·͢໌Β͔ʹ͓͔͍͠Օॴ͕ͳ͍͔؆୯ʹผͰ͖Δͷ͋Γ͕͍ͨσʔλͷܻʹΑͬͯϨΠΞτ͕มΘΔཁૉ͕͋Δɻҙਤ͍ͯ͠ͳ͍ϨΠΞτʹͳ͍ͬͯͳ͍͔͕ҰͰ͔Δͷ͕ྑ͍ಋೖޙͷ
85هऀ σβΠφʔ ΤϯδχΞศརͳΈΛ͋Γ͕ͱ͏͍͟͝·͢໌Β͔ʹ͓͔͍͠Օॴ͕ͳ͍͔؆୯ʹผͰ͖Δͷ͋Γ͕͍ͨσʔλͷܻʹΑͬͯϨΠΞτ͕มΘΔཁૉ͕͋Δɻҙਤ͍ͯ͠ͳ͍ϨΠΞτʹͳ͍ͬͯͳ͍͔͕ҰͰ͔Δͷ͕ྑ͍ಋೖޙͷͰɾɾɾɾͩΜͩΜݟΒΕͳ͘ͳͬͯ͠·͏
86هऀ σβΠφʔ ΤϯδχΞޕޙ̑࣌ఆظ࣮ߦ͡Όͳͯ͘ग़͢લʹνΣοΫͰ͖ΔΑ͏ͳػߏ͕Α͔ͬͨվળϙΠϯτ
هऀνʔϜσβΠφʔɾΤϯδχΞνʔϜεϓϨουγʔτͰຖσʔλूܭˍνΣοΫվम͕͋Δ߹(JU)VCͰϦιʔεཧ$*ͰϦϦʔε͜ͷ࣌Ͱެ։ͱಉ࣌ʹ-BNCEBΛىಈ͞Βʹվળ͢ΔͳΒ
88هऀ σβΠφʔ ΤϯδχΞผͷϒϥβϞόΠϧαΠζͳͲ͍Ζ͍Ζͳը໘ύλʔϯͰݕূͰ͖ͨ΄͏͕҆৺ײ͕ߴ·ΔɻվળϙΠϯτίϯςϯπͷ্෦ͷจষ͕มߋ͞Εͯɺߦ͕มΘͬͯ͠·͏ͱϨΠΞτ͕ͯ͢ԼʹͣΕͨͱݕग़͞ΕΔͱ͍͏߹͕͋Δɻ
هऀνʔϜσβΠφʔɾΤϯδχΞνʔϜεϓϨουγʔτͰຖσʔλूܭˍνΣοΫվम͕͋Δ߹(JU)VCͰϦιʔεཧ$*ͰϦϦʔεάϥϑͷը૾ͷݕग़͚ͩʹಛԽ͞Βʹվળ͢ΔͳΒ
90Pythonͷศར͞Γ͍ͨ͜ͱʹରͯ͠ɺπʔϧ͕ἧ͍ͬͯͯेߦͰ͙͢ʹࢼ͢͜ͱ͕Ͱ͖Δշద͕͞࠷ߴ
91هऀ σβΠφʔ ΤϯδχΞۀվળͷ໘ന͍ϙΠϯτ͍͍ͭͬͯΔಉ͡ܗࣜ֬ೝ࡞ۀ͍ͭͬͯΔ͚Ͳຊ൪Ͱຖ֬ೝ͢Δ͔͠ͳ͍ͷ͔ͳʙ
92هऀ σβΠφʔ ΤϯδχΞۀվળͷ໘ന͍ϙΠϯτ͍͍ͭͬͯΔಉ͡ܗࣜ֬ೝ࡞ۀ͍ͭͬͯΔ͚Ͳຊ൪Ͱຖ֬ೝ͢Δ͔͠ͳ͍ͷ͔ͳʙʮ͜͏ͳͬͨΒ͍͍ͷʹͳʙʯɺࠔ͍ͬͯΔຊਓ͔ΒϐϯϙΠϯτͰདྷͳ͍
93هऀ σβΠφʔ ΤϯδχΞۀվળͷ໘ന͍ϙΠϯτͲΜͳײ͡Ͱ࡞ۀ͍ͯ͠ΔΜͰ͔͢ʁʁ
94هऀ σβΠφʔ ΤϯδχΞۀվળͷ໘ന͍ϙΠϯτ͜Μͳखஈ͋Γ·͢Αʁ͜͏ͨ͠Β͍͍͔ʁͦΜͳ͜ͱͰ͖ΔͷʁʁʂʂศརʂͦΕ΄͍͠ʂ
95·ͱΊνʔϜͷಇ͖ํΛ͞Βʹշదʹ͢ΔͨΊͷछ͕ʑͷίϛϡχέʔγϣϯͷதʹ͋Δ͔ʁʂ
96https://hack.nikkei.com/
97͋Γ͕ͱ͏͍͟͝·ͨ͠