$30 off During Our Annual Pro Sale. View Details »

業務改善の面白さ~毎日更新されるビジュアルコンテンツの差分を わかりやすくするためのプロトタイプを作るまで~

業務改善の面白さ~毎日更新されるビジュアルコンテンツの差分を わかりやすくするためのプロトタイプを作るまで~

PyCon JP
2022 2022/10/14

業務改善の面白さ
毎日更新されるビジュアルコンテンツの差分を
わかりやすくするためのプロトタイプを作るまで

Marina Nakagawa

October 13, 2022
Tweet

More Decks by Marina Nakagawa

Other Decks in Technology

Transcript

  1. 1 ۀ຿վળͷ໘ന͞ ຖ೔ߋ৽͞ΕΔϏδϡΞϧίϯςϯπͷࠩ෼Λ Θ͔Γ΍͘͢͢ΔͨΊͷϓϩτλΠϓΛ࡞Δ·Ͱ ೔ຊܦࡁ৽ฉࣾɹத઒ ສᣦಸ PyCon JP 2022 2022/10/14

  2. 2 Marina Nakagawa ೔ຊܦࡁ৽ฉࣾͷΤϯδχΞ ೔ܦϏδϡΞϧσʔλͷίϯςϯπ੍࡞
 ΠϯϑϥपΓͷվળͳͲͳͲ ࣗಈԽ͕޷͖Ͱ͢ʂ

  3. 3 ຊ೔࿩͢͜ͱ ఆظతʹߋ৽͞ΕΔίϯςϯπͷ՝୊ ೔ܦϏδϡΞϧσʔλͱ͸ 1 2 3 ࠩ෼ݕ஌ͷϓϩτλΠϓΛ࡞Δ ݁Ռͱ·ͱΊ 4

  4. 4 ೔ܦϏδϡΞϧσʔλͱ͸ 1

  5. 5

  6. 6 จষ ਤઆ σʔλ Πϥετ ࣸਅ ͋ΒΏΔදݱΛۦ࢖ͯ͠ etc… χϡʔεΛΘ͔Γ΍͘͢఻͑Δ

  7. 7 https://vdata.nikkei.com/newsgraphics/sanin2022-analysis/

  8. 8 https://vdata.nikkei.com/newsgraphics/party-poll-votes-map/

  9. 9 https://vdata.nikkei.com/newsgraphics/coronavirus-world-map/

  10. 10 https://vdata.nikkei.com/newsgraphics/clear-accounting/clear-accounting/

  11. 11 https://vdata.nikkei.com/

  12. 12 ɾ௚ײతʹΘ͔Γ΍͘͢ɺ୹࣌ؒͰಡΊΔίϯςϯπ ɾैདྷͷใಓදݱΛਐԽͤ͞ΔࢼΈ ɾϢʔβʔʹͱͬͯ໾ཱͭίϯςϯπ ɾଉͷ௕͍ίϯςϯπ ɾطଘͷํ๏Ҏ֎ͷίϯςϯπͷྲྀ௨ํ๏ͱϊ΢ϋ΢ ͦΕΒΛ࡞Δ৔͕ ೔ܦϏδϡΞϧσʔλ

  13. 13 هऀ
 ఻͑Δ΂͖͜ͱ σβΠφʔ ఻͑ํ ΤϯδχΞ 
 ఻͑ΔͨΊͷ࢓૊Έ

  14. 14 هऀ
 ఻͑Δ΂͖͜ͱ σβΠφʔ ఻͑ํ ΤϯδχΞ 
 ఻͑ΔͨΊͷ࢓૊Έ

  15. 15 هऀ
 هࣄίϯςϯπͷ಺༰ɾσʔλ σβΠφʔ ίϯςϯπͷઃܭɾσβΠϯ ΤϯδχΞ 
 ഑৴ͷ࢓૊Έ
 Ϣʔβʔ͔ΒͷΠϯλϥΫγϣϯΛؚΉ࡞Γ

  16. 16 هऀ
 σβΠφʔ ΤϯδχΞ

  17. 17 ఆظతʹߋ৽͞ΕΔίϯςϯπͷ՝୊ 2

  18. 18 ఆظతʹߋ৽͞ΕΔίϯςϯπͷ جຊతͳ੍࡞ͷྲྀΕ

  19. None
  20. هऀνʔϜ εϓϨουγʔτͰ ຖ೔σʔλूܭˍνΣοΫ هऀνʔϜͷ੹೚ऀ͕ެ։Λ൑அ $*Λ༻͍ͨσϓϩΠϑϩʔͱ͸ ҟͳΔϑϩʔͰຊ൪ʹ൓ө

  21. هऀνʔϜ εϓϨουγʔτͰ ຖ೔σʔλूܭˍνΣοΫ هऀνʔϜͷ ੹೚ऀ͕ެ։Λ൑அ هऀ͕੹೚Λ࣋ͭσʔλ͸ جຊతʹຖ೔ߋ৽͞ΕΔ

  22. σβΠφʔɾΤϯδχΞνʔϜ վम͕͋Δ৔߹ (JU)VCͰϦιʔε؅ཧ $*ͰϦϦʔε

  23. σβΠφʔɾΤϯδχΞνʔϜ վम͕͋Δ৔߹ (JU)VCͰϦιʔε؅ཧ $*ͰϦϦʔε ࣌ظʹΑͬͯݟͤΔσʔλ΍ ݟͤํΛมߋ͢Δͱ͖ʹߋ৽

  24. هऀνʔϜ σβΠφʔɾΤϯδχΞνʔϜ εϓϨουγʔτͰ ຖ೔σʔλूܭˍνΣοΫ վम͕͋Δ৔߹ (JU)VCͰϦιʔε؅ཧ $*ͰϦϦʔε هऀνʔϜͷσʔλͱ σβΠφʔɾΤϯδχΞνʔϜͷ੒Ռ෺͕ ߹Θ͞Δͷ͸ຊ൪؀ڥ

    ˞΋ͪΖΜ։ൃ؀ڥ΋ଘࡏ͢Δ
  25. None
  26. 26

  27. ࠓ೔ͷάϥϑ͸ ߋ৽͞Ε͍ͯΔʁ هࣄίϯςϯπͷ ਺ࣈ͸ਖ਼͘͠ දࣔ͞Ε͍ͯΔʁ άϧʔϓԽ͞Εͨ ԣάϥϑ͸େৎ෉ʁ େ෯վमͨ͠ͱ͜Ζ͸ ͖ͪΜͱදࣔ͞Ε͍ͯΔʁ ೔෇͸

    ߋ৽͞Ε͍ͯΔʁ
  28. ࠓ೔ͷάϥϑ͸ ߋ৽͞Ε͍ͯΔʁ هࣄίϯςϯπͷ ਺ࣈ͸ਖ਼͘͠ දࣔ͞Ε͍ͯΔʁ άϧʔϓԽ͞Εͨ ԣάϥϑ͸େৎ෉ʁ େ෯վमͨ͠ͱ͜Ζ͸ ͖ͪΜͱදࣔ͞Ε͍ͯΔʁ ຖ೔ߋ৽͞ΕΔ

    σʔλܥ ೔෇͸ ߋ৽͞Ε͍ͯΔʁ
  29. ࠓ೔ͷάϥϑ͸ ߋ৽͞Ε͍ͯΔʁ هࣄίϯςϯπͷ ਺ࣈ͸ਖ਼͘͠ දࣔ͞Ε͍ͯΔʁ άϧʔϓԽ͞Εͨ ԣάϥϑ͸େৎ෉ʁ େ෯վमͨ͠ͱ͜Ζ͸ ͖ͪΜͱදࣔ͞Ε͍ͯΔʁ վम࣌ʹ

    ߋ৽͞ΕΔܥ
  30. ࠓ೔ͷάϥϑ͸ ߋ৽͞Ε͍ͯΔʁ هࣄίϯςϯπͷ ਺ࣈ͸ਖ਼͘͠ දࣔ͞Ε͍ͯΔʁ άϧʔϓԽ͞Εͨ ԣάϥϑ͸େৎ෉ʁ େ෯վमͨ͠ͱ͜Ζ͸ ͖ͪΜͱදࣔ͞Ε͍ͯΔʁ ֬ೝ͢ΔϙΠϯτ͕ଟ͍

    & ݟΔϙΠϯτ͕ҟͳΔ ใಓػؔͱͯ͠͸σʔλͷνΣοΫ͸ݫ͘͢͠Δඞཁ͕͋Δ͕ɾɾɾ
  31. 31

  32. 32

  33. 33 ໨diff!!!! (͜Ε͸σΟϨΫλʔ͕ਏ͍)

  34. 34 ໨diffؒҧ͍୳͠

  35. 35 ໨diffؒҧ͍୳͠

  36. 36 ࠷ऴతͳ൑அ͸ίϯϐϡʔλͰ͸ͳ͘ਓ͕ؒߦ͏͕ ͤΊͯ ֬ೝ͢ΔՕॴ͕໌֬ʹͳΕ͹͍͍ͷʹɾɾɾɾ

  37. 37 ͦ͏ͩʂ ϏδϡΞϧϦάϨογϣϯςετΛԠ༻ͯ͠ ͏·͍͜ͱ࢓૊ΈԽͰ͖ͳ͍ͩΖ͏͔ʁʁʁ

  38. 38 ࠩ෼ݕ஌ͷϓϩτλΠϓΛ࡞Δ 3

  39. 39 Try1 ϏδϡΞϧϦάϨογϣϯςετπʔϧreg-suit Ͱ΍ͬͯΈΑ͏

  40. 40 https://github.com/reg-viz/reg-suitΑΓҾ༻

  41. NBTUFSϒϥϯν NBTUFS͔Β ੾ͬͨ࣌఺ͷϖʔδ QVTIͯ͠ ߋ৽͞Εͨϖʔδ ൺֱͯࠩ͠෼Λग़͢

  42. (JU)VCʹQVTI͢Δ $*্Ͱ ϖʔδͷεΫϦʔϯγϣοτΛ࡞੒ SFHTVJUͰ εΫϦʔϯγϣοτೖͬͨσΟϨΫτϦΛࢦఆ 4ʹੜ੒ͨ͠ϖʔδΛ্͛Δ (JU)VCͷίϝϯτʹ ௨஌͕ඈͿ

  43. (JU)VCʹQVTI͢Δ $*্Ͱ ϖʔδͷεΫϦʔϯγϣοτΛ࡞੒ SFHTVJUͰ εΫϦʔϯγϣοτೖͬͨσΟϨΫτϦΛࢦఆ 4ʹੜ੒ͨ͠ϖʔδΛ্͛Δ (JU)VCͷίϝϯτʹ ௨஌͕ඈͿ ؤுͬͯίʔυΛॻ͘ͷ͸ ͚ͩ͜͜ʂ

  44. (JU)VCʹQVTI͢Δ $*্Ͱ ϖʔδͷεΫϦʔϯγϣοτΛ࡞੒ SFHTVJUͰ εΫϦʔϯγϣοτೖͬͨσΟϨΫτϦΛࢦఆ 4ʹੜ੒ͨ͠ϖʔδΛ্͛Δ (JU)VCͷίϝϯτʹ ௨஌͕ඈͿ ͜ΕҎ߱͸ SFHTVJU͕ࣗಈͰ΍ͬͯ͘Ε·͢

  45. 13্ʹϦάϨογϣϯςετͷ ݁ՌΛදࣔ͢Δػೳ EJ ff ͷϨϙʔτ΋ ࣗಈੜ੒Ͱ͖Δ

  46. ઃఆͨ͠4ʹ Ϩϙʔτ͕ੜ੒͞ΕΔ ҰཡͱͳͬͯΘ͔Γ΍͍͢

  47. ࠩ෼ͷݟͤํ΋ ύλʔϯ༻ҙ͞Ε͍ͯΔ

  48. 48 ͏·͍͔͘ͳ͔ͬͨϙΠϯτ1 ͜ͷίϯςϯπͰreg-suitΛ࢖͑ͳ͍ࣄ৘͕͋ͬͨ

  49. (JU)VCͰ؅ཧ͍ͯ͠ͳ͍΋ͷ දࣔ͢Δσʔλࣗମ͸ 
 εϓϨουγʔτͰ؅ཧ (JU)VCͰ؅ཧ͍ͯ͠Δ΋ͷ )5.-΍$44΍ը૾ͳͲͷϦιʔε

  50. هऀνʔϜ σβΠφʔɾΤϯδχΞνʔϜ εϓϨουγʔτͰ ຖ೔σʔλूܭˍνΣοΫ վम͕͋Δ৔߹ (JU)VCͰϦιʔε؅ཧ $JSDMF$*ͰϦϦʔε هऀνʔϜͷσʔλͱ σβΠφʔɾΤϯδχΞνʔϜͷ੒Ռ෺͕ ߹Θ͞Δͷ͸ຊ൪؀ڥ

    ˞΋ͪΖΜ։ൃ؀ڥ΋ଘࡏ͢Δ هऀνʔϜͷ ੹೚ऀ͕ެ։Λ൑அ
  51. هऀνʔϜ σβΠφʔɾΤϯδχΞνʔϜ εϓϨουγʔτͰ ຖ೔σʔλूܭˍνΣοΫ վम͕͋Δ৔߹ (JU)VCͰϦιʔε؅ཧ $JSDMF$*ͰϦϦʔε ຖ೔ͷσʔλूܭͨ݁͠Ռ͕ (JU)VCͰ؅ཧ͞Ε͍ͯͳ͍

  52. هऀνʔϜ σβΠφʔɾΤϯδχΞνʔϜ εϓϨουγʔτͰ ຖ೔σʔλूܭˍνΣοΫ վम͕͋Δ৔߹ (JU)VCͰϦιʔε؅ཧ $JSDMF$*ͰϦϦʔε ຊ൪؀ڥͷϖʔδͰ ࠓݱࡏදࣔ͞Ε͍ͯΔ΋ͷͱ աڈදࣔ͞Ε͍ͯͨ΋ͷΛൺֱ͍ͨ͠

  53. 53 ͏·͍͔͘ͳ͔ͬͨϙΠϯτ2 ຊ౰ʹ࢖ͬͯ΋Β͑Δ͔࣮༻ੑͷݒ೦ - GitHubʹ͔͠௨஌͕͜ͳ͍ɻ - هऀʹ΋GitHubΞΧ΢ϯτ͕ඞཁ - ࠩ෼ΛݟΔ·Ͱͷ໿4ΫϦοΫͷนΛӽ͑Δ -

    Slack νϟϯωϧ,GitHubͷPR,reg-suit,reg-suitͷத
  54. 54 ͏·͍͔͘ͳ͔ͬͨϙΠϯτ2 ຊ౰ʹ࢖ͬͯ΋Β͑Δ͔࣮༻ੑͷݒ೦ - GitHubʹ͔͠௨஌͕͜ͳ͍ɻ - هऀʹ΋GitHubΞΧ΢ϯτ͕ඞཁ - ࠩ෼ΛݟΔ·Ͱͷ໿4ΫϦοΫͷนΛӽ͑Δ -

    Slack νϟϯωϧ,GitHubͷPR,reg-suit,reg-suitͷத ຊ౰ʹ਺ճΫϦοΫͯ͘͠ΕΔʁʁʁ Θ͟Θ͟ݟΔͷΊΜͲ͘͘͞ͳ͍ʁʁʁ
  55. 55 ͜͏ͳͬͨΒ͍͍ͳͱໝ૝ͯͨ͜͠ͱ Nikkei ———— ———— ———— ———— ௨஌νϟϯωϧ ௨஌bot 1Click

    ͲΜͳ৬छͰ΋ ͚ͩ͜͜ݟ͓͚ͯ͹͍͍ʂ ͱ͍͏ঢ়ଶΛ࡞Γ͍ͨ ———— ———— ————
  56. 56 ͜͏ͳͬͨΒ͍͍ͳͱໝ૝ͯͨ͜͠ͱ Nikkei ———— ———— ———— ———— ௨஌νϟϯωϧ ௨஌bot 1Click

    ͲΜͳ৬छͰ΋ ͚ͩ͜͜ݟ͓͚ͯ͹͍͍ʂ ঢ়ଶΛ࡞Γ͍ͨ ֬ೝ͢Δ΂͖Օॴ͕໌֬ʹʂ ࠷ऴతͳਓؒͷ൑அͷิॿʹͳΔʂ(͸ͣ)
  57. 57 ཁ݅Λߟ͑Δ ɾهऀνʔϜଆ͕σʔλΛߋ৽͢Δͱ͖ʹɺࣗಈͰલͷঢ়ଶͱࠓͷঢ়ଶͱͦͷࠩ෼͕දࣔ͢Δ ɾ৬छ໰Θͣɺ୭΋͕ͦͷࠩ෼Λ֬ೝ͢Δ͜ͱ͕Ͱ͖Δঢ়ଶʹ͢Δ ɾ࿈བྷखஈʹSlackΛར༻͍ͯ͠ΔͷͰɺͦͷ݁Ռ͕Slackʹ·ͱΊΒΕΔͱΑ͍

  58. 58 αΫοͱϓϩτλΠϓΛ ࡞ͬͯΈΔ SFHTVJUͰֶΜͩ͜ͱΛ׆͔ͯ͠

  59. 59 ࠩ෼Λݕग़ͯ͠ɺSlackʹ౤Լ͢Δ͘͠ΈΛߟ͑ͨ 1.ར༻͢Δπʔϧ΍ϥΠϒϥϦྨΛબఆ͢Δ 2.࣮ߦํ๏ΛܾΊΔ 3.ൺֱը૾Λ༻ҙ͢Δ 4.ը૾ͷߴ͞Λἧ͑ͯɺൺֱ΍Ճ޻͠΍͘͢͢Δ 5.ը૾ͷࠩ෼Λݕग़͢ΔͨΊͷ४උΛ͢Δ 6.ը૾ͷࠩ෼Λݕग़͢Δ 7.ࠩ෼͕͋Ε͹࡞੒ͨ͠εΫϦʔϯγϣοτΛS3ʹΞοϓϩʔυ͢Δ 8.Slack౤ߘ༻ʹը૾Λ߹੒͢Δ

    9.Slackʹ౤ߘ͢Δ
  60. 60 1.ར༻͢Δπʔϧ΍ϥΠϒϥϦྨΛબఆ͢Δ ը૾Ͱࠩ෼Λݕग़͢ΔͳΒ →OpenCV͕࢖͑ͯ Webը૾ΛεΫγϣ͢ΔͳΒˠWebࣗಈԽπʔϧͰεΫγϣΛͱΖ͏ աڈը૾Λอଘ͢ΔͳΒˠS3͕ྑͦ͞͏ ·͋ɺϓϩτλΠϓͩͬ͠͞ͱPythonͰࢼͦ͏ʂ Ұ୴Google ColaboratoryͰϛχϛχϓϩτλΠϓΛ࡞ͬͯΈΔ →ΠέΔʂΛ֬৴

  61. 61 2.࣮ߦํ๏ΛܾΊΔ Google Colaboratory Ͱܾ·ͬͨ࣌ؒʹىಈͰ͖ͨΒ͍͍ͷʹ ࠓͷܖ໿ͩͱͰ͖ͳ͔ͬͨͷͰ GitHubͱ࿈ܞ͍ͯ͠ΔCircleCIͰɺ σʔλ੔ܗͱ൓ө͕ऴΘΔޕޙ̑࣌ʹ࣮ߦ͢Δ͜ͱʹ ※Pro+ͩͱεέδϡʔϧػೳ͕͋Γ·͢ (https://github.com/googlecolab/colabtools/wiki/Scheduled-notebooks)

  62. $JSDMF$*Ͱ ϖʔδͷεΫγϣΛੜ੒ 4͔Βલճߋ৽࣌ʹࡱӨͨ͠ εΫγϣΛμ΢ϯϩʔυ 62 3.ൺֱը૾Λ༻ҙ͢Δ

  63. $JSDMF$*Ͱ ϖʔδͷεΫγϣΛੜ੒ 4͔Βલճߋ৽࣌ʹࡱӨͨ͠ εΫγϣΛμ΢ϯϩʔυ 63 3.ൺֱը૾Λ༻ҙ͢Δ

  64. 64 SCREENSHOT_WIDTH_SIZE = 800 SCREENSHOT_HIGHT_SIZE = 12000 TARGET_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") ※ίʔυ͸Ұ෦ൈਮ
  65. $JSDMF$*Ͱ ϖʔδͷεΫγϣΛੜ੒ 4͔Βલճߋ৽࣌ʹࡱӨͨ͠ εΫγϣΛμ΢ϯϩʔυ 65 3.ൺֱը૾Λ༻ҙ͢Δ

  66. 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' ) ※ίʔυ͸Ұ෦ൈਮ
  67. ଍Γͳ͍௕͞͸0QFO$7Ͱ ന৭෦෼Λ௥Ճͯ͠ௐ੔ 4.ը૾ͷߴ͞Λἧ͑ͯɺൺֱ΍Ճ޻͠΍͘͢͢Δ

  68. 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, ) ※ίʔυ͸Ұ෦ൈਮ
  69. มߋલͱมߋޙΛൺֱͯ͠ ࠩ෼ϚεΫΛ࡞੒͢Δ 5.ը૾ͷࠩ෼Λݕग़͢ΔͨΊͷ४උΛ͢Δ

  70. 70 #=============================================== # ը૾ͷࠩ෼Λ࡞Δ #=============================================== fgbg = cv2.bgsegm.createBackgroundSubtractorMOG(history=2) #ϚεΫͷܭࢉ fgmask

    = fgbg.apply(img_current) fgmask = fgbg.apply(img_past) cv2.imwrite('test-reports/mask.png', fgmask) ※ίʔυ͸Ұ෦ൈਮ
  71. 6.ը૾ͷࠩ෼ΛΘ͔Γ΍͘͢͢Δ ϚεΫ͚ͩͩͱࠩ෼͕Θ͔Βͳ͍ͷͰ ը૾Λ҉ͯ͘͠ॏͶΔ

  72. 72 #=============================================== # ը૾Λ҉ͯࠩ͘͠෼ϚεΫΛॏͶɺ # ࠩ෼ͷݕग़ͷ݁Ռ͕෼͔ΔΑ͏ʹग़ྗ͢Δ #=============================================== # ݱࡏͷεΫγϣΛগ͠҉͘͢Δ img_result

    = img_current // 4 # ϚεΫͰࠩ෼ͷ͋Δͱ͜Ζ͚ͩ྘ΛࡌͤΔ img_result[fgmask==255] = (0, 255, 0) cv2.imwrite('test-reports/result.png', img_result) ※ίʔυ͸Ұ෦ൈਮ
  73. 8.Slack౤ߘ༻ʹը૾Λ߹੒͢Δ 4MBDLͰ௨஌ͨ͠ͱ͖ʹΘ͔Γ΍͍͢Α͏ʹ มߋલɺมߋޙɺࠩ෼ͷ̏ͭΛ଍͠߹Θͤ Ұͭͷը૾ʹ͢Δ

  74. 8.Slack౤ߘ༻ʹը૾Λ߹੒͢Δ ͜͏ͳΔͱɺ Կ͕Ͳ͏มΘ͍ͬͯΔͷ͔Θ͔Βͳ͍

  75. 75 #============================= # ը૾ͷ߹੒(Slack౤ߘ༻) #============================= percentage_to_resize = 0.5 img_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) ※ίʔυ͸Ұ෦ൈਮ
  76. 7.ࠩ෼͕͋Ε͹࣍ճͷൺֱ༻ʹ࡞੒ͨ͠εΫϦʔϯ γϣοτΛS3ʹΞοϓϩʔυ͢Δ Կ΋͠ͳ͍ ࠩ෼͋Γʂ 4΁ ࠩ෼ͳ͠ʂ

  77. 77 #======================================================= # S3ʹը૾ΛΞοϓϩʔυ͢Δ #======================================================= client.upload_file( 'test-reports/current_page_screenshot.png', '{S3໊}', ‘{S3ͷύε໊}/screenshot.png' )

    ※ίʔυ͸Ұ෦ൈਮ
  78. 9.Slackʹ౤ߘ͢Δ Ұຕʹ·ͱΊͨํ͕ݟ΍͍͢ʂ

  79. มߋޙ มߋલ ࠩ෼

  80. 80 ໨diffؒҧ͍୳͠(αϙʔτ෇͖)

  81. 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. 82 ※ίʔυ͸Ұ෦ൈਮ ΋͠΋ະདྷͰɺ ࠩ෼Λݟ͍ͨϖʔδ͕ෳ਺ʹ૿͑ͨ࣌

  83. 83 ݁Ռͱ·ͱΊ 3

  84. 84 هऀ
 σβΠφʔ ΤϯδχΞ ศརͳ࢓૊ΈΛ ͋Γ͕ͱ͏͍͟͝·͢ ໌Β͔ʹ͓͔͍͠Օॴ͕ͳ͍͔ ؆୯ʹ൑ผͰ͖Δͷ͸͋Γ͕͍ͨ σʔλͷܻ਺ʹΑͬͯϨΠΞ΢τ͕ มΘΔཁૉ͕͋Δɻ

    ҙਤ͍ͯ͠ͳ͍ϨΠΞ΢τʹ ͳ͍ͬͯͳ͍͔͕Ұ໨Ͱ෼͔Δͷ͕ ྑ͍ ಋೖޙͷ੠
  85. 85 هऀ
 σβΠφʔ ΤϯδχΞ ศརͳ࢓૊ΈΛ ͋Γ͕ͱ͏͍͟͝·͢ ໌Β͔ʹ͓͔͍͠Օॴ͕ͳ͍͔ ؆୯ʹ൑ผͰ͖Δͷ͸͋Γ͕͍ͨ σʔλͷܻ਺ʹΑͬͯϨΠΞ΢τ͕ มΘΔཁૉ͕͋Δɻ

    ҙਤ͍ͯ͠ͳ͍ϨΠΞ΢τʹ ͳ͍ͬͯͳ͍͔͕Ұ໨Ͱ෼͔Δͷ͕ྑ͍ ಋೖޙͷ੠ Ͱ΋ɾɾɾɾ ͩΜͩΜݟΒΕͳ͘ͳͬͯ͠·͏
  86. 86 هऀ
 σβΠφʔ ΤϯδχΞ ޕޙ̑࣌ఆظ࣮ߦ͡Όͳͯ͘ ग़͢௚લʹνΣοΫͰ͖ΔΑ͏ͳػߏ ͕Α͔ͬͨ վળϙΠϯτ

  87. هऀνʔϜ σβΠφʔɾΤϯδχΞνʔϜ εϓϨουγʔτͰ ຖ೔σʔλूܭˍνΣοΫ վम͕͋Δ৔߹ (JU)VCͰϦιʔε؅ཧ $*ͰϦϦʔε ͜ͷ࣌఺Ͱެ։ͱಉ࣌ʹ -BNCEBΛىಈ ͞Βʹվળ͢ΔͳΒ

  88. 88 هऀ
 σβΠφʔ ΤϯδχΞ ผͷϒϥ΢β΍ϞόΠϧαΠζͳͲ ͍Ζ͍Ζͳը໘ύλʔϯͰ ݕূͰ͖ͨ΄͏͕҆৺ײ͕ߴ·Δɻ վળϙΠϯτ ίϯςϯπ಺ͷ্෦ͷจষ͕ มߋ͞Εͯɺߦ਺͕มΘͬͯ͠

    ·͏ͱϨΠΞ΢τ͕͢΂ͯԼʹ ͣΕͨͱݕग़͞ΕΔͱ͍͏৔߹ ͕͋Δɻ
  89. هऀνʔϜ σβΠφʔɾΤϯδχΞνʔϜ εϓϨουγʔτͰ ຖ೔σʔλूܭˍνΣοΫ վम͕͋Δ৔߹ (JU)VCͰϦιʔε؅ཧ $*ͰϦϦʔε άϥϑͷը૾ͷݕग़͚ͩʹಛԽ ͞Βʹվળ͢ΔͳΒ

  90. 90 Pythonͷศར͞ ΍Γ͍ͨ͜ͱʹରͯ͠ɺπʔϧ͕ἧ͍ͬͯͯ ਺ेߦͰ͙͢ʹࢼ͢͜ͱ͕Ͱ͖Δշద͕͞࠷ߴ

  91. 91 هऀ
 σβΠφʔ ΤϯδχΞ ۀ຿վળͷ໘ന͍ϙΠϯτ ͍ͭ΋΍͍ͬͯΔ ಉ͡ܗࣜ֬ೝ࡞ۀ ͍ͭ΋΍ͬͯΔ͚Ͳ ຊ൪Ͱຖ೔ ֬ೝ͢Δ͔͠ͳ͍ͷ͔ͳʙ

  92. 92 هऀ
 σβΠφʔ ΤϯδχΞ ۀ຿վળͷ໘ന͍ϙΠϯτ ͍ͭ΋΍͍ͬͯΔ ಉ͡ܗࣜ֬ೝ࡞ۀ ͍ͭ΋΍ͬͯΔ͚Ͳ ຊ൪Ͱຖ೔ ֬ೝ͢Δ͔͠ͳ͍ͷ͔ͳʙ

    ʮ͜͏ͳͬͨΒ͍͍ͷʹͳʙʯ͸ɺࠔ͍ͬͯΔຊਓ͔Β ϐϯϙΠϯτͰ͸དྷͳ͍
  93. 93 هऀ
 σβΠφʔ ΤϯδχΞ ۀ຿վળͷ໘ന͍ϙΠϯτ ͲΜͳײ͡Ͱ ࡞ۀ͍ͯ͠ΔΜͰ͔͢ʁʁ

  94. 94 هऀ
 σβΠφʔ ΤϯδχΞ ۀ຿վળͷ໘ന͍ϙΠϯτ ͜Μͳखஈ͋Γ·͢Αʁ ͜͏ͨ͠Β͍͍͔΋ʁ ͦΜͳ͜ͱͰ͖Δͷʁʁʂʂ ศརʂͦΕ΄͍͠ʂ

  95. 95 ·ͱΊ νʔϜͷಇ͖ํΛ͞Βʹշదʹ͢ΔͨΊͷछ͕ ೔ʑͷίϛϡχέʔγϣϯͷதʹ͋Δ͔΋ʁʂ

  96. 96 https://hack.nikkei.com/

  97. 97 ͋Γ͕ͱ͏͍͟͝·ͨ͠