From 743cce543b2ce901e4ff4bc4c203fd7630691366 Mon Sep 17 00:00:00 2001 From: Taehoon Date: Tue, 10 Mar 2026 14:11:49 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20MySQL=20DB=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EB=B0=8F=20=ED=81=AC=EB=A1=A4=EB=A7=81=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=A0=95=EC=83=81=ED=99=94=20(ID=20=EB=A7=A4=EC=B9=AD=20?= =?UTF-8?q?=EB=B0=8F=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A0=95=EB=B0=80?= =?UTF-8?q?=ED=99=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 2 +- __pycache__/analyze.cpython-312.pyc | Bin 13194 -> 13366 bytes __pycache__/crawler_service.cpython-312.pyc | Bin 9977 -> 18209 bytes __pycache__/server.cpython-312.pyc | Bin 3452 -> 6797 bytes backups/crawler_service_v1_dom.py.bak | 141 ++++++++ composition_debug.png | Bin 0 -> 17859 bytes crawler_service.py | 355 +++++++++++--------- crawling_result 2026.03.06.csv | 42 +++ crawling_result 2026.03.09.csv | 42 +++ crwaling_result.csv | 42 +++ db_2026.03.09.csv | 42 +++ db_2026.03.10.csv | 42 +++ diag_folders.py | 66 ++++ js/dashboard.js | 16 +- log_debug.png | Bin 0 -> 129162 bytes server.log | Bin 10858 -> 1406 bytes server.py | 77 +++-- server_reboot.log | Bin 0 -> 93476 bytes server_revert.log | Bin 0 -> 47692 bytes server_startup.log | Bin 0 -> 968 bytes test_main_filtered.py | 33 ++ 21 files changed, 696 insertions(+), 204 deletions(-) create mode 100644 backups/crawler_service_v1_dom.py.bak create mode 100644 composition_debug.png create mode 100644 crawling_result 2026.03.06.csv create mode 100644 crawling_result 2026.03.09.csv create mode 100644 crwaling_result.csv create mode 100644 db_2026.03.09.csv create mode 100644 db_2026.03.10.csv create mode 100644 diag_folders.py create mode 100644 log_debug.png create mode 100644 server_reboot.log create mode 100644 server_revert.log create mode 100644 server_startup.log create mode 100644 test_main_filtered.py diff --git a/.env b/.env index 543c31d..3164fdb 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ PM_USER_ID=b21364 -PM_PASSWORD=b21364!. \ No newline at end of file +PM_PASSWORD=b21364!.`nDB_HOST=localhost`nDB_USER=root`nDB_PASSWORD=45278434`nDB_NAME=crawling diff --git a/__pycache__/analyze.cpython-312.pyc b/__pycache__/analyze.cpython-312.pyc index 9492ae50b3f4b314e865784d4f3c2be464e29a0e..f44c613c22fc54c647b4648c64b783f2b25f3d6e 100644 GIT binary patch delta 691 zcmeB5-28JTj z6!sK`9HCmy8qO?rpu7xQEmsXw7Fa1WSC-~v2Q4Wdm}*9bJVB5oL@zR#!i-Q;q79R& zVW?qR%>?1a0O?xpTAs=4bi_HiQ}}9lQuwo2K`yFig6U0RND+`?ND-XFk|H#RIhaA2 zp+pX5mI_0WTrEe5B8;EHUBi;XQU&DBW=P?w;h4=Zmjz}HBSR!Z3PUYN9Y@av2wl!t z&QQS|$xzOSW~M|fuSJP2%+MNmz|=6L2+v_kW&#_;TgMv=G7v~34AK;t9Hg5nQ6=Q> z9Hih{RFq$&ke{bekeHsTP{m}WFnPOfJ)`(!bG;TpPS=X$)Pj=C{JdMN1x1;8C6jmQ z>9R2wmlSF8P5z1;3s2sv?IOy(nh~UefuYDW zg*}BKN1&FYhGX&qZPCg0Vw`NXoHa~YV8zUwS*nvAw4{7s>KPgG1VNGz-N`zO0;488XlM#H4G_&bC{BuA{kN`YI*8- zf}wOdV>tuF98Dp=TWrONxdl0?RV;c1DU+A!hEEpNt7jCOJXNn{vbMgCAg60Za%w?I zW`5o+=HikfP2S0|`d*Va=!>%O0&SdpN?%i`56EZ+;^H1)U^Xy(U{adQYLLs!DylfS z%)mqRfq?9F0hNmaDhnd73g~|nW)Rc+ATs%?!6dE^q70&nGhKdv(U?5bP~OTMXhxHh zh#MEfA#po5W~RfUPP#zOF=i$=cGhF8tROZQr<*qOF=1XeHRfXqj3BletDE*@7NdD= iASV>{OzwR?`{FZT(He~(xSIN}xzW()k6_H9&=vr=Hn$`jTM~42?PS@(+=ZGr^ z7S8bg`q$Pz`<#1*ea_zJoPGA$m)}H2h7<5?x_Z;_L^(nHJBsiRwS;_f8IX$vLolR? zXb*&BJBi~|JB33*y8ws6b|DT$?IIkC+r>DPv`cU(ZI?nwnZnFr?O`OUOJE8&%i3ia z7n&l>k?oNrK@qyh7nhocH==VydlVxExQ>wkjAo<&W0)|2u>+(k{4UD7PeuBrjMlER z8_YVuqqVjHOSh)aq#fvI4ZV6hq{&QHEu&$qcAe!^_fi8mkOCCI?-Mu{Fo*^bqd15LksIO{mr`2^mBdjBFPaBh4>Zy9|7B|7%FFl8 zP0jyo9FT=)uhI(_r#}1{q@JVar^fDG8oT%W_4)4%&wuBt+8<`Jc56*~tIh5gvR13z zFD)xCsi-U~E%QseS#7_`VCnTs9QK|{b61&4>=y>II&3=DFYVLXZ2eZ2!NaBP(%N)> zNw;3h+H`imtlPobtZcUl@~DJEqki{xE2BH4v)MZ^l{!`f6rD13>(qS% z{+M2!UBh%~mYOnHEo?H>7!5yL5r84$eOc^tb?57Rkx9PDIA6>L^glXzE`Gzs{TKFo zCQK4v=5MYsyKyxFiEE(n+$FjKE16 zMNq-2hY`NG)YcC{WY@?e{t9^{%XzMdTY*ZLCejqbC|T7YM42!~#8U_I6u!?-3}z@h zm@_3V)p2!EVP^>3PnB%Eizt0Ss_&wn-9>_b7cB%2$U@*b#p?WGn@-Di>;0l$*6Qf< zOIRJuqi&sw3QRGL&CdEoX05$jZ$nkkG@As0Kc?HH(^@oW7NRU5gsckEH^9$^X4Vk# zt}JeB+gwD{bGy&)<`OHXm7a+0LyhlBB78A%qm38$Uf4TMes>=impxuQe)!t)iQ`i- zKYompmrd1A>0UW`>*P%4OBSxYkz2QelkV`z;zqZR9vrUq%4oNY9*-OE_Q>)$Vcx^6 zM-0OgoPw?+*0Vx}bP}gX78u-0gh7gNrKmu5^e`mP3>RrffzCoaWx8%k$4&y7&BLdf{6)=6^J@lraCTmlu9;osWzREj;z4pVZt%>mZwk z01aSJ(xFu6)pe*?Bm;v~0S$|h$kt~v*!=>N&Vt1Q5DvpdA4pYNj0gMBCjhwNu|TP zed|-l4qP~W@$7}Op7puIyXMv>Up#f;)R=KHYf|r7U*TO}>t0{$SzkB2%a@ojdVHK3 zuN=?g;tIKl!o@HmV#8tt5fMAo{I^8`A&MDp@X2C^njhFAfUIZh^XsdK*Q%)cErRZ# zaKQ`IF%e#9W1b1m_k;E`DObwGg0){##bqSpU%>0X&J3L@Wy-zWY=f_Pr=OwKd8dto}P+~xUN%7~{xu{i@{|9$GB z;M*b*;eyrIMTQaQmBy7ETB?6VzeDWx0X^X|#rJ^^NwnC67=NQ|CD{QSX&JpFXbnqy z&{IGUrcbm)AM8oS$PncujFbtxOx+0QTYab`Qr(1%te0RSE(@Q{8P4e;nMmM@z)6MT z3KIo650h{{?~!zeDwB9#^~f@zC|kc)Uod58p4SZtr{!vjLGfO0p65Y`zRXcU&UaL`6mgpS~ROIm!u_n6IOO z=o}^pm&7SC<}T;tF(#F#!X*tOm^4?IQ*1<<#Hz;`wnq7MzPwYqMve?d#*dLPe^s>* z};xS_tk1dDJ z@CM>JSvS>7bW@!mnJ$@A_9(8}$dUL*=eR(PD1=a(OU6^qhpvd_k#j}_QzPx0d3u&p z8;DU+=K?`=z-)9yJ)3K<q5?upoCjs$8tq8 z1k{vM1JyG^z;Y4x4fiaiGm23SLV1vbJZB`p{PVd03$92)%LL5((Cc&|E~mZ{-2aVR z`2H`4t{7*Gv3@zuV-HD%II!b^jKvtY^SPG8weq`Sov~~&P}s1Xm&Zcw1S0Q5l=3q2a4DcF)Cyk4l!sWsgKd4u3chLW_LvG+ z98>9vXN0Z<`%a$Jlzj{0Mu zGnB4V6C87NU|aR9MXf8@nGC#ymC}{sOfeoCqy&Z7hn2esz#JTyg#G5V6NApy&B=JbbA|5r89k5$Kh8SHrAOQa`)fuOy~1hNCV-@ zfK{D#W`xYU#}L#eU71dLMT?osE!xX?I(jI+W>&UB(+O&{pl?(T!ijUu_V%u5FKb0> zS<9^jTWE1+8ISWVFNgd*1wMernCplIs1-Cl98DAyPok`hPsn4mjf^3}-N$#BdbDQy7+DC;%uN`2&VN41bBJ{F1d?#g85yZ?MOH zAM0%ugb2#Ep|+n7^aI!UDuzG8@EnHQFhrvw9Ek%cz_bcRW-)#k!#WJ39~vWa zjL4C_*@V4|U(e(Od)%c6EgN5IwLFZ^ZAVtDrwV>NV675{)(K$$4mpeXlA%Wu&aR5H z3gGbb0j!_o`M#<*TfT8`+ScgD8oEszSYI$r$z>_Z_$MZ%8umY(@3p`Ht#YIiCiW=Ey$_;7X@`A6%(edmVKk1M|}(^H=_5 z;RjO-<3n(d{Jn*1=jacohTtBDRxXSKK0P)6>`&;0OXuc)_CM(Pmwpb{K=k}iC+EL= zS*2F1;hs-uALxU7VYAL=)As6i3`P_dTC9aOt%d2bo<{e8dYzUr!CSvj%l6s~TfqQs zI0rUzcn3y!#;*5^^}3~dcj+mEuD{R9+VM3IT<-|&tWM{T));IWbbYNsmyL!~I)9i3 zz0f#VlRu&_aCNLP8Ep11T;sxU1PuCmSmK^11IBzXsq?bGB1EQpxaT8J5v&?=0C}q) zUKv=uu(~KPaR;w8mP;{UWa5>M^CCuo3@rm-bir+C7?Dc=H+87J0uYc;SGK_`U`B#e zz>s;Q{G?&Ru$lq!<~P=LKxu*Y69^8iCD2k%&5oMWL9J1Z-WP4+D537&%)( zjHCn>@-K*2^ge$$T+r8>OijQLzYuQZv}^;^;g5vmL%_EEUFfQR$6x~7#A(g8; zEu@D6_l2>&CTo}0q%l~)Gof48XScG0TX?SoyPgH{)_|A9Ngb=M!QK|OEo#dA5x$hH7YZ&FjBa0~q7yQG8*(R0-5buE1$c(W_V8hkZd zf4S?`T{A~+AN16;j5SZH-%hRar4>vG+-aqEa`MM^`Z6|6XS*|MefjE}RoAPy@+MDy z^KGp=zr~w>#GQYHJKFBaKhAY@y7M0!m-@2vC!Ox>%`^7tqkqWA@fDWe?7ZIjqQ;wB zGcNR1){I9^_PFVCUqdr@;1JhvXgrcrZ*|l4zS^zu>g3yWHC$TKxr^(F^s+?}A+P$| zVmzU&y}u|W5;89}{N095S5HN5D5W z*CilaE`S%W=aL9lVVF;CD-yh3D1vkrosI{K^>%xot-7eldP)bExLTWfY4V$~-$=K~ z>R{B}R&x=fwduR8TJT+oW~^p#6ah~jJ96sLG2q@4-mf*-H4cm2U>c0bhPBXODeM|3 zG%$u?*qW}BehKmovO4U8(rn}k0~gFZ*4IB6&X=%TfS@upT6Z+a83nargC)wK)nIoB zO_!A!z{`@xVAq*7CT*9_WH|95$RZ8B2~3J`e)+PPwJjj>;aK**1nl0|+Ia8~y?fuG z{WL!mnx%?tw34sVz!cCtZZQ|oHa#q@8iWPLtAIvS8!SLKLSaDI0o7L`;7EPb;l@^4 zsjwB$5C6Ve9sBpu4ToErc5kmg)JX4bY@-jiG$8aV5r77W@0x+3Yv}+*E4r>)+4qMt zSj?(|uiO$paLd*3DbPw_ESFye;$NfoAQP7B2qr=OON?3h@@sI)9~3a~l92Lb`^5n& z!P52ReS(}SmN(u`u-GBrsE`gc!E?xY3fmRsYvco;I(}Py)Hc0T3pujc zNq(QaNW!hzRv|GUz#5Q{JqCoa?Fb;ttI%OE=eR zd%MNP^`G|kJKg=xMS?g>?xG;rLp4#K5X5P+nfeR`t<*<>04E+sS=uOFAd8N=S`Tlb z{`)o=wD?p_y@Y&?kO0JcD&9&TkjDewIC~(+Ak|4bkUIpuFg&(!?E(!RJ_|p(Fj(`o zSG#Jx)>dfOowh4;2dP|@pFDjR35TB?I0Wmks0TaRQg@pS-6xf*!36LIGJwOGdP#LC zG+P<1X>dcxWZGcqbJ*Exs2Hm*y20?0jU^ikHx|Qx2ht4|#-9X#ropVx#Tmn?;|38A{gLk&e>ttzCC&;R1w!nrG*^uo_CFMMZw$&rc%*Q$kId~e|w;5Bvb)`u_s zyqb0(^M0TR%KG1)rop@O!QO7RpNf0dGvA#>xj)xBiGHttO-^S z@Ooja{c5DA*uig7Z3T~4gN4q2=mpY_kl3rS50)~wC|9Mn!GP+N8w=y|Qf+Iy|?e?bqhZ}N2>WD=rRGZiC zxa)2@j9@SP;JH%=-i8jAg*|Rr_w);U3?}ei?6H~{@N^AFG23>u0s6^}jyxz97=PsS zcJ5Z^vePZSaO>Q?r>+Ef1!o|vgc^MR_{TpS`41IbVjx;Sr-o>7%w71_)KXzuIoP_i z<2}5Ew>BQ4SzR{}jU3g0acGl8RDzxXRN@5s=&r_tjbGda6*jzb2dHn@2Eumn>7}Xj z>~wI|-rZ15KOj|u;y^wJSZRq)`omi<&z~EfzdTe;gXmi=;KhmO0alzHv5;rs)v@`X zJ`EFqUKqPN|C6z5T2;cL9l$R@lcpJABF16vvw?T9p0%0{4l{V@X&n}D5tUhV{Q)iM zwB1jEsxCzdeZX$Nu-9t0`XyK@t-ub@(N7s{hAv={2+v~7FOxq8>us=TfH$xSju4Pn zg1xs5R`3lp>2!VA5!f#d_#Wdm-7nFd)^$5TcSnmmyt10j20M$UC92#CPR;AICZyh5 zK+!|X5S&zzN(W;Aj>~>&5A@@tZUB4>bry$N$AZtQUkGcz9hNTx3;9xP-K-VYV7CI@ z&?!TY#-h`KuIZ2H0(LRr-wL|mY4C)#f;#CJv04lCS_V@<(=~wG^hNW@B)-bs2cpeMR;%YlNNs@uZ{&$L|9P$qyc=xHP{2#AF(tKHBb%X4})VN8UdZj zFF=D6zAW#72^kP|e*|8xHP$}Za2Xa&F(fH4pmqxoZnxl(72{r@f)v~1mjspso1g6Qlihw&#~y?hSuJWd%xvq` zJnqmrbS&B&!EZirHn1(tdzejM_H5lcG_-WC6u=>IFzd^e2jtLVTL&BW1AJJVi_7-J zDL#WUewcg_!^s$5V#@H&MXHaAl!Kf5#mEbhmzfugmyA;i&;uID9Y{II+ljP+j9t{H z1QD~F^3j>s!Y9JLbg`Q*o-V%~#qB)G(ZwG6m^bCvsKiI-dg)R(T{>fjbECWVI7gRy z=nij6$Ef6vs&J;9JKDybG`nfbXym8D*qF>kB@vT!G5kXKST&bhH5*;+OOt!k3f*ai zp0pzG`l3-G5P8vX!NAe2+zEEn;7PQ3qitNYZBb05q`#1QDRtc9NiO#$Z*?bcy&cab zZ}lYa^TvUT_dXxI&%2a2{+K7F%o|_E#h0NJ)g{&Vo+*hZrP3Q;$;DSLr%632Ro?h2 zF20H{+2Khk@y3^M@g>mO`VHR10(W8oS9pRmTDimmPhy`px{r(Qn@dc)Xue<`ulFS8 zc%yT;=p4u%pE;iHiQ720p}@02J=(BH#U|wW(lTE-e(CrRI~R$l+S;8cMpw{BdxNXasb!HYOwIlg@{no#6l+c&Xqs&qQ>mnpBN%rtqb4sfkU zxi*crt=rw!%`q0PkM*?Kyln&SwgFGu8DB;1D}%QNXOy0by|<72w*A-b+%cV}xrftR zyn5EHXF1zhkN$~80a;Z~{gogU+o+G$6ZyNy&jdi%VmgtW_JZt^>~f?pDf5NMOOaQZ zYsLxVw1V6B_$=!H;pitDkgnKBVFj|EJcNYAMq&k$C6AzYN8sZf2%5>`NQ_E4P>$SA zBu2@PQD`9AFSTFpfPu=$e!+Cf#N|KcN!NJOt?qQIC;f46(&M9|Ia+@8(6!Eq&Kbw= zO50}wTJBMI%h7jQ+NSDX*?DW{&v(CF+U`*t2N@fUoJ-m;*6c~j8x_5uyKySbn_G8b z|7iWF^ZoQJXdCItuIb0zMNL2gM1VFuWx~R3rbc(ZyLIPy#kI{7nE(AcX}CDz6LP41i~FfJ98dJDF?3$}U+ws~{5jqQ9l zBWIGiX}oUqs<*h+Tc-PGY_B@O+Elk64P9G@`#>jmLhC-D^{BhN$}YFE%cm^38F@XD z+q8!}*ycT`cOTSy4jR2pMvwBOH|r#qb#hTCOxujxuW{$paJ7fH$GW(j8c$BQm+t21 zZeLO9c*MK3Vlj@$%KJEpNLAj+FS=QCy@sni?8!gk&2M+-gN>`htLPZp@m_A>xWJcJ z=*`>g&f7e_!;`n&E8l)w?8)8-sW+9^l~XmIyscjOR!+Y4UAbyeLMYXX;e@L2X2kUf zWIa_HGte%_-FI~aW z6>~X-*US^Jkqnj|LsL}IM)^_|FEn3jz9GMvcRg=f#~tkDVBP4oaV>Utxx>b$9STxwllR)gp)5`x0CPY6Lq`e%e7IUS7Po8 ztlV+-pOQgnGGH~Wdpl$6Yl^un6{>1V;K?fUrk1%=k$EsHAMApus>wvphK)XD`BaZv zSv$6S?$BeLMn7w`%pS6iS6!=}sO5?qW(>30Eu5ntOrCPZSmT{c#kHh~q{*DAEKg?n z*fw8k=F8#JC2tDfWTu_78=J1SPR3q6${lQVr?x`woV;uL3H{{h=~z!r&DhSl4Ao@r z%Vo0}l|I$Ro9Wlnf2XP%ulFfcH$~S)lcwqI9_3bu%T+Jiri))X^~%{>XJ;#R-e{eQ zxpCz70k?eLL?ck2R}JHkS2VWgp`i?%$oHbzewN&i1|J2$krwJW3OXqb;>B6=1d3@X zCJ^XQaF)btmy7I0u>+(Y72jk)`SXp4cWEad=A8?&J`v#kS#l35xQE&oD36=p)Pl<& zz~v88ABka-%w?B(vNw&v&LvJO@hMd3YpEZ@&P8ROAg5sKdSZOLPoB55Go{S5b1-!) zADfkHJ`-5dnh%!^AEM3+7=U4!Tpl z7m-ucgviNkrcmSU6YWN>FmlOcJ*JGmXlX4^Wr&c{4$8t&K$u0iWob$Qaez0u6u(ah(d zuRs|*0woVFRIFg8dj&J!iOzno7~tmp06SMQ_3yU7f<^A>b>@8Xdt{GH{Ja3LF@ZTz zaJgQ3GJ$$cPWD8JUsI$4{yIta#E4&~$`M{c_QZ={uS@~_jaag0z4(ndCBiq8Jt^Wh zYLWndGoI{86Tg{|jBqvCLyO-mLik%!vL{>oRv60jRwmh#BYrCj)$>*j*`pG_Rg2pC zRWjLAApTWKJi?2jdxg}m>QZ_tME^6TzO1K6{Oc$RBEOEQUk7jgl`er?zlkM#lf}P@ zL#2OHl+c?R^}j^12(I522TA{yUt&-Tf15`3W=emXz8>M_WUpNM+fBuQbGc-1u9Q=z z0Pd#9-aM&WfN{uQD0Qc&qV#IAccaw3xn2wr4@vfxhI=Sf*i%aOZVLC5$pN2DB73W% zXOm?Jmy^9U;j;=M!t)aKl=vNj?5zubhZG}RqJ;E!ib%au`p(8Qz<(D>>hr^Y7bQV> zVmyL*q+T8VyZm}og%`3GOT8Nr?LG;qFO&MDh%TR;)K^GB3jzFH8L6+9z8it6dsjv3 zYo+hzZ6hJ_UOxD(N#83-0(?$L8U)fg5u$x=6KN2K&s8*{TK~8%+K?#xV@8r8O!CKy zdI3cKy&6^fK1~|(rSE4VGTv9@!EpX*T>{9+pX8(|L;NQN#;au@IvtNRq|Ak7?E5iPgO6oHr z{*op_coyQsUtr__sxd6aunfZr468A$Mer_xp#VcMhG8N@oa}Ct6h`uHVyr+273`G*{`8~R=4oqTt?)&t zm2E^hnyl8omcaWcWQJNU=8yVfHU3yQrw8r|!60GoGwHzo@-(!k60yI8fSo}A+XI9q zsFi&U;x=UDK5^m%|IKMa$YVbHuaFB_rECm<2Sdc1B>WlYlg`opw`!Yx%? z?F}g5o}7KN(*5vdyH}R!mSuWm*+UI;LYY^X;ufZimCXw2|0A?fBKabCBZ$Jh!VPZW zhD+Oj*f=Z9@(HES?0Is}(@lZzouRSdgDlztxOV&`9Kh<&9YcRW`XU&g(c}8EKYtMX zpb@@_MgxMMP@kK=xb)6NJ^Jfrd+?)CC*=g6gdV|-pc5hTcL?=4B40NNpG<`j_L!xn z2qQ9Ru6n?eBYss9L>b|Y;K%b1d4GV%#Sm!;2VV{$xE4yT2>w|JpM;Wd-BbbegmCv? zrU$vxjbwrQ60)G;#|R&uu71Els}$Uo1&?x5w^41xNac#YrL3+6dJ*&$2|8E>U4@XV z+DIGkRD`d{!oZ88rCDRJMtJ;ubGWJF|@-c41cES z$)IMP%TCsdvHSu}^xvf(8dZHNNsU)Poo)(7i zoLGcck_fNPZXg72q*0LaMn)3CE6DBD;x{Tq2(QKIbtK?#5(3DhierBZ&EPNfF$V*8 z17UU+{y0RJw)-UeI(qFvz>NT!j4Zlg^~W#&Ar^JuFSBU-41r4qao`WKuxKs8hJO54 z0kAO~iwtHQi{=ns=P-vKNNd1;>@exJuy^1ETDolLlO<3=N%B1+4F8XMkC44bM88Lb zV;J!s5%qf_?e|3S?}_w35VCWT9}B}s@yCfGGXLW!85#R=ii;v+J~=CjB4cq={}*s{ BVFdsH literal 9977 zcmcgS3v?6Ll{5N|W%+}Vf3k>2GT4@E$+rB#*bc;C0wlqNI23Gb3t2O^C1gpFMm7kk zWgE6j8+Qw*rI;2Lvzso^(2cWAPv~jSsnhgBn|?-_w4i}O!o65e za>RRZ@mkg+6GwTE97dT}F{12I;%JWCs~S=FsBuh&(dw5{OTit*F|3C;jGL7=5v|jV z3%SnFVV}zp@H!8V1>Hl#4A3&YekbLi{0!|Ib)}faAq$`!G`sVDE`~jc;h-3UOA|bj z$`S!a3V$heKlY%RvZa}L6bs6tc!;Frj8a<6qmr=Yky21fN_BRL^XnL;J}3W{;;Z;+ z9LEk5Ls(44WJvQRH#A_+;}mg3j$vPwotA%2sl;OPhme$!R+0=!ipo7=ASFr3(SyA8 zu@9vg!l=x@#jj{zN_p#fETxM)rHdk}@Z@}q4KArHDx1nVE2DC+thz6+GOF~fTFEO} zzCxBN15)LIKF&*Pxk9vDw}GNXi~O9ysB(f0v{#WFHb>_1U&k5S@Z9-|r3N-<4T<0)Id zBVjA7QYCZEvrd|^JW6w8nGa#HF`7Y{BESrGmx zyOcjE9ibjHY3o6ArChRmB@bhk*7aB*D+5TDLq-tZiR9$QpWsl|E$I4tu+lQ*K)XJ3gUHku??mp7<{$Hf$Gj&q-dF&FlJW};kLv*!N0Te+s>akcsv;gY8DXJ4; z{@1Z{N~nVe@0#n=_6JpJ*G!ks&D4f89e*h=ACS>4k_SItK{y5#+ZrppkLL>|zO)rv z6fOE6RO}JpN@w9GRxCxtikEi}s!h_X1M7Pn_6|LqZ5oziC1G$^2X{-TN24X4CW*Q{ zj$$EvJTF=jE5#Xd|Gx)h=m5ZAM#^bViGrq9%xhuQ4?}E9V_6STpIf3? zP|+RtIm;yLwAiyrlD9mr*vFS6D)Y22&y%odW>g!^qPCuuOV)`e;B=>;$E6wRYVn~f zYWZA|ey3jp`~1pt_7c|vGJ2b&<5FcTah_0&|3UHKCyE_W8TCY(r?%u1h2o)no_bn> zM_K~?lQQLb*+-x3&{N=g?1XCkjtHkjcuIsvMYvsrwIVDQp$wpMd|rg#5#g6aSOHKm zo)F>dBD^TVzZT&h5k4xyGJx{&MG^i~gfED27eLwgzliV`W$^Uejjn%vNZyT&;Ue|C z2>(iiO(M((h>!o92)`%7#uO($-YjvBf4CkSe;2-Qlwr(fDeu-|K~l`LbWdp8S3IF9 z;CWb#o!i;u$OZbQ##J zOk!iWqyyNuScbvV@q=m-S)xFv$D}38{IIH~46DP$EJ3rxEJCwF_!#U8-C#G$n550$ zl8@o$r^4v)uOZ>{^wKMmxo>=*oIm&K{MRnuKJ_X&_r)o=xP5F&Bp;uczj*TYsfk

mvZm-u_(`c(DEBCs6 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 diff --git a/__pycache__/server.cpython-312.pyc b/__pycache__/server.cpython-312.pyc index b5cf328b10376077b9a66fbdf6dd680bc2d4e1e2..64c72d1db2a824baa8629debc5e4802aeb114326 100644 GIT binary patch literal 6797 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 Va2QPM;)$oATEN0-vd_8;^Dk$EGKl~H diff --git a/backups/crawler_service_v1_dom.py.bak b/backups/crawler_service_v1_dom.py.bak new file mode 100644 index 0000000..30b4384 --- /dev/null +++ b/backups/crawler_service_v1_dom.py.bak @@ -0,0 +1,141 @@ +import os +import re +import asyncio +import json +from playwright.async_api import async_playwright +from dotenv import load_dotenv + +load_dotenv() + +async def run_crawler_service(): + """ + Playwright를 이용해 데이터를 수집하고 SSE(Server-Sent Events)용 제너레이터를 반환합니다. + """ + user_id = os.getenv("PM_USER_ID") + password = os.getenv("PM_PASSWORD") + + if not user_id or not password: + yield f"data: {json.dumps({'type': 'log', 'message': '오류: .env 파일에 계정 정보가 없습니다.'})}\n\n" + return + + results = [] + + async with async_playwright() as p: + browser = None + try: + yield f"data: {json.dumps({'type': 'log', 'message': '브라우저 실행 중...'})}\n\n" + browser = await p.chromium.launch(headless=True, args=[ + "--no-sandbox", + "--disable-dev-shm-usage", + "--disable-blink-features=AutomationControlled" + ]) + context = await browser.new_context( + viewport={'width': 1920, 'height': 1080}, + user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" + ) + page = await context.new_page() + + yield f"data: {json.dumps({'type': 'log', 'message': '사이트 접속 및 로그인 중...'})}\n\n" + await page.goto("https://overseas.projectmastercloud.com/", wait_until="domcontentloaded") + + await page.click("#login-by-id", timeout=10000) + await page.fill("#user_id", user_id) + await page.fill("#user_pw", password) + await page.click("#login-btn") + + yield f"data: {json.dumps({'type': 'log', 'message': '대시보드 목록 대기 중...'})}\n\n" + await page.wait_for_selector("h4.list__contents_aria_group_body_list_item_label", timeout=60000) + + locators = page.locator("h4.list__contents_aria_group_body_list_item_label") + count = await locators.count() + yield f"data: {json.dumps({'type': 'log', 'message': f'총 {count}개의 프로젝트 발견. 수집 시작.'})}\n\n" + + for i in range(count): + try: + proj = page.locator("h4.list__contents_aria_group_body_list_item_label").nth(i) + project_name = (await proj.inner_text()).strip() + + yield f"data: {json.dumps({'type': 'log', 'message': f'[{i+1}/{count}] {project_name} - 시작'})}\n\n" + await proj.scroll_into_view_if_needed() + await proj.click(force=True) + + await asyncio.sleep(5) + await page.wait_for_selector("div.footer", state="visible", timeout=20000) + + recent_log = "기존데이터유지" + file_count = 0 + + # 로그 수집 + try: + log_btn_sel = "body > div.footer > div.left > div.wrap.log-wrap > div.title.text" + log_btn = page.locator(log_btn_sel).first + if await log_btn.is_visible(timeout=5000): + await log_btn.click(force=True) + await asyncio.sleep(5) + + date_sel = "article.archive-modal .log-body .date .text" + user_sel = "article.archive-modal .log-body .user .text" + act_sel = "article.archive-modal .log-body .activity .text" + + if await page.locator(date_sel).count() > 0: + raw_date = (await page.locator(date_sel).first.inner_text()).strip() + user_name = (await page.locator(user_sel).first.inner_text()).strip() + activity = (await page.locator(act_sel).first.inner_text()).strip() + formatted_date = re.sub(r'[-/]', '.', raw_date)[:10] + recent_log = f"{formatted_date}, {user_name}, {activity}" + yield f"data: {json.dumps({'type': 'log', 'message': f' - [로그] 수집 완료'})}\n\n" + + await page.click("article.archive-modal div.close", timeout=3000) + await asyncio.sleep(1.5) + except: pass + + # 구성 수집 + try: + sitemap_btn_sel = "body > div.footer > div.left > div.wrap.site-map-wrap" + sitemap_btn = page.locator(sitemap_btn_sel).first + if await sitemap_btn.is_visible(timeout=5000): + await sitemap_btn.click(force=True) + + popup_page = None + for _ in range(20): + for p_item in context.pages: + if "composition" in p_item.url: + popup_page = p_item + break + if popup_page: break + await asyncio.sleep(0.5) + + if popup_page: + target_selector = "#composition-list h6:nth-child(3)" + await asyncio.sleep(5) # 로딩 대기 + locators_h6 = popup_page.locator(target_selector) + h6_count = await locators_h6.count() + current_total = 0 + for j in range(h6_count): + text = (await locators_h6.nth(j).inner_text()).strip() + nums = re.findall(r'\d+', text.split('\n')[-1]) + if nums: current_total += int(nums[0]) + file_count = current_total + yield f"data: {json.dumps({'type': 'log', 'message': f' - [구성] {file_count}개 확인'})}\n\n" + await popup_page.close() + except: pass + + results.append({"projectName": project_name, "recentLog": recent_log, "fileCount": file_count}) + + # 홈 복귀 + await page.locator("div.header div.title div").first.click(force=True) + await page.wait_for_selector("h4.list__contents_aria_group_body_list_item_label", timeout=20000) + await asyncio.sleep(2) + + except Exception: + await page.goto("https://overseas.projectmastercloud.com/dashboard", wait_until="domcontentloaded") + + yield f"data: {json.dumps({'type': 'done', 'data': results})}\n\n" + + except GeneratorExit: + # SSE 연결이 클라이언트 측에서 먼저 끊겼을 때 실행 + if browser: await browser.close() + except Exception as e: + yield f"data: {json.dumps({'type': 'log', 'message': f'치명적 오류: {str(e)}'})}\n\n" + finally: + if browser: await browser.close() diff --git a/composition_debug.png b/composition_debug.png new file mode 100644 index 0000000000000000000000000000000000000000..5ccabb3ffb3db32182090a81d2b8ff7a578a1c81 GIT binary patch literal 17859 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 G%YOp!hIVrR literal 0 HcmV?d00001 diff --git a/crawler_service.py b/crawler_service.py index bd84df4..b291493 100644 --- a/crawler_service.py +++ b/crawler_service.py @@ -2,101 +2,159 @@ import os import re import asyncio import json -import csv import traceback +import sys +import threading +import queue +import pymysql from datetime import datetime from playwright.async_api import async_playwright from dotenv import load_dotenv load_dotenv() +def get_db_connection(): + """MySQL 데이터베이스 연결을 반환합니다.""" + return pymysql.connect( + host='localhost', + user='root', + password='45278434', + database='crawling', + charset='utf8mb4', + cursorclass=pymysql.cursors.DictCursor + ) + def clean_date_string(date_str): - """ - 날짜 문자열에서 YY.MM.DD 형식만 추출합니다. - """ if not date_str: return "" match = re.search(r'(\d{2})[./-](\d{2})[./-](\d{2})', date_str) if match: - return f"{match.group(1)}.{match.group(2)}.{match.group(3)}" - return date_str[:8] + return f"20{match.group(1)}.{match.group(2)}.{match.group(3)}" + return date_str[:10].replace("-", ".") -async def run_crawler_service(): - """ - 상세 패킷을 강제 호출하여 팝업 없이 상세 파일 개수를 수집하며 모든 성공 로직을 보존한 크롤러입니다. - """ - user_id = os.getenv("PM_USER_ID") - password = os.getenv("PM_PASSWORD") +def parse_log_id(log_id): + """ID 구조: 로그고유번호_시간_활동한 사람_활동내용_활동대상""" + if not log_id or "_" not in log_id: return log_id + try: + parts = log_id.split('_') + if len(parts) >= 4: + date_part = clean_date_string(parts[1]) + activity = parts[3].strip() + activity = re.sub(r'\(.*?\)', '', activity).strip() + return f"{date_part}, {activity}" + except: pass + return log_id - if not user_id or not password: - yield f"data: {json.dumps({'type': 'log', 'message': '오류: .env 파일에 계정 정보가 없습니다.'})}\n\n" - return - - results = [] - - async with async_playwright() as p: - browser = None - try: - yield f"data: {json.dumps({'type': 'log', 'message': '브라우저 엔진 (데이터 강제 유도 모드) 가동...'})}\n\n" - browser = await p.chromium.launch(headless=False, args=["--no-sandbox", "--disable-dev-shm-usage"]) - context = await browser.new_context(viewport={'width': 1600, 'height': 900}) - - captured_data = {"log": None, "tree": None} - async def global_interceptor(response): - url = response.url - try: - # 상세 패킷 감시 (params[resourcePath]=/ 가 포함된 상세 응답 우선) - if "getTreeObject" in url: - data = await response.json() - if data.get('currentTreeObject', {}).get('folder'): - captured_data["tree"] = data - elif "Log" in url: - captured_data["log"] = await response.json() - except: pass - context.on("response", global_interceptor) - - page = await context.new_page() - - # --- 1. 로그인 (안정 로직) --- - await page.goto("https://overseas.projectmastercloud.com/dashboard", wait_until="domcontentloaded") - if await page.locator("#login-by-id").is_visible(timeout=5000): - await page.click("#login-by-id") - await page.fill("#user_id", user_id) - await page.fill("#user_pw", password) - await page.click("#login-btn") - - await page.wait_for_selector("h4.list__contents_aria_group_body_list_item_label", timeout=60000) - await asyncio.sleep(5) - - names = await page.locator("h4.list__contents_aria_group_body_list_item_label").all_inner_texts() - project_names = [n.strip() for n in names if n.strip()] - count = len(project_names) - yield f"data: {json.dumps({'type': 'log', 'message': f'총 {count}개의 프로젝트 수집 시작.'})}\n\n" - - for i, project_name in enumerate(project_names): - captured_data["log"] = None - captured_data["tree"] = None - yield f"data: {json.dumps({'type': 'log', 'message': f'[{i+1}/{count}] {project_name} 수집 시작'})}\n\n" +def crawler_thread_worker(msg_queue, user_id, password): + if sys.platform == 'win32': + asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) + + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + + async def run(): + async with async_playwright() as p: + browser = None + try: + msg_queue.put(json.dumps({'type': 'log', 'message': '브라우저 엔진 가동 (전 기능 완벽 복구 모드)...'})) + browser = await p.chromium.launch(headless=False, args=["--no-sandbox"]) + context = await browser.new_context(viewport={'width': 1600, 'height': 900}) - try: - # 상세 페이지 진입 (안정 로직) - target_el = page.get_by_text(project_name).first - await target_el.scroll_into_view_if_needed() - box = await target_el.bounding_box() - if box: await page.mouse.click(box['x'] + 5, box['y'] + 5) - else: await target_el.click(force=True) - - await page.wait_for_selector("text=활동로그", timeout=30000) - await asyncio.sleep(3) + captured_data = {"tree": None, "_is_root_archive": False, "_tree_url": "", "project_list": []} - recent_log = "데이터 없음" - file_count = 0 - - # --- 2. 활동로그 수집 (100% 복구 로직) --- + async def global_interceptor(response): + url = response.url try: + if "getAllList" in url: + data = await response.json() + captured_data["project_list"] = data.get("data", []) + elif "getTreeObject" in url: + # [핵심 복원] 정확한 루트 경로 판별 로직 + is_root = False + if "params[resourcePath]=" in url: + path_val = url.split("params[resourcePath]=")[1].split("&")[0] + if path_val in ["%2F", "/"]: is_root = True + + if is_root: + data = await response.json() + captured_data["tree"] = data + captured_data["_is_root_archive"] = "archive" in url + captured_data["_tree_url"] = url + except: pass + + context.on("response", global_interceptor) + page = await context.new_page() + await page.goto("https://overseas.projectmastercloud.com/dashboard", wait_until="domcontentloaded") + + # 로그인 + if await page.locator("#login-by-id").is_visible(timeout=5000): + await page.click("#login-by-id") + await page.fill("#user_id", user_id) + await page.fill("#user_pw", password) + await page.click("#login-btn") + + # 리스트 로딩 대기 + await page.wait_for_selector("h4.list__contents_aria_group_body_list_item_label", timeout=60000) + await asyncio.sleep(3) + + # [Phase 1] DB 기초 정보 동기화 (엄격한 매칭) + if captured_data["project_list"]: + conn = get_db_connection() + try: + with conn.cursor() as cursor: + for p_info in captured_data["project_list"]: + p_nm = p_info.get("project_nm") + try: + sql = """ + INSERT INTO overseas_projects (project_id, project_nm, short_nm, master, continent, country) + VALUES (%s, %s, %s, %s, %s, %s) + ON DUPLICATE KEY UPDATE + project_id = VALUES(project_id), project_nm = VALUES(project_nm), + short_nm = VALUES(short_nm), master = VALUES(master), + continent = VALUES(continent), country = VALUES(country) + """ + cursor.execute(sql, (p_info.get("project_id"), p_nm, p_info.get("short_nm", "").strip(), + p_info.get("master"), p_info.get("large_class"), p_info.get("mid_class"))) + except: continue + conn.commit() + msg_queue.put(json.dumps({'type': 'log', 'message': f'DB 기초 정보 동기화 완료 ({len(captured_data["project_list"])}개)'})) + finally: conn.close() + + # [Phase 2] h4 태그 기반 수집 루프 + names = await page.locator("h4.list__contents_aria_group_body_list_item_label").all_inner_texts() + project_names = list(dict.fromkeys([n.strip() for n in names if n.strip()])) + count = len(project_names) + + for i, project_name in enumerate(project_names): + # 현재 프로젝트의 고유 ID 매칭 (저장용) + p_match = next((p for p in captured_data["project_list"] if p.get('project_nm') == project_name or p.get('short_nm', '').strip() == project_name), None) + current_p_id = p_match.get('project_id') if p_match else None + + captured_data["tree"] = None + captured_data["_is_root_archive"] = False + msg_queue.put(json.dumps({'type': 'log', 'message': f'[{i+1}/{count}] {project_name} 수집 시작'})) + + try: + # 1. 프로젝트 진입 ([완전 복원] 좌표 클릭) + target_el = page.locator(f"h4.list__contents_aria_group_body_list_item_label:has-text('{project_name}')").first + await target_el.scroll_into_view_if_needed() + box = await target_el.bounding_box() + if box: await page.mouse.click(box['x'] + 5, box['y'] + 5) + else: await target_el.click(force=True) + + await page.wait_for_selector("text=활동로그", timeout=30000) + await asyncio.sleep(2) + + recent_log = "데이터 없음" + file_count = 0 + + # 2. 활동로그 ([완전 복원] 3회 재시도 + 좌표 클릭 + 날짜 필터) modal_opened = False for _ in range(3): log_btn = page.get_by_text("활동로그").first - await page.evaluate("(el) => el.click()", await log_btn.element_handle()) + btn_box = await log_btn.bounding_box() + if btn_box: await page.mouse.click(btn_box['x'] + 5, btn_box['y'] + 5) + else: await page.evaluate("(el) => el.click()", await log_btn.element_handle()) + try: await page.wait_for_selector("article.archive-modal", timeout=5000) modal_opened = True @@ -104,96 +162,91 @@ async def run_crawler_service(): except: await asyncio.sleep(1) if modal_opened: + # 날짜 필터 입력 inputs = await page.locator("article.archive-modal input").all() for inp in inputs: - itype = await inp.get_attribute("type") - iname = (await inp.get_attribute("name") or "").lower() - iclass = (await inp.get_attribute("class") or "").lower() - if itype == "date" or "start" in iname or "start" in iclass: + if (await inp.get_attribute("type")) == "date": await inp.fill("2020-01-01") break - captured_data["log"] = None apply_btn = page.locator("article.archive-modal").get_by_text("적용").first if await apply_btn.is_visible(): await apply_btn.click() - await asyncio.sleep(4) - - if captured_data["log"]: - data = captured_data["log"] - logs = data.get('logData', []) or data.get('result', []) - if logs and isinstance(logs, list) and len(logs) > 0: - top = logs[0] - rd = top.get('log_date') or top.get('date') or "" - u = top.get('user_name') or top.get('user') or "" - c = top.get('activity_content') or top.get('activity') or "" - recent_log = f"{clean_date_string(rd)}, {u}, {c}" - - if recent_log == "데이터 없음": - modal = page.locator("article.archive-modal") - try: - d_v = (await modal.locator(".log-body .date .text").first.inner_text()).strip() - u_v = (await modal.locator(".log-body .user .text").first.inner_text()).strip() - a_v = (await modal.locator(".log-body .activity .text").first.inner_text()).strip() - if d_v: recent_log = f"{clean_date_string(d_v)}, {u_v}, {a_v}" - except: pass - - yield f"data: {json.dumps({'type': 'log', 'message': f' - [로그 결과] {recent_log}'})}\n\n" + await asyncio.sleep(5) # 렌더링 보장 + log_elements = await page.locator("article.archive-modal div[id*='_']").all() + if log_elements: + raw_id = await log_elements[0].get_attribute("id") + recent_log = parse_log_id(raw_id) + msg_queue.put(json.dumps({'type': 'log', 'message': f' - [분석] 최신 로그 ID 추출 성공: {recent_log}'})) + msg_queue.put(json.dumps({'type': 'log', 'message': f' - [최종 결과] {recent_log}'})) await page.keyboard.press("Escape") - else: - yield f"data: {json.dumps({'type': 'log', 'message': ' - [로그] 모달 진입 실패'})}\n\n" - except Exception as le: - yield f"data: {json.dumps({'type': 'log', 'message': f' - [로그] 오류: {str(le)}'})}\n\n" - # --- 3. 구성 수집 (상세 패킷 강제 유도) --- - try: - # [지능형 유도] 상세 정보를 포함한 API 요청을 브라우저가 직접 날리게 함 - await page.evaluate("""() => { - fetch('/api/getTreeObject?params[storageType]=CLOUD¶ms[resourcePath]=/'); + # 3. 구성 수집 ([완전 복원] BaseURL fetch + 정밀 합산) + await page.evaluate("""() => { + const baseUrl = window.location.origin + window.location.pathname.split('/').slice(0, 2).join('/'); + fetch(`${baseUrl}/archive/getTreeObject?params[storageType]=CLOUD¶ms[resourcePath]=/`); }""") - - # 패킷 대기 (최대 10초) - for _ in range(20): - if captured_data["tree"]: break + for _ in range(30): + if captured_data["_is_root_archive"]: break await asyncio.sleep(0.5) if captured_data["tree"]: - data = captured_data["tree"] - # 분석된 딕셔너리 구조 합산 - folders = data.get('currentTreeObject', {}).get('folder', {}) - total_files = 0 + data_root = captured_data["tree"] + tree = data_root.get('currentTreeObject', data_root) if isinstance(data_root, dict) else {} + total = 0 + # 루트 파일 합산 + rf = tree.get("file", {}) + total += len(rf) if isinstance(rf, (dict, list)) else 0 + # 폴더별 filesCount 합산 + folders = tree.get("folder", {}) if isinstance(folders, dict): - for folder_name, folder_info in folders.items(): - total_files += int(folder_info.get('filesCount', 0)) - file_count = total_files - yield f"data: {json.dumps({'type': 'log', 'message': f' - [구성] 상세 합산 성공 ({file_count}개)'})}\n\n" - else: - yield f"data: {json.dumps({'type': 'log', 'message': ' - [구성] 상세 데이터 응답 없음'})}\n\n" - except: pass + for f in folders.values(): + c = f.get("filesCount", "0") + total += int(c) if str(c).isdigit() else 0 + file_count = total + msg_queue.put(json.dumps({'type': 'log', 'message': f' - [구성] 데이터 채택 성공: ...{captured_data.get("_tree_url", "")[-40:]}'})) + msg_queue.put(json.dumps({'type': 'log', 'message': f' - [구성] 최종 정밀 합산 성공 ({file_count}개)'})) - results.append({"projectName": project_name, "recentLog": recent_log, "fileCount": file_count}) - await page.goto("https://overseas.projectmastercloud.com/dashboard", wait_until="domcontentloaded") - await page.wait_for_selector("h4.list__contents_aria_group_body_list_item_label", timeout=20000) - - except Exception as e: - yield f"data: {json.dumps({'type': 'log', 'message': f' - [{project_name}] 건너뜀 (사유: {str(e)})'})}\n\n" - await page.goto("https://overseas.projectmastercloud.com/dashboard") + # 4. DB 실시간 저장 (ID 기반) + if current_p_id: + conn = get_db_connection() + try: + with conn.cursor() as cursor: + sql = "UPDATE overseas_projects SET recent_log = %s, file_count = %s WHERE project_id = %s" + cursor.execute(sql, (recent_log, file_count, current_p_id)) + conn.commit() + msg_queue.put(json.dumps({'type': 'log', 'message': f' - [DB] 업데이트 완료 (ID: {current_p_id})'})) + finally: conn.close() - # --- 4. CSV 파일 저장 --- - try: - today_str = datetime.now().strftime("%Y.%m.%d") - csv_path = f"crawling_result {today_str}.csv" - with open(csv_path, 'w', newline='', encoding='utf-8-sig') as f: - writer = csv.DictWriter(f, fieldnames=["projectName", "recentLog", "fileCount"]) - writer.writeheader() - writer.writerows(results) - yield f"data: {json.dumps({'type': 'log', 'message': f'✅ 모든 데이터가 {csv_path}에 저장되었습니다.'})}\n\n" - except Exception as fe: - yield f"data: {json.dumps({'type': 'log', 'message': f'❌ CSV 저장 실패: {str(fe)}'})}\n\n" + await page.goto("https://overseas.projectmastercloud.com/dashboard", wait_until="domcontentloaded") + + except Exception as e: + msg_queue.put(json.dumps({'type': 'log', 'message': f' - [{project_name}] 건너뜀: {str(e)}'})) + await page.goto("https://overseas.projectmastercloud.com/dashboard") - yield f"data: {json.dumps({'type': 'done', 'data': results})}\n\n" - - except Exception as e: - yield f"data: {json.dumps({'type': 'log', 'message': f'치명적 오류: {str(e)}'})}\n\n" - finally: - if browser: await browser.close() + msg_queue.put(json.dumps({'type': 'done', 'data': []})) + + except Exception as e: + msg_queue.put(json.dumps({'type': 'log', 'message': f'치명적 오류: {str(e)}'})) + finally: + if browser: await browser.close() + msg_queue.put(None) + + loop.run_until_complete(run()) + loop.close() + +async def run_crawler_service(): + user_id = os.getenv("PM_USER_ID") + password = os.getenv("PM_PASSWORD") + msg_queue = queue.Queue() + thread = threading.Thread(target=crawler_thread_worker, args=(msg_queue, user_id, password)) + thread.start() + while True: + try: + msg = await asyncio.to_thread(msg_queue.get, timeout=1.0) + if msg is None: break + yield f"data: {msg}\n\n" + except queue.Empty: + if not thread.is_alive(): break + await asyncio.sleep(0.1) + thread.join() diff --git a/crawling_result 2026.03.06.csv b/crawling_result 2026.03.06.csv new file mode 100644 index 0000000..bd6d6c4 --- /dev/null +++ b/crawling_result 2026.03.06.csv @@ -0,0 +1,42 @@ +projectName,recentLog,fileCount +ITTC 관개 교육센터,"26.01.29, 박진규, 폴더 삭제",16 +비엔티안 메콩강 관리 2차,"25.12.07, 나쉬, 파일 업로드",260 +만달레이 철도 개량 감리,"25.11.19, 이태훈, 보안참여자 권한 추가",298 +푸옥호아 양수 발전,"26.02.23, 이철호, 폴더 이름 변경",139 +아시르 지잔 고속도로,"26.03.04, 이태훈, 보안참여자 권한 추가",73 +지방 도로 복원,"26.03.04, 이태훈, 보안참여자 권한 추가",0 +타슈켄트 철도,"26.02.05, 조항언, 파일 업로드",51 +Habbaniyah Shuaiba AirBase,"26.03.04, 이태훈, 보안참여자 권한 추가",0 +시엠립 하수처리 개선,"26.02.09, 이태훈, 보안참여자 권한 추가",221 +반테 민체이 관개 홍수저감,"25.12.07, 나쉬, 파일 업로드",44 +메콩유역 수자원 관리 기후적응,"25.11.19, 이태훈, 보안참여자 권한 추가",0 +잘랄아바드 상수도 계획,"26.03.06, -, 폴더 자동 삭제 (파일 개수 미달)",58 +CAREC 도로 감리,"26.03.04, 이태훈, 보안참여자 권한 추가",0 +펀잡 홍수 방재,"25.12.08, 콰윰 아딜, 폴더 삭제",0 +KP 아보타바드 상수도,"26.02.26, 정기일, 파일 업로드",240 +홍수 복원 InFRA2,"25.12.18, -, 폴더 자동 삭제 (파일 개수 미달)",6 +PGN 해상교량 BID2,"26.03.04, 이태훈, 보안참여자 권한 추가",631 +홍수 관리 Package5B,"25.12.02, 조명훈, 폴더 이름 변경",14 +족자~바웬 도로사업,"26.03.06, 시스템관리-Savannah, 참관자 권한 추가",0 +테치만 상수도 확장,"26.02.09, 이태훈, 보안참여자 권한 추가",0 +기니 벼 재배단지,"26.01.07, -, 폴더 자동 삭제 (파일 개수 미달)",43 +부수쿠마 분뇨 자원화 2단계,"26.02.09, 이태훈, 보안참여자 권한 추가",9 +우간다 벼 재배단지,"25.12.08, 박수빈, 파일 업로드",52 +Adeaa-Becho 지하수 관개,"25.12.29, -, 폴더 자동 삭제 (파일 개수 미달)",140 +도도타군 관개,"25.12.30, -, 폴더 자동 삭제 (파일 개수 미달)",142 +지하수 관개 환경설계,"26.02.09, 이태훈, 보안참여자 권한 추가",0 +Dodoma 하수 설계감리,"26.02.09, 이태훈, 보안참여자 권한 추가",32 +Iringa 상하수도 개선,"26.02.09, 이태훈, 보안참여자 권한 추가",0 +도도마 유수율 상수도개선,"26.02.12, 서하연, 부관리자 권한 추가",35 +잔지바르 쌀 생산,"25.12.08, 박수빈, 파일 업로드",23 +SALDEORO 수력발전 28MW,"25.11.19, 이태훈, 보안참여자 권한 추가",0 +LaPaz Danli 상수도,"26.02.09, 이태훈, 보안참여자 권한 추가",60 +에스꼬마 차라짜니 도로,"26.03.06, -, 폴더 자동 삭제 (파일 개수 미달)",0 +마모레 교량도로,"26.03.04, 이태훈, 보안참여자 권한 추가",120 +Bombeo-Colomi 도로설계,"26.03.04, 이태훈, 보안참여자 권한 추가",48 +AI 폐기물,"25.11.19, 이태훈, 보안참여자 권한 추가",0 +도로 통행료 현대화,"26.02.25, 류창수, 폴더 삭제",0 +Barranca 상하수도 확장,"26.02.09, 이태훈, 보안참여자 권한 추가",44 +태평양 철도,"26.02.24, -, 폴더 자동 삭제 (파일 개수 미달)",101 +필리핀 사무소,"26.03.06, 한형남, 파일 다운로드",316 +PGN 해상교량 BID2,"26.03.04, 이태훈, 보안참여자 권한 추가",631 diff --git a/crawling_result 2026.03.09.csv b/crawling_result 2026.03.09.csv new file mode 100644 index 0000000..b1bc926 --- /dev/null +++ b/crawling_result 2026.03.09.csv @@ -0,0 +1,42 @@ +projectName,recentLog,fileCount +비엔티안 메콩강 관리 2차,212487_25-12-07 12:22:26_나쉬_파일 업로드_/서류/06. 전문가파견/01. 파견/251031~260208_전문가 파견(이범주).zip,260 +ITTC 관개 교육센터,225728_26-01-29 09:10:21_박진규_폴더 삭제_/서류/ggg,16 +만달레이 철도 개량 감리,207041_25-11-19 16:54:36_이태훈_보안참여자 권한 추가_홍아름_김혜인,298 +푸옥호아 양수 발전,233465_26-02-23 10:24:46_이철호_폴더 이름 변경_/6 준공/3 준공도서 26년 2월 작성예정 발주처 협의중_/6 준공/3 준공도서 26년 3월 작성예정 발주처 협의중,139 +아시르 지잔 고속도로,234455_26-03-04 14:31:52_이태훈_보안참여자 권한 추가_복진훈,73 +타슈켄트 철도,228919_26-02-05 10:08:11_조항언_파일 업로드_/02_성과품/B_중간보고/BB_중간보고서/[러문] INTERIM REPORT_0115_F.pdf,51 +지방 도로 복원,234456_26-03-04 14:32:07_이태훈_보안참여자 권한 추가_복진훈,0 +Habbaniyah Shuaiba AirBase,234457_26-03-04 14:32:28_이태훈_보안참여자 권한 추가_복진훈,0 +시엠립 하수처리 개선,231205_26-02-09 11:03:05_이태훈_보안참여자 권한 추가_김창환_배형원,221 +반테 민체이 관개 홍수저감,212512_25-12-07 12:35:02_나쉬_파일 업로드_/서류/04. 기성/18차 기성금/06. 통장사본.pdf,44 +메콩유역 수자원 관리 기후적응,207047_25-11-19 17:01:19_이태훈_보안참여자 권한 추가_홍아름_김혜인,0 +잘랄아바드 상수도 계획,234860_26-03-06 10:24:27_-_폴더 자동 삭제 (파일 개수 미달)_/4. MP 성과품/3. 최종보고서/초안 제출,58 +펀잡 홍수 방재,212686_25-12-08 13:05:24_콰윰 아딜_폴더 삭제_/RFP,0 +CAREC 도로 감리,234458_26-03-04 14:32:50_이태훈_보안참여자 권한 추가_복진훈,0 +KP 아보타바드 상수도,234120_26-02-26 20:58:46_정기일_파일 업로드_/99 참고자료/99 체코 두코바니 원전/00 2025년 입찰/Engineering work instruction_241206.pdf,240 +PGN 해상교량 BID2,234454_26-03-04 14:31:31_이태훈_보안참여자 권한 추가_복진훈,631 +홍수 복원 InFRA2,214399_25-12-18 09:05:49_-_폴더 자동 삭제 (파일 개수 미달)_/서류/3.경비신청 및 정산/1. 신청,6 +홍수 관리 Package5B,211353_25-12-02 10:04:18_조명훈_폴더 이름 변경_/서류/01. 계약서/01. 계약서_/서류/01. 계약서/01. 사업계약서,14 +족자~바웬 도로사업,234908_26-03-06 13:36:39_시스템관리-Savannah_참관자 권한 추가_이호성,0 +테치만 상수도 확장,231210_26-02-09 11:06:41_이태훈_보안참여자 권한 추가_배형원_정낙훈,0 +기니 벼 재배단지,216888_26-01-07 11:07:23_-_폴더 자동 삭제 (파일 개수 미달)_/계약서류/경비 신청 및 정산/01. 신청,43 +우간다 벼 재배단지,"212622_25-12-08 11:17:57_박수빈_파일 업로드_/계약서류/경비 신청 및 정산/01. 현장경비 신청전표/11-20251029-J0401-006 (9,10월 현장운영비).pdf",52 +부수쿠마 분뇨 자원화 2단계,231215_26-02-09 11:08:34_이태훈_보안참여자 권한 추가_김창환_배형원,9 +지하수 관개 환경설계,231212_26-02-09 11:07:35_이태훈_보안참여자 권한 추가_김창환_배형원,0 +Adeaa-Becho 지하수 관개,215553_25-12-29 09:36:23_-_폴더 자동 삭제 (파일 개수 미달)_/Topographic Survey/측량조사성과품/Appendix B - List of GPS Control Points,140 +도도타군 관개,215706_25-12-30 09:17:43_-_폴더 자동 삭제 (파일 개수 미달)_/서류/03.경비신청 및 정산/02.사내정산 2차,142 +Iringa 상하수도 개선,231216_26-02-09 11:10:18_이태훈_보안참여자 권한 추가_김창환_배형원,0 +Dodoma 하수 설계감리,231217_26-02-09 11:11:06_이태훈_보안참여자 권한 추가_김창환_배형원,32 +도도마 유수율 상수도개선,232629_26-02-12 17:26:13_서하연_부관리자 권한 추가_정기일,35 +잔지바르 쌀 생산,212641_25-12-08 11:43:37_박수빈_파일 업로드_/서류/경비신청 및 정산/01. 25년/11-20250409-J0401-005 (운영경비 2분기 송금).pdf,23 +SALDEORO 수력발전 28MW,207029_25-11-19 16:44:04_이태훈_보안참여자 권한 추가_홍아름_김혜인,0 +LaPaz Danli 상수도,231219_26-02-09 11:12:37_이태훈_보안참여자 권한 추가_배형원_정낙훈,60 +에스꼬마 차라짜니 도로,234837_26-03-06 08:00:21_-_폴더 자동 삭제 (파일 개수 미달)_/EOI/001/EOI서류,0 +Bombeo-Colomi 도로설계,234463_26-03-04 14:34:24_이태훈_보안참여자 권한 추가_복진훈,48 +마모레 교량도로,234462_26-03-04 14:33:56_이태훈_보안참여자 권한 추가_복진훈,120 +AI 폐기물,207034_25-11-19 16:50:49_이태훈_보안참여자 권한 추가_홍아름_김혜인,0 +도로 통행료 현대화,233938_26-02-25 14:39:08_류창수_폴더 삭제_/필리핀다바오프로젝트,0 +Barranca 상하수도 확장,231220_26-02-09 11:13:28_이태훈_보안참여자 권한 추가_김창환_배형원,44 +태평양 철도,233798_26-02-24 17:52:33_-_폴더 자동 삭제 (파일 개수 미달)_/01_수행문서/D_보고자료/D6_최종보고,101 +필리핀 사무소,234973_26-03-09 09:35:45_한형남_파일 다운로드_/3. DPTMP(Davao Public Transportation Modernization Project)/AFCS/2.배포자료/PHI DPTMP AFCS Package PIM 04March2026.pdf_/3. DPTMP(Davao Public Transportation Modernization Project)/AFCS/2.배포자료/PAFCS PIM v04March2026.pdf,322 +PGN 해상교량 BID2,234454_26-03-04 14:31:31_이태훈_보안참여자 권한 추가_복진훈,631 diff --git a/crwaling_result.csv b/crwaling_result.csv new file mode 100644 index 0000000..5560a02 --- /dev/null +++ b/crwaling_result.csv @@ -0,0 +1,42 @@ +projectName,recentLog,fileCount +ITTC 관개 교육센터,"26.01.29, 박진규, 폴더 삭제",16 +비엔티안 메콩강 관리 2차,"25.12.07, 나쉬, 파일 업로드",260 +만달레이 철도 개량 감리,"25.11.19, 이태훈, 보안참여자 권한 추가",298 +푸옥호아 양수 발전,"26.02.23, 이철호, 폴더 이름 변경",139 +아시르 지잔 고속도로,"26.03.04, 이태훈, 보안참여자 권한 추가",75 +지방 도로 복원,"26.03.04, 이태훈, 보안참여자 권한 추가",0 +타슈켄트 철도,"26.02.05, 조항언, 파일 업로드",51 +Habbaniyah Shuaiba AirBase,"26.03.04, 이태훈, 보안참여자 권한 추가",0 +시엠립 하수처리 개선,"26.02.09, 이태훈, 보안참여자 권한 추가",222 +반테 민체이 관개 홍수저감,"25.12.07, 나쉬, 파일 업로드",0 +메콩유역 수자원 관리 기후적응,"25.11.19, 이태훈, 보안참여자 권한 추가",0 +잘랄아바드 상수도 계획,"26.03.06, -, 폴더 자동 삭제 (파일 개수 미달)",58 +CAREC 도로 감리,"26.03.04, 이태훈, 보안참여자 권한 추가",0 +펀잡 홍수 방재,"25.12.08, 콰윰 아딜, 폴더 삭제",0 +KP 아보타바드 상수도,"26.02.26, 정기일, 파일 업로드",240 +홍수 복원 InFRA2,"25.12.18, -, 폴더 자동 삭제 (파일 개수 미달)",6 +PGN 해상교량 BID2,"26.03.04, 이태훈, 보안참여자 권한 추가",0 +홍수 관리 Package5B,"25.12.02, 조명훈, 폴더 이름 변경",14 +족자~바웬 도로사업,"26.03.06, 시스템관리-Savannah, 참관자 권한 추가",0 +테치만 상수도 확장,"26.02.09, 이태훈, 보안참여자 권한 추가",0 +기니 벼 재배단지,"26.01.07, -, 폴더 자동 삭제 (파일 개수 미달)",44 +부수쿠마 분뇨 자원화 2단계,"26.02.09, 이태훈, 보안참여자 권한 추가",9 +우간다 벼 재배단지,"25.12.08, 박수빈, 파일 업로드",52 +Adeaa-Becho 지하수 관개,"25.12.29, -, 폴더 자동 삭제 (파일 개수 미달)",140 +도도타군 관개,"25.12.30, -, 폴더 자동 삭제 (파일 개수 미달)",0 +지하수 관개 환경설계,"26.02.09, 이태훈, 보안참여자 권한 추가",0 +Dodoma 하수 설계감리,"26.02.09, 이태훈, 보안참여자 권한 추가",32 +Iringa 상하수도 개선,"26.02.09, 이태훈, 보안참여자 권한 추가",0 +도도마 유수율 상수도개선,"26.02.12, 서하연, 부관리자 권한 추가",35 +잔지바르 쌀 생산,"25.12.08, 박수빈, 파일 업로드",23 +SALDEORO 수력발전 28MW,"25.11.19, 이태훈, 보안참여자 권한 추가",0 +LaPaz Danli 상수도,"26.02.09, 이태훈, 보안참여자 권한 추가",65 +에스꼬마 차라짜니 도로,"26.03.06, -, 폴더 자동 삭제 (파일 개수 미달)",0 +마모레 교량도로,"26.03.04, 이태훈, 보안참여자 권한 추가",120 +Bombeo-Colomi 도로설계,"26.03.04, 이태훈, 보안참여자 권한 추가",49 +AI 폐기물,"25.11.19, 이태훈, 보안참여자 권한 추가",0 +도로 통행료 현대화,"26.02.25, 류창수, 폴더 삭제",0 +Barranca 상하수도 확장,"26.02.09, 이태훈, 보안참여자 권한 추가",50 +태평양 철도,"26.02.24, -, 폴더 자동 삭제 (파일 개수 미달)",101 +필리핀 사무소,"26.03.06, 한형남, 파일 다운로드",0 +PGN 해상교량 BID2,"26.03.04, 이태훈, 보안참여자 권한 추가",637 diff --git a/db_2026.03.09.csv b/db_2026.03.09.csv new file mode 100644 index 0000000..475e24e --- /dev/null +++ b/db_2026.03.09.csv @@ -0,0 +1,42 @@ +[PM Overseas 프로젝트 현황],,2026.03.04,,,,,,<<활동로그가 없는 프로젝트 (8),, +,,,,,,,,,, +No.,프로젝트 명,담당부서,담당자,종료(예정)일,최근 활동로그,과업개요 작성 유무,파일 수,비고,, +1,라오스 ITTC 관개 교육센터 PMC,수자원1부,방노성,2025.12.20,"2026.01.29, 폴더 삭제",O,16,2026.01.29 로그는 테스트 활동 추정,종료(예정)일 지남,진행 +2,라오스 비엔티안 메콩강 관리 2차 DD,수자원1부,방노성,2026.05.31,"2025.12.07, 파일업로드",X,260,탭 1개에 모든파일 업로드,, +3,미얀마 만달레이 철도 개량 감리 CS,철도사업부,김태헌,2027.11.17,"2025.11.17, 폴더이름변경",O,298,,, +4,베트남 푸옥호아 양수 발전 FS,수력부,이철호,2025.11.30,"2026.02.23, 폴더이름변경",O,139,준공도서 3월 작성예정,종료(예정)일 지남,준공 +5,사우디아라비아 아시르 지잔 고속도로 FS,도로부,공태원,2025.11.21,"2026.02.09, 파일다운로드",O,73,,종료(예정)일 지남,준공 +6,우즈베키스탄 지방 도로 복원 MP,도로부,장진영,2029.04.28,X,X,0,,, +7,우즈베키스탄 타슈켄트 철도 FS,철도사업부,김태헌,2026.03.20,"2026.02.05, 파일업로드",O,51,,, +8,이라크 Habbaniyah Shuaiba AirBase PD,도로부,강동구,2026.12.31,X,X,0,,, +9,메콩유역 수자원 관리 기후적응 MP,수자원1부,정귀한,2025.12.31,X,X,0,,종료(예정)일 지남,준공 +10,캄보디아 반테 민체이 관개 홍수저감 MP,수자원1부,이대주,2026.08.28,"2025.12.07, 파일업로드",X,44,,, +11,캄보디아 시엠립 하수처리 개선 DD,물환경사업1부,변역근,2028.12.18,"2026.02.06, AI 요약",O,221,,, +12,키르기스스탄 잘랄아바드 상수도 계획 MP,물환경사업1부,변기상,2025.12.31,"2026.02.12, 파일업로드",X,60,,종료(예정)일 지남,준공 +13,파키스탄 펀잡 홍수 방재 PMC,수자원1부,방노성,2027.12.31,"2025.12.08, 폴더삭제",O,0,,, +14,파키스탄 KP 아보타바드 상수도 PMC,물환경사업2부,변기상,2026.12.31,"2026.02.26, 파일업로드",O,240,,, +15,파키스탄 CAREC 도로 감리 DD,도로부,황효섭,2026.10.26,X,X,0,,, +16,필리핀 홍수 복원 InFRA2 DD,수자원1부,이대주,2026.08.07,"2025.12.01, 폴더삭제",O,6,최근로그 >> 폴더자동삭제(파일 개수 미달),, +17,필리핀 홍수 관리 Package5B MP,수자원1부,이희철,2026.05.31,"2025.12.02, 폴더이름변경",O,14,,, +18,필리핀 PGN 해상교량 BID2 IDC,구조부,이상희,2026.05.31,"2026.02.11, 파일다운로드",O,631,,, +19,가나 테치만 상수도 확장 DS,물환경사업2부,-,2029.04.25,X,X,0,책임자 및 담당자 설정X,, +20,기니 벼 재배단지 PMC,수자원1부,이대주,2028.12.20,"2025.12.08, 파일업로드",O,43,최근로그 >> 폴더자동삭제(파일 개수 미달),, +21,우간다 벼 재배단지 PMC,수자원1부,방노성,2028.12.20,"2025.12.08, 파일업로드",O,52,,, +22,우간다 부수쿠마 분뇨 자원화 2단계 PMC,물환경사업2부,변기상,2026.12.31,"2026.02.05, 파일업로드",X,9,,, +23,에티오피아 지하수 관개 환경설계 DD,물환경사업2부,변기상,2026.06.23,X,X,0,,, +24,에티오피아 도도타군 관개 PMC,수자원1부,방노성,2026.12.31,"2025.12.01, 폴더이름변경",O,144,탭 1개에 모든파일 업로드 // 최근로그 >> 폴더자동삭제(파일 개수 미달),, +25,에티오피아 Adeaa-Becho 지하수 관개 MP,수자원1부,방노성,2026.07.31,"2025.11.21, 파일업로드",O,146,최근로그 >> 폴더자동삭제(파일 개수 미달),, +26,탄자니아 Iringa 상하수도 개선 CS,물환경사업1부,백운영,2029.06.08,"2026.02.03, 폴더생성",X,0,,, +27,탄자니아 Dodoma 하수 설계감리 DD,물환경사업2부,변기상,2027.07.08,"2026.02.04, 폴더삭제",X,32,,, +28,탄자니아 잔지바르 쌀 생산 PMC,수자원1부,방노성,2027.12.20,"2025.12.08, 파일 업로드",O,23,,, +29,탄자니아 도도마 유수율 상수도개선 PMC,물환경사업1부,박순석,2026.12.31,"2026.02.12, 부관리자권한추가",X,35,,, +30,아르헨티나 SALDEORO 수력발전 28MW DD,플랜트1부,양정모,2026.01.31,X,X,0,,종료(예정)일 지남,준공 +31,온두라스 LaPaz Danli 상수도 CS,물환경사업2부,-,2027.02.23,"2026.01.29, 파일 삭제",O,60,"책임자 및 담당자 설정 X, 실 관리부서는 해외사업부, 더미파일 다수",, +32,볼리비아 에스꼬마 차라짜니 도로 CS,도로부,전홍찬,2029.12.15,"2026.02.06, 파일업로드",X,1,,, +33,볼리비아 마모레 교량도로 FS,도로부,황효섭,2025.10.17,"2026.02.06, 파일업로드",X,120,,종료(예정)일 지남,준공 +34,볼리비아 Bombeo-Colomi 도로설계 DD,도로부,황효섭,2026.07.24,"2025.12.05, 파일삭제",O,48,"더미파일(폴더유지용) 12개, 실 관리부서는 해외사업부",, +35,콜롬비아 AI 폐기물 FS,플랜트1부,서재희,2026.02.27,X,X,0,,종료(예정)일 지남, +36,파라과이 도로 통행료 현대화 MP,교통계획부,오제훈,2025.10.24,"2025.02.25, 폴더삭제",X,0,,종료(예정)일 지남,준공 +37,페루 Barranca 상하수도 확장 DD,물환경사업2부,변기상,2026.03.08,"2025.11.14, 파일업로드",O,44,"더미파일(폴더유지용) 27개, 실 관리부서는 해외사업부",, +38,엘살바도르 태평양 철도 FS,철도사업부,김태헌,2025.12.31,"2026.02.24, 폴더자동삭제",X,101,,종료(예정)일 지남,준공 +39,필리핀 사무소,해외사업부,한형남,,"2026-03-09, 파일다운로드",과업개요 페이지 없음,323,,, diff --git a/db_2026.03.10.csv b/db_2026.03.10.csv new file mode 100644 index 0000000..4708abf --- /dev/null +++ b/db_2026.03.10.csv @@ -0,0 +1,42 @@ +[PM Overseas 프로젝트 현황],,2026.03.04,,,,,,<<활동로그가 없는 프로젝트 (8),, +,,,,,,,,,, +No.,프로젝트 명,담당부서,담당자,종료(예정)일,최근 활동로그,과업개요 작성 유무,파일 수,비고,, +1,라오스 ITTC 관개 교육센터 PMC,수자원1부,방노성,2025.12.20,"2026.01.29, 폴더 삭제",O,16,2026.01.29 로그는 테스트 활동 추정,종료(예정)일 지남,진행 +2,라오스 비엔티안 메콩강 관리 2차 DD,수자원1부,방노성,2026.05.31,"2025.12.07, 파일업로드",X,260,탭 1개에 모든파일 업로드,, +3,미얀마 만달레이 철도 개량 감리 CS,철도사업부,김태헌,2027.11.17,"2025.11.17, 폴더이름변경",O,298,,, +4,베트남 푸옥호아 양수 발전 FS,수력부,이철호,2025.11.30,"2026.02.23, 폴더이름변경",O,139,준공도서 3월 작성예정,종료(예정)일 지남,준공 +5,사우디아라비아 아시르 지잔 고속도로 FS,도로부,공태원,2025.11.21,"2026.02.09, 파일다운로드",O,73,,종료(예정)일 지남,준공 +6,우즈베키스탄 지방 도로 복원 MP,도로부,장진영,2029.04.28,X,X,0,,, +7,우즈베키스탄 타슈켄트 철도 FS,철도사업부,김태헌,2026.03.20,"2026.02.05, 파일업로드",O,51,,, +8,이라크 Habbaniyah Shuaiba AirBase PD,도로부,강동구,2026.12.31,X,X,0,,, +9,메콩유역 수자원 관리 기후적응 MP,수자원1부,정귀한,2025.12.31,X,X,0,,종료(예정)일 지남,준공 +10,캄보디아 반테 민체이 관개 홍수저감 MP,수자원1부,이대주,2026.08.28,"2025.12.07, 파일업로드",X,44,,, +11,캄보디아 시엠립 하수처리 개선 DD,물환경사업1부,변역근,2028.12.18,"2026.02.06, AI 요약",O,221,,, +12,키르기스스탄 잘랄아바드 상수도 계획 MP,물환경사업1부,변기상,2025.12.31,"2026.02.12, 파일업로드",X,60,,종료(예정)일 지남,준공 +13,파키스탄 펀잡 홍수 방재 PMC,수자원1부,방노성,2027.12.31,"2025.12.08, 폴더삭제",O,0,,, +14,파키스탄 KP 아보타바드 상수도 PMC,물환경사업2부,변기상,2026.12.31,"2026.02.26, 파일업로드",O,240,,, +15,파키스탄 CAREC 도로 감리 DD,도로부,황효섭,2026.10.26,X,X,0,,, +16,필리핀 홍수 복원 InFRA2 DD,수자원1부,이대주,2026.08.07,"2025.12.01, 폴더삭제",O,6,최근로그 >> 폴더자동삭제(파일 개수 미달),, +17,필리핀 홍수 관리 Package5B MP,수자원1부,이희철,2026.05.31,"2025.12.02, 폴더이름변경",O,14,,, +18,필리핀 PGN 해상교량 BID2 IDC,구조부,이상희,2026.05.31,"2026.02.11, 파일다운로드",O,631,,, +19,가나 테치만 상수도 확장 DS,물환경사업2부,-,2029.04.25,X,X,0,책임자 및 담당자 설정X,, +20,기니 벼 재배단지 PMC,수자원1부,이대주,2028.12.20,"2025.12.08, 파일업로드",O,43,최근로그 >> 폴더자동삭제(파일 개수 미달),, +21,우간다 벼 재배단지 PMC,수자원1부,방노성,2028.12.20,"2025.12.08, 파일업로드",O,52,,, +22,우간다 부수쿠마 분뇨 자원화 2단계 PMC,물환경사업2부,변기상,2026.12.31,"2026.02.05, 파일업로드",X,9,,, +23,에티오피아 지하수 관개 환경설계 DD,물환경사업2부,변기상,2026.06.23,X,X,0,,, +24,에티오피아 도도타군 관개 PMC,수자원1부,방노성,2026.12.31,"2025.12.01, 폴더이름변경",O,144,탭 1개에 모든파일 업로드 // 최근로그 >> 폴더자동삭제(파일 개수 미달),, +25,에티오피아 Adeaa-Becho 지하수 관개 MP,수자원1부,방노성,2026.07.31,"2025.11.21, 파일업로드",O,146,최근로그 >> 폴더자동삭제(파일 개수 미달),, +26,탄자니아 Iringa 상하수도 개선 CS,물환경사업1부,백운영,2029.06.08,"2026.02.03, 폴더생성",X,0,,, +27,탄자니아 Dodoma 하수 설계감리 DD,물환경사업2부,변기상,2027.07.08,"2026.02.04, 폴더삭제",X,32,,, +28,탄자니아 잔지바르 쌀 생산 PMC,수자원1부,방노성,2027.12.20,"2025.12.08, 파일 업로드",O,23,,, +29,탄자니아 도도마 유수율 상수도개선 PMC,물환경사업1부,박순석,2026.12.31,"2026.02.12, 부관리자권한추가",X,35,,, +30,아르헨티나 SALDEORO 수력발전 28MW DD,플랜트1부,양정모,2026.01.31,X,X,0,,종료(예정)일 지남,준공 +31,온두라스 LaPaz Danli 상수도 CS,물환경사업2부,-,2027.02.23,"2026.01.29, 파일 삭제",O,60,"책임자 및 담당자 설정 X, 실 관리부서는 해외사업부, 더미파일 다수",, +32,볼리비아 에스꼬마 차라짜니 도로 CS,도로부,전홍찬,2029.12.15,"2026.02.06, 파일업로드",X,1,,, +33,볼리비아 마모레 교량도로 FS,도로부,황효섭,2025.10.17,"2026.02.06, 파일업로드",X,120,,종료(예정)일 지남,준공 +34,볼리비아 Bombeo-Colomi 도로설계 DD,도로부,황효섭,2026.07.24,"2025.12.05, 파일삭제",O,48,"더미파일(폴더유지용) 12개, 실 관리부서는 해외사업부",, +35,콜롬비아 AI 폐기물 FS,플랜트1부,서재희,2026.02.27,X,X,0,,종료(예정)일 지남, +36,파라과이 도로 통행료 현대화 MP,교통계획부,오제훈,2025.10.24,"2025.02.25, 폴더삭제",X,0,,종료(예정)일 지남,준공 +37,페루 Barranca 상하수도 확장 DD,물환경사업2부,변기상,2026.03.08,"2025.11.14, 파일업로드",O,44,"더미파일(폴더유지용) 27개, 실 관리부서는 해외사업부",, +38,엘살바도르 태평양 철도 FS,철도사업부,김태헌,2025.12.31,"2026.02.24, 폴더자동삭제",X,101,,종료(예정)일 지남,준공 +39,필리핀 사무소,해외사업부,한형남,,"2026.03.10, PDF 변환",과업개요 페이지 없음,829,,, diff --git a/diag_folders.py b/diag_folders.py new file mode 100644 index 0000000..d63fa8e --- /dev/null +++ b/diag_folders.py @@ -0,0 +1,66 @@ +import asyncio, os, json, re, sys +from playwright.async_api import async_playwright +from dotenv import load_dotenv + +load_dotenv() + +async def run_diagnostics(): + user_id = os.getenv("PM_USER_ID") + password = os.getenv("PM_PASSWORD") + + async with async_playwright() as p: + browser = await p.chromium.launch(headless=False) + context = await browser.new_context(viewport={"width": 1600, "height": 900}) + page = await context.new_page() + + print(">>> 로그인 중...") + await page.goto("https://overseas.projectmastercloud.com/dashboard") + if await page.locator("#login-by-id").is_visible(timeout=5000): + await page.click("#login-by-id") + await page.fill("#user_id", user_id) + await page.fill("#user_pw", password) + await page.click("#login-btn") + + await page.wait_for_selector("h4.list__contents_aria_group_body_list_item_label", timeout=60000) + + project_name = "필리핀 사무소" + print(f">>> [{project_name}] 폴더 전수 조사 시작...") + + target_el = page.get_by_text(project_name).first + await target_el.scroll_into_view_if_needed() + await target_el.click(force=True) + + await asyncio.sleep(10) # 충분한 로딩 대기 + + print("\n" + "="*60) + print(f"{'No':<4} | {'Folder Name':<40} | {'Files'}") + print("-" * 60) + + # fetch 결과를 직접 리턴받음 + tree_data = await page.evaluate("""async () => { + const resp = await fetch('/api/getTreeObject?params[storageType]=CLOUD¶ms[resourcePath]=/'); + return await resp.json(); + }""") + + if tree_data: + tree = tree_data.get('currentTreeObject', {}) + folders = tree.get('folder', {}) + folder_items = list(folders.values()) if isinstance(folders, dict) else (folders if isinstance(folders, list) else []) + + total_sum = 0 + for i, f in enumerate(folder_items): + name = f.get('name', 'Unknown') + count = int(f.get('filesCount', 0)) + total_sum += count + print(f"{i+1:<4} | {name:<40} | {count}개") + + print("-" * 60) + print(f">>> 총 {len(folder_items)}개 폴더 발견 | 전체 파일 합계: {total_sum}개") + print("="*60) + else: + print(">>> [오류] 데이터를 가져오지 못했습니다.") + + await browser.close() + +if __name__ == "__main__": + asyncio.run(run_diagnostics()) diff --git a/js/dashboard.js b/js/dashboard.js index d057f79..792fb01 100644 --- a/js/dashboard.js +++ b/js/dashboard.js @@ -37,19 +37,9 @@ async function init() { rawData.forEach((item, index) => { const projectName = item[0]; - let continent = ""; - let country = ""; - - if (projectName.endsWith("사무소")) { - continent = "지사"; - country = projectName.split(" ")[0]; - } else if (projectName.startsWith("메콩유역")) { - country = "캄보디아"; - continent = "아시아"; - } else { - country = projectName.split(" ")[0]; - continent = continentMap[country] || "기타"; - } + // DB에서 넘어온 대륙과 국가 정보 사용 (item[5], item[6]) + let continent = item[5] || "기타"; + let country = item[6] || "미분류"; if (!groupedData[continent]) groupedData[continent] = {}; if (!groupedData[continent][country]) groupedData[continent][country] = []; diff --git a/log_debug.png b/log_debug.png new file mode 100644 index 0000000000000000000000000000000000000000..dcb29f1fa173a184f2e932f33d272488bf5c0378 GIT binary patch literal 129162 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ⅇ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 w68gRxq!}STemCDDSz+5ek7SP=K0p1R= 8: - # [프로젝트명, 담당부서, 담당자, 최근활동로그, 파일수] - # 복구된 sheet.csv 형식에 맞춰 인덱스 추출 (1, 2, 3, 5, 7) - try: - # 파일 수 숫자로 변환 (공백 제거 후 처리) - raw_count = row[7].strip() - file_count = int(raw_count) if raw_count.isdigit() else 0 - except (ValueError, IndexError): - file_count = 0 - - projects.append([ - row[1], # 프로젝트 명 - row[2], # 담당부서 - row[3], # 담당자 - row[5], # 최근 활동로그 - file_count # 파일 수 - ]) + conn = get_db_connection() + try: + with conn.cursor() as cursor: + # 대시보드에 필요한 모든 정보를 쿼리 (short_nm 포함) + cursor.execute("SELECT project_nm, short_nm, department, master, recent_log, file_count, continent, country FROM overseas_projects ORDER BY id ASC") + rows = cursor.fetchall() + + # 프론트엔드 기대 형식에 맞춰 반환 + # [표시될 프로젝트명(short_nm), 담당부서, 담당자, 최근활동로그, 파일수, 대륙, 국가] + projects = [] + for row in rows: + # short_nm이 있으면 그것을 쓰고, 없으면 project_nm 사용 + display_name = row['short_nm'] if row['short_nm'] and row['short_nm'].strip() else row['project_nm'] + projects.append([ + display_name, + row['department'], + row['master'], + row['recent_log'], + row['file_count'], + row['continent'], + row['country'] + ]) + return projects + finally: + conn.close() except Exception as e: - print(f"Error reading sheet.csv: {e}") + print(f"Error fetching from DB: {e}") return {"error": str(e)} - - return projects @app.get("/") async def root(request: Request): diff --git a/server_reboot.log b/server_reboot.log new file mode 100644 index 0000000000000000000000000000000000000000..8a8f47f37d79037894171bdfbadc448c66c2c371 GIT binary patch literal 93476 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 literal 0 HcmV?d00001 diff --git a/server_revert.log b/server_revert.log new file mode 100644 index 0000000000000000000000000000000000000000..955460613ea1c1de81d78692f80967c899188afa GIT binary patch literal 47692 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 literal 0 HcmV?d00001 diff --git a/test_main_filtered.py b/test_main_filtered.py new file mode 100644 index 0000000..ceed5ba --- /dev/null +++ b/test_main_filtered.py @@ -0,0 +1,33 @@ +import asyncio, os, json, queue, threading +from crawler_service import crawler_thread_worker +from dotenv import load_dotenv + +load_dotenv() + +async def run_main_test(): + user_id = os.getenv("PM_USER_ID") + password = os.getenv("PM_PASSWORD") + msg_queue = queue.Queue() + + thread = threading.Thread(target=crawler_thread_worker, args=(msg_queue, user_id, password)) + thread.start() + + print(">>> 메인 워커 실행 중 (필리핀 사무소)...") + try: + while True: + msg_raw = await asyncio.to_thread(msg_queue.get, timeout=300) + if msg_raw is None: break + + msg = json.loads(msg_raw) + if msg["type"] == "log": + print(f"[LOG] {msg['message']}") + elif msg["type"] == "done": + print(f"\n[DONE] 최종 결과: {msg['data']}") + break + except queue.Empty: + print(">>> 타임아웃") + finally: + thread.join() + +if __name__ == "__main__": + asyncio.run(run_main_test())