home.vue 145 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277
  1. <template>
  2. <div>
  3. <el-container style="height: 100vh;">
  4. <!-- #333744 -->
  5. <el-aside width="180px" style="user-select: none; border-right: 1px solid #fafafa; background-color: #333744; overflow-x: hidden;">
  6. <p class="soft-name" style="-webkit-app-region: drag; color: #fff;">
  7. <img src="../assets/image/icon.png" class="soft-icon" />
  8. <span style="letter-spacing: 1px;">{{productName}}</span>
  9. </p>
  10. <el-menu :default-openeds="['a']" :default-active="menuIndex" @select="setMenuIndex" active-text-color="#409EFF" background-color="#333744" text-color="#fff" style="margin-top: 10px;">
  11. <el-submenu index="a">
  12. <template slot="title"><img src="../assets/image/m-download.png" class="m-image"/>图片下载</template>
  13. <el-menu-item index="3">
  14. <img src="../assets/image/m-tmall.png" class="m-image"/><span slot="title">天猫</span>
  15. </el-menu-item>
  16. <el-menu-item index="2">
  17. <img src="../assets/image/m-jd.png" class="m-image"/><span slot="title">京东</span>
  18. </el-menu-item>
  19. <el-menu-item index="4">
  20. <img src="../assets/image/m-taobao.png" class="m-image"/><span slot="title">淘宝</span>
  21. </el-menu-item>
  22. <el-menu-item index="1">
  23. <img src="../assets/image/m-alibaba.png" class="m-image"/><span slot="title">阿里巴巴</span>
  24. </el-menu-item>
  25. <el-menu-item index="6">
  26. <img src="../assets/image/m-aliguoji.png" class="m-image"/><span slot="title">阿里国际</span>
  27. </el-menu-item>
  28. <el-menu-item index="9">
  29. <img src="../assets/image/m-pdd.png" class="m-image"/><span slot="title">拼多多</span>
  30. </el-menu-item>
  31. <el-menu-item index="7">
  32. <img src="../assets/image/m-baidu.png" class="m-image"/><span slot="title">百度爱采购</span>
  33. </el-menu-item>
  34. <!-- <el-menu-item index="8">
  35. <img src="../assets/image/m-amazon.png" class="m-image"/><span slot="title">亚马逊</span>
  36. </el-menu-item> -->
  37. <el-menu-item index="5">
  38. <img src="../assets/image/m-hong.png" class="m-image"/><span slot="title">小红书</span>
  39. </el-menu-item>
  40. <el-menu-item index="11">
  41. <img src="../assets/image/m-goofish.png" class="m-image"/><span slot="title">闲鱼</span>
  42. </el-menu-item>
  43. <el-menu-item index="12">
  44. <img src="../assets/image/m-dy.png" class="m-image"/><span slot="title">抖店</span>
  45. </el-menu-item>
  46. <el-menu-item index="10">
  47. <img src="../assets/image/m-chrome.png" class="m-image"/><span slot="title">其他(Beta)</span>
  48. </el-menu-item>
  49. </el-submenu>
  50. <el-submenu index="b">
  51. <template slot="title"><img src="../assets/image/m-edit.png" class="m-image"/>图片处理</template>
  52. <el-menu-item index="2-1">
  53. <img src="../assets/image/m-geshi.png" class="m-image"/><span slot="title">格式转换</span>
  54. </el-menu-item>
  55. <el-menu-item index="2-2">
  56. <img src="../assets/image/m-yasuo.png" class="m-image"/><span slot="title">图片压缩</span>
  57. </el-menu-item>
  58. <el-menu-item index="2-3">
  59. <img src="../assets/image/m-chicun.png" class="m-image"/><span slot="title">修改尺寸</span>
  60. </el-menu-item>
  61. <el-menu-item index="2-5">
  62. <img src="../assets/image/m-shuiyin.png" class="m-image"/><span slot="title">添加水印</span>
  63. </el-menu-item>
  64. </el-submenu>
  65. </el-menu>
  66. </el-aside>
  67. <el-container>
  68. <el-header height="45px" style="background-color: #fafafa; padding: 0 10px;">
  69. <soft-header ref="headerRef" @update-soft="updateSoft()" @export-file="exportFile" @login-url="loginUrl" @clear-cache="clearCache"></soft-header>
  70. </el-header>
  71. <soft-img ref="imgRef" v-show="['2-1', '2-2', '2-3', '2-5'].indexOf(menuIndex) > -1" @open-vip="openVip" @check-authority="checkAuthority"></soft-img>
  72. <el-main v-show="['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'].indexOf(menuIndex) > -1" ref="el-main" style="background-color: #fafafa;">
  73. <template>
  74. <div class="content-top">
  75. <div>
  76. <el-button-group>
  77. <el-button type="primary" size="mini" icon="el-icon-circle-plus-outline"
  78. @click="addVisible = true; add();">添加链接</el-button>
  79. <el-button type="primary" size="mini" icon="el-icon-upload"
  80. @click="pickLink()">导入链接</el-button>
  81. <el-button type="primary" size="mini" icon="el-icon-delete"
  82. @click="clearList()">清空链接</el-button>
  83. <el-button type="danger" size="mini" icon="el-icon-video-pause" :disabled="pauseFlag"
  84. @click="pause()">任务中止</el-button>
  85. <!-- <el-button type="danger" size="mini" icon="el-icon-video-pause"
  86. @click="del()">批量删除</el-button> -->
  87. </el-button-group>
  88. <el-link type="info" style="margin-left: 5px; vertical-align:baseline; font-size: 12px;" @click="downloadExample()">导入模板<i class="el-icon-download"></i></el-link>
  89. </div>
  90. <el-row type="flex" style="align-items: center;">
  91. <div class="set-item">
  92. <span class="set-title">保存目录:</span>
  93. <el-input :title="downloadDir" ref="upload-input" size="mini" @focus="pickPath" placeholder="请选择输出目录" v-model="downloadDir" readonly style="width:200px;" prefix-icon="el-icon-folder"></el-input>
  94. <el-popover placement="bottom" popper-class="popper-open" trigger="hover" content="打开保存目录">
  95. <i class="el-icon-folder-opened" slot="reference" style="padding-left: 5px; cursor: pointer; font-size: 22px; vertical-align: middle;" @click="openFolder()"></i>
  96. </el-popover>
  97. </div>
  98. <el-button type="danger" @click="exportFile()" :loading="loading">开始下载</el-button>
  99. </el-row>
  100. </div>
  101. <div style="padding: 20px 20px 0 20px; height: calc(100% - 62px);">
  102. <el-row type="flex" justify="space-between">
  103. <div>
  104. <h3 style="display: inline-block;">
  105. <span v-if="menuIndex == '1'">阿里巴巴 - </span>
  106. <span v-if="menuIndex == '2'">京东 - </span>
  107. <span v-if="menuIndex == '3'">天猫 - </span>
  108. <span v-if="menuIndex == '4'">淘宝 - </span>
  109. <span v-if="menuIndex == '5'">小红书 - </span>
  110. <span v-if="menuIndex == '6'">阿里国际 - </span>
  111. <span v-if="menuIndex == '7'">百度爱采购 - </span>
  112. <span v-if="menuIndex == '8'">亚马逊 - </span>
  113. <span v-if="menuIndex == '9'">拼多多 - </span>
  114. <span v-if="menuIndex == '10'">网页 - </span>
  115. <span v-if="menuIndex == '11'">闲鱼 - </span>
  116. <span v-if="menuIndex == '12'">抖店 - </span>
  117. 图片下载
  118. </h3>
  119. <el-link v-if="menuIndex == '5'" :underline="false" type="danger" style="text-align: center; font-size: 12px;">
  120. 仅支持win10及以上系统,浏览器请选择最新版本
  121. </el-link>
  122. <el-link v-show="menuIndex == '9'" :underline="false" type="danger" style="text-align: center; font-size: 12px;">
  123. <span id="ccc">网址:https://mobile.yangkeduo.com</span>
  124. </el-link>
  125. <el-link v-if="menuIndex == '10'" :underline="false" type="danger" style="text-align: center; font-size: 12px;">
  126. 非会员功能,仅提供测试试用
  127. </el-link>
  128. </div>
  129. </el-row>
  130. <div style="padding: 15px 0 20px;">
  131. <el-row type="flex" justify="space-between">
  132. <div v-if="menuIndex == '5'" style="padding-top: 10px;">
  133. <label>下载类型:</label>
  134. <el-checkbox-group :min="1" v-model="settingArr" style="display: inline-block;" @input="settingGroup">
  135. <el-checkbox label="mainImg">文章图</el-checkbox>
  136. <el-checkbox label="video">视频</el-checkbox>
  137. </el-checkbox-group>
  138. <!-- <el-checkbox :value="true" style="opacity: 0.6; cursor: not-allowed;">文章图/视频</el-checkbox> -->
  139. <el-popover placement="bottom" popper-class="popper-open" trigger="hover" content="实况(Live)图下载的格式是mp4视频">
  140. <i class="el-icon-info" slot="reference" style="margin-left: 10px; color: #F56C6C;"></i>
  141. </el-popover>
  142. </div>
  143. <div v-if="menuIndex == '10'" style="padding-top: 10px;">
  144. <label>下载类型:</label>
  145. <el-checkbox :value="true" style="opacity: 0.6; cursor: not-allowed;">图片</el-checkbox>
  146. </div>
  147. <div v-if="['1', '2', '3', '4', '6', '7', '8', '9', '11', '12'].indexOf(menuIndex) > -1" style="padding-top: 10px;">
  148. <label>下载类型:</label>
  149. <el-checkbox-group :min="1" v-model="settingArr" style="display: inline-block;" @input="settingGroup">
  150. <el-checkbox label="mainImg">主图</el-checkbox>
  151. <el-checkbox label="detailImg" v-if="menuIndex != '11'">详情图</el-checkbox>
  152. <el-checkbox label="skuImg" v-if="menuIndex != '7' && menuIndex != '11' && menuIndex != '12'">SKU图</el-checkbox>
  153. <el-checkbox label="commentImg" v-if="menuIndex == '3' || menuIndex == '4'">评论图</el-checkbox>
  154. <el-checkbox label="video">主图视频</el-checkbox>
  155. </el-checkbox-group>
  156. <el-popover placement="bottom" popper-class="popper-open" trigger="hover"
  157. :content="menuIndex == '9' ? '视频下载的是商品视频,非商品讲解视频' : '下载类型至少选一个,评论图默认只下载商品首页展示的评论内容'">
  158. <i class="el-icon-info" slot="reference" style="margin-left: 10px; color: #F56C6C;"></i>
  159. </el-popover>
  160. </div>
  161. <!-- 阿里巴巴账号 -->
  162. <template v-if="menuIndex == '1'">
  163. <div>
  164. <el-tag type="info" size="mini" v-if="alibabaStatus == 1">未检测</el-tag>
  165. <el-tag type="success" size="mini" v-if="alibabaStatus == 2">阿里巴巴账号已登录</el-tag>
  166. <el-link type="danger" style="text-decoration: underline;" v-if="alibabaStatus == 3" :underline="false" @click="loginUrl('https://www.1688.com')">未登录,点击登录阿里巴巴账号</el-link>
  167. <el-button size="mini" type="warning" :loading="checkLoading" style="margin-left: 10px;" :disabled='alibabaStatus == 2' @click="checkAlibabaLogin">检测登录状态</el-button>
  168. </div>
  169. </template>
  170. <!-- 天猫/淘宝 -->
  171. <template v-if="menuIndex == '3' || menuIndex == '4'">
  172. <div>
  173. <el-tag type="info" size="mini" v-if="tbStatus == 1">未检测</el-tag>
  174. <el-tag type="success" size="mini" v-if="tbStatus == 2">{{menuIndex == '3' ? '天猫' : '淘宝'}}账号已登录</el-tag>
  175. <el-link type="danger" style="text-decoration: underline;" v-if="tbStatus == 3" :underline="false" @click="loginUrl('https://login.taobao.com')">未登录,点击登录<span>{{menuIndex == '3' ? '天猫' : '淘宝'}}</span>账号</el-link>
  176. <el-button size="mini" type="warning" :loading="checkLoading" style="margin-left: 10px;" :disabled='tbStatus == 2' @click="checkLogin">检测登录状态</el-button>
  177. </div>
  178. </template>
  179. <!-- 京东账号 -->
  180. <template v-if="menuIndex == '2'">
  181. <div>
  182. <el-tag type="info" size="mini" v-if="jdStatus == 1">未检测</el-tag>
  183. <el-tag type="success" size="mini" v-if="jdStatus == 2">京东账号已登录</el-tag>
  184. <el-link type="danger" style="text-decoration: underline;" v-if="jdStatus == 3" :underline="false" @click="loginUrl('https://passport.jd.com/new/login.aspx')">未登录,点击登录京东账号</el-link>
  185. <el-button size="mini" type="warning" :loading="checkLoading" style="margin-left: 10px;" :disabled='jdStatus == 2' @click="checkJdLogin">检测登录状态</el-button>
  186. </div>
  187. </template>
  188. <!-- 小红书 -->
  189. <template v-if="menuIndex == '5'">
  190. <div>
  191. <el-tag type="info" size="mini" v-if="redStatus == 1">未检测</el-tag>
  192. <el-tag type="success" size="mini" v-if="redStatus == 2">小红书账号已登录</el-tag>
  193. <el-link type="danger" style="text-decoration: underline;" v-if="redStatus == 3" :underline="false" @click="loginUrl('https://www.xiaohongshu.com')">未登录,点击登录小红书账号</el-link>
  194. <el-button size="mini" type="warning" :loading="checkLoading" style="margin-left: 10px;" :disabled='redStatus == 2' @click="checkRedLogin">检测登录状态</el-button>
  195. </div>
  196. </template>
  197. <!-- 拼多多 -->
  198. <template v-if="menuIndex == '9'">
  199. <div>
  200. <el-tag type="info" size="mini" v-if="pddStatus == 1">未检测</el-tag>
  201. <el-tag type="success" size="mini" v-if="pddStatus == 2">拼多多账号已登录</el-tag>
  202. <el-link type="danger" style="text-decoration: underline;" v-if="pddStatus == 3" :underline="false" @click="loginUrl('https://mobile.yangkeduo.com/login.html')">未登录,点击登录拼多多账号</el-link>
  203. <el-button size="mini" type="warning" :loading="checkLoading" style="margin-left: 10px;" :disabled='pddStatus == 2' @click="checkPddLogin">检测登录状态</el-button>
  204. </div>
  205. </template>
  206. </el-row>
  207. </div>
  208. <div class="table-scroll">
  209. <!-- 1、 -->
  210. <vxe-table ref="xTable" show-overflow class="img-table" max-height="100%" empty-text="没有更多数据了!" :loading="tabLoading" :row-config="{isHover: true}"
  211. :loading-config="{icon: 'vxe-icon-indicator roll', text: '列表加载中...'}" :data="this[listStr+'List']" :scroll-y="{enabled: true}">
  212. <!-- <vxe-column type="checkbox" width="40"></vxe-column> -->
  213. <vxe-column type="seq" width="60"></vxe-column>
  214. <vxe-column field="title" title="目录名称" width="180">
  215. <template #default="{ row, rowIndex }">
  216. <span v-if="row.title">{{row.title}}</span>
  217. <el-tag size="mini" v-else>默认使用网页标题</el-tag>
  218. </template>
  219. </vxe-column>
  220. <vxe-column field="url" title="网页链接"></vxe-column>
  221. <vxe-column field="status" title="下载状态" width="200">
  222. <template #default="{ row }">
  223. <template v-if="row.status == '1'">
  224. <i class="el-icon-info" style="font-size: 16px; color: #999;"></i>
  225. <span>待操作</span>
  226. </template>
  227. <template v-if="row.status == '2'">
  228. <i class="el-icon-loading" style="font-size: 16px; color: #999;"></i>
  229. <span>任务处理中...</span>
  230. </template>
  231. <template v-if="row.status == '3'">
  232. <i class="el-icon-loading" style="font-size: 16px; color: #999;"></i>
  233. <span>图片下载中..<span v-if="row.num > 0">第{{row.num}}张</span></span>
  234. </template>
  235. <template v-if="row.status == '4'">
  236. <i class="el-icon-success" style="font-size: 16px; color: #19be6b;"></i>
  237. <span>下载完成,共{{row.num}}张</span>
  238. </template>
  239. <template v-if="row.status == '5'">
  240. <i class="el-icon-error" style="font-size: 16px; color: #ed4014;"></i>
  241. <span>网络异常,请重试!</span>
  242. </template>
  243. <template v-if="row.status == '6'">
  244. <i class="el-icon-error" style="font-size: 16px; color: #ed4014;"></i>
  245. <span>验证码拦截,请手动验证!</span>
  246. </template>
  247. <template v-if="row.status == '7'">
  248. <i class="el-icon-error" style="font-size: 16px; color: #ed4014;"></i>
  249. <span>频繁访问受限,清除缓存重试</span>
  250. </template>
  251. </template>
  252. </vxe-column>
  253. <vxe-column title="操作" width="80">
  254. <template #default="{ row, rowIndex }">
  255. <i class="el-icon-delete cur-pointer" style="font-size: 20px;" @click="delFile(rowIndex)"></i>
  256. </template>
  257. </vxe-column>
  258. </vxe-table>
  259. </div>
  260. </div>
  261. </template>
  262. <el-dialog title="添加链接" :visible.sync="addVisible" width="500px" :close-on-click-modal="false" :close-on-press-escape="false" :show-close="false">
  263. <div>
  264. <el-form label-position="right" label-width="80px" :rules="rules" :model="formData" ref="formData">
  265. <el-form-item label="目录名称" prop="title">
  266. <el-input id="aaa" v-model="formData.title" placeholder="为空则默认使用网页标题前50个字符"></el-input>
  267. </el-form-item>
  268. <el-form-item label="网页链接" prop="url">
  269. <el-input id="bbb" type="textarea" :rows="10" :placeholder="'请输入网址链接(例:' + exampleUrl[menuIndex-1] + ')'" v-model="formData.url"></el-input>
  270. </el-form-item>
  271. </el-form>
  272. </div>
  273. <span slot="footer" class="dialog-footer">
  274. <el-button @click="addVisible = false; $refs['formData'].resetFields();">取 消</el-button>
  275. <el-button type="primary" @click="onSubmit">确 定</el-button>
  276. </span>
  277. </el-dialog>
  278. <el-dialog title="提示" :visible.sync="loginVisible" width="400px" :close-on-click-modal="false" :close-on-press-escape="false">
  279. <div style="text-align: center; color: #999; font-size: 14px;">
  280. <template v-if="menuIndex == '1'">
  281. <p>阿里巴巴渠道建议登录后下载</p>
  282. <p class="visible-tips-style">目前检测还未登录阿里巴巴账号,未登录可能会导致图片下载不全</p>
  283. </template>
  284. <template v-else-if="menuIndex == '2'">
  285. <p>京东渠道需要登录后才能下载</p>
  286. <p class="visible-tips-style">目前检测还未登录京东账号,需立即登录</p>
  287. </template>
  288. <template v-else-if="menuIndex == '5'">
  289. <p>小红书渠道需要登录后才能下载</p>
  290. <p class="visible-tips-style">目前检测还未登录小红书账号,需立即登录</p>
  291. </template>
  292. <template v-else-if="menuIndex == '9'">
  293. <p>拼多多渠道需要登录后才能下载</p>
  294. <p class="visible-tips-style">目前检测还未登录拼多多账号,需立即登录</p>
  295. </template>
  296. <template v-else>
  297. <p>天猫/淘宝渠道需要登录后才能下载</p>
  298. <p class="visible-tips-style">目前检测还未登录天猫/淘宝账号,需立即登录</p>
  299. </template>
  300. </div>
  301. <div slot="footer" class="dialog-footer-center">
  302. <el-button v-if="menuIndex == '2'" @click="loginVisible = false; loginUrl('https://passport.jd.com/new/login.aspx')">点击登录京东账号</el-button>
  303. <template v-else-if="menuIndex == '1'">
  304. <el-button @click="loginVisible = false; loginUrl('https://www.1688.com')">点击登录阿里巴巴账号</el-button>
  305. <el-button type="primary" @click="loginVisible = false; skipLogin = true; exportFile();">继续下载</el-button>
  306. </template>
  307. <el-button v-else-if="menuIndex == '5'" @click="loginVisible = false; loginUrl('https://www.xiaohongshu.com')">点击登录小红书账号</el-button>
  308. <el-button v-else-if="menuIndex == '9'" @click="loginVisible = false; loginUrl('https://mobile.yangkeduo.com/login.html')">点击登录拼多多账号</el-button>
  309. <el-button v-else @click="loginVisible = false; loginUrl('https://login.taobao.com')">点击登录天猫/淘宝账号</el-button>
  310. </div>
  311. </el-dialog>
  312. <!-- 非会员转换提示框 -->
  313. <el-dialog title="非会员提示" :visible.sync="tipsModal" width="400px">
  314. <div class="member-model">
  315. <div class="tips-flex">
  316. <i class="el-icon-s-opportunity"></i>
  317. <p class="m-title">{{tipsDesc}}</p>
  318. </div>
  319. <div class="member-btn">
  320. <el-button size="small" round type="primary" @click="openVip()">开通会员</el-button>
  321. </div>
  322. </div>
  323. </el-dialog>
  324. </el-main>
  325. <el-footer height="48px">
  326. <!-- 更新 -->
  327. <soft-update ref="updateRef" :showDowload="dowloadModel" :dowloadFinish="finishModel"></soft-update>
  328. </el-footer>
  329. </el-container>
  330. </el-container>
  331. </div>
  332. </template>
  333. <script>
  334. import os from 'os'
  335. import fs from 'fs'
  336. import request from 'request'
  337. import path from 'path';
  338. import xlsx from 'node-xlsx';
  339. import softUpdate from './update.vue';
  340. import softHeader from './header.vue';
  341. import softImg from './img.vue';
  342. import electronApi from '@/utils/electronApi';
  343. import pjson from '/package.json'
  344. // import puppeteer from 'puppeteer'
  345. import puppeteer from 'puppeteer-extra'
  346. const StealthPlugin = require('puppeteer-extra-plugin-stealth');
  347. const listNameArr = ['alibaba','jd','tmall','tb','red','aliguoji','acaigou','amazon', 'pdd' ,'common','goofish','dy'];
  348. // const headless = true;
  349. // const waitUntil = 'networkidle2';
  350. const { ipcRenderer } = require('electron');
  351. //const chromePath = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
  352. let separator = '';
  353. if (os.platform == 'linux') {
  354. separator = '/'
  355. } else {
  356. separator = '\\'
  357. }
  358. // let chromePath = process.cwd() + '\\resources\\app\\node_modules\\puppeteer\\.local-chromium\\win64-1045629\\chrome-win\\chrome.exe';
  359. // if (process.env.NODE_ENV == 'development') {
  360. // chromePath = process.cwd() + '\\node_modules\\puppeteer\\.local-chromium\\win64-1045629\\chrome-win\\chrome.exe';
  361. // }
  362. export default {
  363. name: 'landing-page',
  364. components: {
  365. softUpdate,
  366. softHeader,
  367. softImg
  368. },
  369. data() {
  370. return {
  371. tipsModal: false,
  372. tipsDesc: "非VIP用户不能下载视频,如需完整功能请开通VIP会员。",
  373. settingArr: ['mainImg'],
  374. loginVisible: false,
  375. addVisible: false,
  376. formData: {
  377. title: '',
  378. url: ''
  379. },
  380. rules:{ //
  381. title: [
  382. { min: 0, max: 50, message: '不能超过 50 个字符', trigger: 'blur' },
  383. { pattern: /^[^\\/:*?"<>|]*$/, message: '标题中不能包含 \\ / : * ? " < > |', trigger: 'blur' }
  384. ],
  385. url: [
  386. { required: true, message: '请输入网页链接', trigger: 'blur' },
  387. { pattern: /^(http|https):\/\/.+$/, message: '请输入正确的网址链接(http://或https://开头),结尾不能有换行符', trigger: 'blur' }
  388. ],
  389. },
  390. tabLoading: false,
  391. alibabaList: [],
  392. aliguojiList: [],
  393. amazonList: [],
  394. acaigouList: [],
  395. jdList: [],
  396. tbList: [],
  397. tmallList: [],
  398. redList: [],
  399. pddList: [],
  400. goofishList: [],
  401. dyList: [],
  402. commonList: [],
  403. productName: pjson.softInfo.softName,
  404. imgUrl: this.$api.imgUrl,
  405. imgSrc: '',
  406. menuIndex: '3',
  407. settingData: {
  408. detailImg: true,
  409. skuImg: true,
  410. commentImg: false,
  411. video: false,
  412. },
  413. exampleUrl: ['https://www.1688.com', 'https://www.jd.com', 'https://www.tmall.com', 'https://www.taobao.com', 'https://www.xiaohongshu.com',
  414. 'https://www.alibaba.com', 'https://b2b.baidu.com', 'https://www.amazon.com', 'https://mobile.yangkeduo.com/goods.html', 'https://www.example.com',
  415. 'https://www.goofish.com', 'https://v.douyin.com/xxxxxx/'],
  416. fileList: [],
  417. downloadDir: os.userInfo().homedir + separator + "Downloads",
  418. dowloadModel: false,
  419. finishModel: false,
  420. loading: false,
  421. checkLoading: false, //点击检测登录状态
  422. tbStatus: 1, // 1、未检测 2、已经登录 3、未登录
  423. jdStatus: 1, // 1、未检测 2、已经登录 3、未登录
  424. redStatus: 1, //同上
  425. alibabaStatus: 1, //同上上
  426. aliguojiStatus: 1, //同上上上
  427. pddStatus: 1,
  428. execLimit: 1,
  429. execNum: 3, // 限制5张
  430. /** 浏览器名称 **/
  431. alibabaBrowser: null,
  432. aliguojiBrowser: null,
  433. amazonBrowser: null,
  434. acaigouBrowser: null,
  435. tbBrowser: null,
  436. jdBrowser: null,
  437. commonBrowser: null,
  438. redBrowser: null,
  439. pddBrowser: null,
  440. goofishBrowser: null,
  441. dyBrowser: null,
  442. loginBrowser: null, // 登录用的浏览器实例
  443. skipLogin: false,
  444. pauseFlag: true, //暂停中止标志
  445. rightClick: false, // 右击事件绑定
  446. };
  447. },
  448. computed: {
  449. listStr: function(){
  450. let index = Number(this.menuIndex) - 1;
  451. return listNameArr[index];
  452. }
  453. },
  454. async mounted() {
  455. this.$refs.updateRef.updateSoft(true);
  456. let homedir = os.userInfo().homedir;
  457. if (fs.existsSync(homedir + separator + "Desktop")) {
  458. this.downloadDir = homedir + separator + "Desktop"
  459. } else {
  460. this.downloadDir = homedir + separator + "Downloads"
  461. }
  462. let dir = this.$utils.getStorage('downloadDir');
  463. if(dir){
  464. this.downloadDir = dir;
  465. }
  466. if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture')) {
  467. fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture');
  468. }
  469. if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture-jd')) {
  470. fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture-jd');
  471. }
  472. if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture-local')) {
  473. fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture-local');
  474. }
  475. let path = os.tmpdir() + separator + 'chrome-data-capture';
  476. let path2 = os.tmpdir() + separator + 'chrome-data-capture-jd';
  477. //this.deleteAll(path, false);
  478. //this.deleteAll(path2, false);
  479. // 打开浏览器
  480. const {
  481. shell
  482. } = require('electron');
  483. const links = document.querySelectorAll('a[href]');
  484. links.forEach(link => {
  485. link.addEventListener('click', e => {
  486. const url = link.getAttribute('href');
  487. e.preventDefault();
  488. shell.openExternal(url);
  489. });
  490. });
  491. // 判断系统版本 低于10使用兼容模式
  492. if(os.release() && os.release().indexOf('.') > -1){
  493. let systemVersion = Number(os.release().split('.')[0]);
  494. if(systemVersion < 10){ // 低于win10,软件打开时候浏览器设置为兼容版
  495. this.$utils.setStorage('versionType', 1);
  496. }else{
  497. this.$utils.setStorage('versionType', 2);
  498. }
  499. }
  500. // 初始化开发者设置
  501. // this.$utils.setStorage('headless', 1);
  502. // this.$utils.setStorage('waitUntil', 'networkidle2');
  503. document.getElementById('ccc').addEventListener('contextmenu', e => {
  504. e.preventDefault();
  505. // 发送事件到主进程,附带元素类型信息
  506. ipcRenderer.send('show-context-menu', 'span');
  507. });
  508. },
  509. methods: {
  510. add(){
  511. if(!this.rightClick){
  512. setTimeout(() => {
  513. document.getElementById('aaa').addEventListener('contextmenu', e => {
  514. e.preventDefault();
  515. // 发送事件到主进程,附带元素类型信息
  516. ipcRenderer.send('show-context-menu', 'input');
  517. });
  518. document.getElementById('bbb').addEventListener('contextmenu', e => {
  519. e.preventDefault();
  520. // 发送事件到主进程,附带元素类型信息
  521. ipcRenderer.send('show-context-menu', 'input');
  522. });
  523. }, 800)
  524. this.rightClick = true;
  525. }
  526. },
  527. // 实时获取浏览器路径
  528. initPath(){
  529. let chromeType = this.$utils.getStorage('chromeType');
  530. let chromePath = puppeteer.executablePath().replace('win32-1', 'win64-1');
  531. if(chromeType == 1){ // 电脑自带浏览器
  532. chromePath = this.$utils.getStorage('chromePath');
  533. }else{
  534. chromePath = puppeteer.executablePath().replace('win32-1', 'win64-1');
  535. let versionType = this.$utils.getStorage('versionType');
  536. if(versionType && versionType == 1){
  537. chromePath = chromePath.replace('chrome-win', 'chrome7');
  538. }
  539. }
  540. // let chromePath = this.$utils.getStorage('chromePath');
  541. return chromePath;
  542. },
  543. // 实时获取浏览器数据缓存
  544. initDataDir(tag){
  545. let chromeType = this.$utils.getStorage('chromeType');
  546. let userDataDir = os.tmpdir() + separator + 'chrome-data-capture';
  547. if(chromeType == 1){ // 电脑自带浏览器
  548. userDataDir = os.tmpdir() + separator + 'chrome-data-capture-local';
  549. }else{
  550. userDataDir = os.tmpdir() + separator + 'chrome-data-capture';
  551. if(tag == 'jd'){
  552. userDataDir = os.tmpdir() + separator + 'chrome-data-capture-jd';
  553. }
  554. }
  555. return userDataDir;
  556. },
  557. // 实时获取页面滚动加载时间
  558. initMs(){
  559. let pageMs = this.$utils.getStorage('pageMs');
  560. if(pageMs){
  561. return Number(pageMs);
  562. }else{
  563. return 600;
  564. }
  565. },
  566. // 任务下载间隔时间
  567. initGap(){
  568. let gap = this.$utils.getStorage('gap');
  569. let gapRandom = this.$utils.getStorage('gapRandom');
  570. if(gap){
  571. let g = Number(gap);
  572. let r = 0;
  573. if(gapRandom){
  574. r = Number(gapRandom) + 1;
  575. }
  576. let n = Math.floor(Math.random() * r) + g;
  577. return n;
  578. }else{
  579. return 1;
  580. }
  581. },
  582. // 实时获取淘宝的开发者设置
  583. initDevelop(){
  584. let develop = {
  585. headless: true,
  586. waitUntil: 'networkidle2'
  587. };
  588. let n1 = this.$utils.getStorage('exeType');
  589. let n2 = this.$utils.getStorage('waitUntil'); //淘宝的网络连接模式
  590. let n3 = this.$utils.getStorage('waitUntil2');
  591. if(n1){
  592. if(n1 == 1){
  593. develop.headless = true;
  594. }else if(n1 == 2){
  595. develop.headless = false;
  596. }
  597. }
  598. if(this.menuIndex == '3' || this.menuIndex == '4'){ // 非淘宝网络连接设置
  599. if(n2){
  600. develop.waitUntil = n2;
  601. }else{
  602. develop.waitUntil = 'domcontentloaded';
  603. }
  604. }
  605. if(this.menuIndex != '3' && this.menuIndex != '4'){ // 非淘宝网络连接设置
  606. if(n3){
  607. develop.waitUntil = n3;
  608. }
  609. }
  610. return develop;
  611. },
  612. // 删除文件夹内容
  613. deleteAll(folderPath, flag) {
  614. if (fs.existsSync(folderPath)) {
  615. fs.readdirSync(folderPath).forEach((file, index) => {
  616. var curPath = path.join(folderPath, file);
  617. if (fs.lstatSync(curPath).isDirectory()) {
  618. this.deleteAll(curPath, true);
  619. } else {
  620. fs.unlinkSync(curPath);
  621. }
  622. });
  623. if(flag){
  624. fs.rmdirSync(folderPath);
  625. }
  626. }
  627. },
  628. checkAuthority(){
  629. let authority = this.$refs.headerRef.authority;
  630. this.$refs.imgRef.authority = authority;
  631. },
  632. setMenuIndex(index){
  633. this.menuIndex = index;
  634. if(index.indexOf('2-') > -1){
  635. let num = Number(index.split('-')[1]);
  636. this.$refs.imgRef.setMenuIndex(num);
  637. }
  638. },
  639. // 选择目录
  640. pickPath() {
  641. this.$refs['upload-input'].blur();
  642. electronApi.call('pickDir', []).then((path) => {
  643. if (path) {
  644. this.downloadDir = path;
  645. this.$utils.setStorage('downloadDir', path);
  646. }
  647. });
  648. },
  649. // 打开自定义下载目录
  650. openFolder() {
  651. let path = this.downloadDir;
  652. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName)) {
  653. path = this.downloadDir + separator + pjson.softInfo.softName;
  654. } else {
  655. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName);
  656. path = this.downloadDir + separator + pjson.softInfo.softName;
  657. }
  658. electronApi.call('showItemInfolder', [path + '\\tty.tty'])
  659. },
  660. openVip() {
  661. this.$refs.headerRef.openVip();
  662. },
  663. updateSoft() {
  664. this.$refs.updateRef.updateSoft();
  665. },
  666. // 删除文件
  667. delFile(rowIndex){
  668. let index = Number(this.menuIndex) - 1;
  669. let type = listNameArr[index];
  670. this.$confirm('确认删除此行数据吗?', '提示', {
  671. confirmButtonText: '确定',
  672. cancelButtonText: '取消',
  673. type: 'warning'
  674. }).then(() => {
  675. this[type+'List'].splice(rowIndex, 1);
  676. if(this[type+'List'].length == 0) {
  677. this.clearList();
  678. }
  679. }).catch(() => {
  680. });
  681. },
  682. // 清除列表
  683. clearList() {
  684. let index = Number(this.menuIndex) - 1;
  685. this[listNameArr[index]+'List'] = [];
  686. },
  687. // 提交表单
  688. onSubmit(){
  689. this.$refs['formData'].validate((valid) => {
  690. if (valid) {
  691. let info = {
  692. url: this.formData.url,
  693. title: this.formData.title,
  694. status: '1',
  695. num: 0,
  696. newPath: ''
  697. }
  698. let index = Number(this.menuIndex) - 1;
  699. this[listNameArr[index]+'List'].push(info);
  700. this.$refs['formData'].resetFields();
  701. this.addVisible = false;
  702. } else {
  703. return false;
  704. }
  705. });
  706. },
  707. async pickLink() { // 导入链接
  708. const spinLoad = this.$loading();
  709. await electronApi.call('pickFile', ['xlsx,xls', true]).then(async (path) => {
  710. spinLoad.close();
  711. if(path.length > 0){
  712. this.$notify({
  713. title: '提示',
  714. message: '导入成功',
  715. type: 'success'
  716. });
  717. let workSheetsFromBuffer = xlsx.parse(fs.readFileSync(path[0]));
  718. if(workSheetsFromBuffer && workSheetsFromBuffer.length > 0){
  719. let errMsg = "";
  720. workSheetsFromBuffer[0].data.map((item, index) => {
  721. if(item.length > 0){
  722. let ititle = '';
  723. if(item[0]){
  724. ititle = item[0].toString().trim();
  725. }
  726. if(item[0] == '目录名称' && item[1] == '网页链接'){
  727. return false;
  728. }
  729. if(this.containsAnyChar(ititle.toString(), ['\\', '/', ':', '*', '?', '"', '<', '>', '|', '.'])){ //判断是否含有特殊字符
  730. errMsg += "第" + (index+1) + '行-名称不能包以下字符 \\ / : * ? " < > | .';
  731. ititle = ititle.replace(/[\\|/|:|*|?|.|"|<|>||]/g, "");
  732. }
  733. if(item[1] == undefined){
  734. errMsg += "第" + (index+1) + "行格式有误</br>";
  735. item[1] = '';
  736. }else if(!/^(http|https):\/\/.+$/.exec(item[1])){
  737. errMsg += "第" + (index+1) + "行网址格式有误</br>";
  738. }else{
  739. let info = {
  740. url: item[1],
  741. title: ititle,
  742. status: '1',
  743. num: 0,
  744. newPath: ''
  745. }
  746. let key = Number(this.menuIndex) - 1;
  747. this[listNameArr[key]+'List'].push(info);
  748. }
  749. }
  750. });
  751. if(errMsg){
  752. this.$notify({
  753. title: '请检查文件以下问题',
  754. dangerouslyUseHTMLString: true,
  755. message: errMsg,
  756. type: 'warning'
  757. });
  758. }
  759. }else{
  760. this.$notify({
  761. title: '提示',
  762. message: '格式有误,请重新导入',
  763. type: 'warning'
  764. });
  765. }
  766. }
  767. });
  768. },
  769. settingGroup(name){
  770. let authority = this.$refs.headerRef.authority.isAuthority;
  771. let index = name.indexOf('video');
  772. if(index > -1 && !authority){ // 非会员选中下载视频选项-提示
  773. this.tipsModal = true;
  774. name.splice(index, 1);
  775. }
  776. },
  777. // 清除缓存的后续操作
  778. async clearCache(){
  779. this.jdStatus = 3;
  780. this.tbStatus = 3;
  781. this.redStatus = 3;
  782. this.alibabaStatus = 3;
  783. this.aliguojiStatus = 3;
  784. this.pddStatus = 3;
  785. if(this.loginBrowser){
  786. await this.loginBrowser.close();
  787. this.loginBrowser = null;
  788. }
  789. for(let i = 0; i < listNameArr.length; i++){
  790. if(listNameArr[i]){
  791. if(this[listNameArr[i]+'Browser']){
  792. await this[listNameArr[i]+'Browser'].close();
  793. this[listNameArr[i]+'Browser'] = null;
  794. }
  795. }
  796. }
  797. },
  798. // 去登录
  799. loginUrl(url){
  800. (async () => {
  801. if(this.loginBrowser){
  802. await this.loginBrowser.close();
  803. this.loginBrowser = null;
  804. }
  805. try{
  806. if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture')) {
  807. fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture');
  808. }
  809. if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture-jd')) {
  810. fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture-jd');
  811. }
  812. if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture-local')) {
  813. fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture-local');
  814. }
  815. let userDataDir = this.initDataDir();
  816. if(url.indexOf('.jd.com/') > -1){
  817. userDataDir = this.initDataDir('jd');
  818. }
  819. puppeteer.use(StealthPlugin());
  820. this.loginBrowser = await puppeteer.launch({
  821. headless: false,
  822. executablePath: this.initPath(),
  823. args: ['--window-size=1280,800'],
  824. userDataDir: userDataDir,
  825. });
  826. const page = await this.loginBrowser.newPage();
  827. await page.setViewport({ width: 1280, height: 800 });
  828. await page.evaluateOnNewDocument(() => {
  829. const newProto = navigator.__proto__;
  830. delete newProto.webdriver;
  831. navigator.__proto__ = newProto;
  832. window.navigator.chrome = {
  833. runtime: {}
  834. };
  835. });
  836. await page.goto(url, {waitUntil : 'networkidle2'});
  837. }catch(e){
  838. this.showError(e);
  839. }
  840. })();
  841. },
  842. del(){
  843. let info = this.$refs.xTable.getCheckboxRecords();
  844. console.log(info);
  845. },
  846. //任务暂停
  847. async pause(){
  848. this.$confirm('是否中止下载任务?', '提示', {
  849. confirmButtonText: '确定',
  850. cancelButtonText: '取消',
  851. type: 'warning'
  852. }).then(async() => {
  853. if(this.loginBrowser){
  854. await this.loginBrowser.close();
  855. this.loginBrowser = null;
  856. }
  857. this.pauseFlag = true;
  858. for(let i = 0; i < listNameArr.length; i++){
  859. if(listNameArr[i]){
  860. if(this[listNameArr[i]+'Browser']){
  861. await this[listNameArr[i]+'Browser'].close();
  862. this[listNameArr[i]+'Browser'] = null;
  863. }
  864. }
  865. }
  866. let index = Number(this.menuIndex) - 1;
  867. this[listNameArr[index]+'List'].map(item => {
  868. if(item.status != '4'){
  869. item.status = '1';
  870. }
  871. });
  872. }).catch(() => {
  873. });
  874. },
  875. // 开始下载
  876. async exportFile(flag) {
  877. this.pauseFlag = false;
  878. if(this.loginBrowser){
  879. await this.loginBrowser.close();
  880. this.loginBrowser = null;
  881. }
  882. let authority = this.$refs.headerRef.authority.isAuthority;
  883. if (!fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName)) {
  884. try{
  885. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName);
  886. }catch(e){
  887. this.$notify.error({
  888. title: '保存目录不存在!- 1',
  889. message: '请重新设置保存目录路径'
  890. });
  891. return false;
  892. }
  893. }
  894. let index = Number(this.menuIndex) - 1;
  895. let fileList = this[listNameArr[index]+'List'];
  896. if(fileList.length > 0){
  897. if (!authority && !flag) { // 非会员点击转换弹出提示框
  898. this.$refs.headerRef.memberModel = true;
  899. this.$refs.headerRef.isClick = true;
  900. return false;
  901. } else {
  902. this.$refs.headerRef.memberModel = false;
  903. this.loading = true;
  904. setTimeout(() => {
  905. this.loading = false;
  906. }, 60000);
  907. }
  908. if(this.menuIndex == '1' && !this.skipLogin){ // 阿里巴巴
  909. if(this.alibabaStatus == 1 || this.alibabaStatus == 3){ // 未检测登录状态/或提示未登录状态,开始检测
  910. await this.checkAlibabaLogin().then((data) => {
  911. if(data != 2){ // 未登录
  912. this.alibabaStatus = 3;
  913. this.loginVisible = true;
  914. }
  915. }).catch(err => {
  916. this.alibabaStatus = 3;
  917. });
  918. if(this.alibabaStatus == 3){
  919. this.loading = false;
  920. return false;
  921. }
  922. }
  923. }
  924. if(this.menuIndex == '2'){ // 京东
  925. if(this.jdStatus == 1 || this.jdStatus == 3){ // 未检测登录状态/或提示未登录状态,开始检测
  926. await this.checkJdLogin().then((data) => {
  927. if(data != 2){ // 未登录
  928. this.jdStatus = 3;
  929. this.loginVisible = true;
  930. }
  931. }).catch(err => {
  932. this.jdStatus = 3;
  933. });
  934. if(this.jdStatus == 3){
  935. this.loading = false;
  936. return false;
  937. }
  938. }
  939. }
  940. if(this.menuIndex == '3' || this.menuIndex == '4'){ // 天猫/淘宝
  941. if(this.tbStatus == 1 || this.tbStatus == 3){ // 未检测登录状态/或提示未登录状态,开始检测
  942. await this.checkLogin().then((data) => {
  943. if(data != 2){ // 未登录
  944. this.tbStatus = 3;
  945. this.loginVisible = true;
  946. }
  947. }).catch(err => {
  948. this.tbStatus = 3;
  949. });
  950. }
  951. if(this.tbStatus == 3){
  952. this.loading = false;
  953. return false;
  954. }
  955. }
  956. if(this.menuIndex == '5'){ // 小红书
  957. if(this.redStatus == 1 || this.redStatus == 3){ // 未检测登录状态/或提示未登录状态,开始检测
  958. await this.checkRedLogin().then((data) => {
  959. if(data != 2){ // 未登录
  960. this.redStatus = 3;
  961. this.loginVisible = true;
  962. }
  963. }).catch(err => {
  964. this.redStatus = 3;
  965. });
  966. if(this.redStatus == 3){
  967. this.loading = false;
  968. return false;
  969. }
  970. }
  971. }
  972. if(this.menuIndex == '9'){ // 拼多多
  973. if(this.pddStatus == 1 || this.pddStatus == 3){ // 未检测登录状态/或提示未登录状态,开始检测
  974. await this.checkPddLogin().then((data) => {
  975. if(data != 2){ // 未登录
  976. this.pddStatus = 3;
  977. this.loginVisible = true;
  978. }
  979. }).catch(err => {
  980. this.pddStatus = 3;
  981. });
  982. if(this.pddStatus == 3){
  983. this.loading = false;
  984. return false;
  985. }
  986. }
  987. }
  988. let taskArr = [];
  989. let task = "";
  990. let userDataDir = this.initDataDir();
  991. if(this.menuIndex == '2'){
  992. userDataDir = this.initDataDir('jd');
  993. }
  994. // 运行不同平台的浏览器
  995. puppeteer.use(StealthPlugin());
  996. let browserName = listNameArr[index] + 'Browser';
  997. if(index == '2'){ // 天猫和淘宝共用一个
  998. browserName = 'tbBrowser';
  999. }
  1000. let headless = true;
  1001. headless = this.initDevelop().headless;
  1002. let redSize = '';
  1003. if(['3','4','5'].indexOf(this.menuIndex) > -1){
  1004. redSize = '--window-size=1920,800'; //给浏览器一个初始大小,在无头模式下,页面会自适用缩放
  1005. }
  1006. if(this[browserName] && this[browserName].isConnected()){
  1007. }else{
  1008. for(let i = 0; i < listNameArr.length; i++){
  1009. if(listNameArr[i]){
  1010. if(this[listNameArr[i]+'Browser']){
  1011. await this[listNameArr[i]+'Browser'].close();
  1012. this[listNameArr[i]+'Browser'] = null;
  1013. }
  1014. }
  1015. }
  1016. this[browserName] = await puppeteer.launch({
  1017. headless: headless,
  1018. executablePath: this.initPath(),
  1019. userDataDir: userDataDir,
  1020. args: [
  1021. '--start-maximized',
  1022. '--no-sandbox',
  1023. '--disable-setuid-sandbox',
  1024. '--disable-blink-features=AutomationControlled',
  1025. redSize
  1026. ]
  1027. });
  1028. }
  1029. for(let i = 0; i < fileList.length; i++){
  1030. let item = fileList[i];
  1031. switch(this.menuIndex){
  1032. case '1': // 阿里巴巴
  1033. task = this.alibabaDownload(item, this.alibabaBrowser);
  1034. break;
  1035. case '2': // 京东
  1036. task = this.jdScanImg(item, this.jdBrowser);
  1037. break;
  1038. case '3': // 天猫
  1039. case '4': // 淘宝
  1040. task = this.tbScanImg(item, this.tbBrowser);
  1041. break;
  1042. case '5': // 小红书
  1043. task = this.redDownload(item, this.redBrowser);
  1044. break;
  1045. case '6': // 阿里国际
  1046. task = this.alibabaDownload(item, this.aliguojiBrowser);
  1047. break;
  1048. case '7': // 百度爱采购
  1049. task = this.alibabaDownload(item, this.acaigouBrowser);
  1050. break;
  1051. case '8': // 亚马逊
  1052. task = this.alibabaDownload(item, this.amazonBrowser);
  1053. break;
  1054. case '9': // 拼多多
  1055. task = this.pddDownload(item, this.pddBrowser);
  1056. break;
  1057. case '10': // 普通网址
  1058. task = this.normalDownload(item, this.commonBrowser);
  1059. break;
  1060. case '11': // 闲鱼
  1061. task = this.goofishDownload(item, this.goofishBrowser);
  1062. break;
  1063. case '12': // 抖店
  1064. task = this.dyDownload(item, this.dyBrowser);
  1065. break;
  1066. }
  1067. if(this.pauseFlag){ //暂停跳出循环
  1068. break;
  1069. }
  1070. if(task){
  1071. taskArr.push(task);
  1072. }
  1073. if((i+1) % this.execLimit == 0){
  1074. await Promise.all(taskArr).then(result => {
  1075. taskArr = [];
  1076. }).catch(err => {
  1077. console.log('err'+i, err)
  1078. })
  1079. }
  1080. }
  1081. if(taskArr.length > 0){
  1082. await Promise.all(taskArr).then(result => {
  1083. taskArr = [];
  1084. }).catch(err => {
  1085. // 错误文件添加到服务中
  1086. console.log('err',err)
  1087. })
  1088. }
  1089. if(this[browserName]){
  1090. //如果是前台显示模式就不关闭浏览器
  1091. let n1 = this.$utils.getStorage('exeType');
  1092. if(n1 && n1 == 2){
  1093. }else{
  1094. this[browserName].close();
  1095. this[browserName] = null;
  1096. }
  1097. }
  1098. this.loading = false;
  1099. // 打开文件夹
  1100. if(fileList.length > 0){
  1101. this.$message({message: '恭喜你,任务已完成!', type: 'success'});
  1102. electronApi.call('showItemInfolder',[this.downloadDir + separator + pjson.softInfo.softName +'\\tty.tty'])
  1103. }
  1104. }
  1105. },
  1106. // 通用的延迟函数
  1107. async delay() {
  1108. let s = this.initGap();
  1109. if(s > 0){
  1110. return new Promise(resolve => setTimeout(resolve, Number(s)*1000));
  1111. }else{
  1112. return null;
  1113. }
  1114. },
  1115. // 10-普通网址下载
  1116. async normalDownload(urlInfo, commonBrowser){
  1117. let task = await new Promise((resolve,reject) =>{
  1118. (async () => {
  1119. try{
  1120. let authority = this.$refs.headerRef.authority.isAuthority;
  1121. let number = 0;
  1122. urlInfo.status = '2';
  1123. urlInfo.num = 0;
  1124. const page = await commonBrowser.newPage();
  1125. let titleFlag = true;
  1126. page.on('response', async(response) => {
  1127. if(titleFlag){ // 第一次生成页面标题
  1128. if(urlInfo.title){
  1129. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
  1130. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  1131. } else {
  1132. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
  1133. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  1134. }
  1135. }else{
  1136. await this.getTitle(page, urlInfo); // 生成页面标题对应的文件夹
  1137. }
  1138. titleFlag = false;
  1139. }
  1140. // 检查响应的 MIME 类型是否以 'image/' 开头
  1141. let flag = false;
  1142. if(response.headers()['content-encoding'] && response.headers()['content-encoding'].indexOf('gzip') > -1){
  1143. flag = true;
  1144. }
  1145. if (response.headers()['content-type'] && response.headers()['content-type'].startsWith('image/') && (flag || response.headers()['content-length'])) {
  1146. let imgArr = ['gif', 'jpeg', 'png', 'webp', 'svg', 'tiff', 'bmp', 'ico', 'avif'];
  1147. let imgType = 'jpg';
  1148. let isBase = false;
  1149. imgArr.map((item, index) => {
  1150. if(response.headers()['content-type'].indexOf(item) > -1){
  1151. imgType = item;
  1152. if(item == 'jpeg'){
  1153. imgType = 'jpg';
  1154. }else if(item == 'avif'){
  1155. imgType = 'png';
  1156. }
  1157. }
  1158. });
  1159. let url = response.url();
  1160. let regex = /^data:image\/[\w|+|-]+;base64,/;
  1161. if(regex.exec(url)){
  1162. url = response.url().replace(/^data:image\/[\w|+|-]+;base64,/, '');
  1163. isBase = true;
  1164. }
  1165. let imgInfo = {
  1166. url: url,
  1167. contentType: response.headers()['content-type'],
  1168. status: response.status(),
  1169. imgType: imgType,
  1170. isBase: isBase
  1171. }
  1172. let outputPath = urlInfo.newPath + '\\' + this.randomString(35) + '.' + imgInfo.imgType;
  1173. urlInfo.status = '3';
  1174. number++;
  1175. if(!authority && number <= this.execNum){
  1176. if(imgInfo.isBase){ //base64位图片下载
  1177. this.downloadBaseImage(imgInfo.url, outputPath, urlInfo)
  1178. }else{
  1179. this.downloadImage(imgInfo.url, outputPath, urlInfo);
  1180. }
  1181. }
  1182. if(authority){
  1183. if(imgInfo.isBase){ //base64位图片下载
  1184. this.downloadBaseImage(imgInfo.url, outputPath, urlInfo)
  1185. }else{
  1186. this.downloadImage(imgInfo.url, outputPath, urlInfo);
  1187. }
  1188. }
  1189. }
  1190. });
  1191. await page.goto(urlInfo.url, {waitUntil : 'networkidle2'});
  1192. let pageInfo = await page.evaluate(() => {
  1193. let cHeight = document.documentElement.clientHeight;
  1194. let scrollHeight = document.body.scrollHeight;
  1195. return {'scrollHeight': scrollHeight, 'cHeight': cHeight}
  1196. });
  1197. let scrollHeight = pageInfo.scrollHeight;
  1198. let cHeight = pageInfo.cHeight;
  1199. let num = Math.ceil(scrollHeight / cHeight);
  1200. let start = -1;
  1201. let scrollTime = this.initMs();
  1202. let scrollInt = setInterval(async() => {
  1203. start ++;
  1204. await page.evaluate((start) => {
  1205. let cHeight = document.documentElement.clientHeight;
  1206. window.scrollTo({
  1207. top: cHeight * start,
  1208. behavior: "smooth"
  1209. });
  1210. }, start);
  1211. if(start > num || start > 200){ // 防止页面过长,滚动200次自动停止
  1212. clearInterval(scrollInt);
  1213. await page.close();
  1214. urlInfo.status = '4';
  1215. await this.delay();
  1216. resolve(true);
  1217. this.loading = false;
  1218. }
  1219. }, scrollTime);
  1220. }catch(e){
  1221. urlInfo.status = '5';
  1222. reject(e);
  1223. this.showError(e);
  1224. }
  1225. })();
  1226. });
  1227. },
  1228. // 检查阿里巴巴登录状态
  1229. checkAlibabaLogin(){
  1230. this.checkLoading = true;
  1231. this.alibabaStatus = 1;
  1232. return new Promise((resolve, reject) => {
  1233. (async () => {
  1234. try{
  1235. if(this.loginBrowser){
  1236. await this.loginBrowser.close();
  1237. this.loginBrowser = null;
  1238. }
  1239. this.loginBrowser = await puppeteer.launch({
  1240. executablePath: this.initPath(),
  1241. args: ['--window-size=1280,800'],
  1242. userDataDir: this.initDataDir()
  1243. });
  1244. const page = await this.loginBrowser.newPage();
  1245. await page.setViewport({ width: 1280, height: 800 });
  1246. let testUrl = 'https://www.1688.com';
  1247. await page.goto(testUrl, {waitUntil : 'networkidle2'});
  1248. const cookies = await page.cookies();
  1249. let loginDiv = await page.$('div[class^=userNotLogin-]');
  1250. const loginEle = await page.$('div[class^=loginAvatar-]');
  1251. let loginText = '';
  1252. if (loginEle) {
  1253. loginText = await page.evaluate(el => el.innerText, loginEle);
  1254. }
  1255. const loginCookie = cookies.find(cookie =>
  1256. cookie.name === '__cn_logon__'
  1257. );
  1258. let logonValue = '';
  1259. if(loginCookie){
  1260. logonValue = loginCookie.value;
  1261. }
  1262. if(loginDiv || loginText == '登录' || logonValue == 'false' || logonValue == false){
  1263. this.alibabaStatus = 3; //未登录
  1264. }else{
  1265. this.alibabaStatus = 2;
  1266. }
  1267. resolve(this.alibabaStatus);
  1268. this.checkLoading = false;
  1269. await this.loginBrowser.close();
  1270. this.loginBrowser = null;
  1271. }catch(e){
  1272. this.checkLoading = false;
  1273. reject(3);
  1274. this.showError(e);
  1275. }
  1276. })();
  1277. });
  1278. },
  1279. // 1 - 阿里巴巴下载
  1280. async alibabaDownload(urlInfo, browser){
  1281. let task = await new Promise((resolve,reject) =>{
  1282. (async () => {
  1283. try{
  1284. let authority = this.$refs.headerRef.authority.isAuthority;
  1285. urlInfo.status = '2';
  1286. urlInfo.num = 0;
  1287. const page = await browser.newPage();
  1288. let waitUntil = 'networkidle2';
  1289. waitUntil = this.initDevelop().waitUntil;
  1290. let goUrl = urlInfo.url;
  1291. if(this.menuIndex == '1' && goUrl.indexOf('version=0') == -1){ // 阿里巴巴
  1292. if(goUrl.indexOf('?') > -1){
  1293. goUrl += "&version=0";
  1294. }else{
  1295. goUrl += "?verison=0";
  1296. }
  1297. }
  1298. await page.goto(goUrl, {waitUntil : waitUntil});
  1299. if(urlInfo.title){
  1300. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
  1301. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  1302. } else {
  1303. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
  1304. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  1305. }
  1306. }else{
  1307. await this.getTitle(page, urlInfo); // 生成页面标题对应的文件夹
  1308. }
  1309. let pageInfo = await page.evaluate(() => {
  1310. let cHeight = document.documentElement.clientHeight;
  1311. let scrollHeight = document.body.scrollHeight;
  1312. return {'scrollHeight': scrollHeight, 'cHeight': cHeight}
  1313. });
  1314. let scrollHeight = pageInfo.scrollHeight;
  1315. let cHeight = pageInfo.cHeight;
  1316. let num = Math.ceil(scrollHeight / cHeight);
  1317. let start = -1;
  1318. let scrollTime = this.initMs();
  1319. if(scrollTime < 800 && this.menuIndex == '6'){
  1320. scrollTime = 800;
  1321. }
  1322. let scrollInt = setInterval(async() => {
  1323. start ++;
  1324. if(this.settingArr.indexOf('detailImg') > -1){
  1325. let scrollHeight2 = await page.evaluate((start) => {
  1326. let scrollHeight = document.body.scrollHeight;
  1327. let cHeight = document.documentElement.clientHeight;
  1328. // let num = Math.ceil(scrollHeight / cHeight);
  1329. window.scrollTo({
  1330. top: cHeight * start,
  1331. behavior: "smooth"
  1332. });
  1333. return scrollHeight;
  1334. }, start);
  1335. num = Math.ceil(scrollHeight2 / cHeight);
  1336. }
  1337. if(start > num || start > 200){ // 防止页面过长,滚动200次自动停止
  1338. urlInfo.status = '3';
  1339. clearInterval(scrollInt);
  1340. if(this.menuIndex == '1'){ // 阿里巴巴
  1341. await this.alibabaScanImg(browser, page, urlInfo, authority);
  1342. }else if(this.menuIndex == '6'){ //阿里国际
  1343. await this.aliguojiScanImg(browser, page, urlInfo, authority);
  1344. }else if(this.menuIndex == '7'){ // 爱采购
  1345. await this.acaigouScanImg(browser, page, urlInfo, authority);
  1346. }else if(this.menuIndex == '8'){ // 亚马逊
  1347. await this.amazonScanImg(browser, page, urlInfo, authority);
  1348. }
  1349. this.loading = false;
  1350. urlInfo.status = '4';
  1351. await this.delay();
  1352. resolve(true);
  1353. }
  1354. }, scrollTime);
  1355. }catch(e){
  1356. urlInfo.status = '5';
  1357. reject(e);
  1358. this.showError(e);
  1359. }
  1360. })();
  1361. });
  1362. },
  1363. // 检查京东登录状态
  1364. checkJdLogin(){
  1365. this.checkLoading = true;
  1366. this.jdStatus = 1;
  1367. return new Promise((resolve, reject) => {
  1368. (async () => {
  1369. try{
  1370. if(this.loginBrowser){
  1371. await this.loginBrowser.close();
  1372. this.loginBrowser = null;
  1373. }
  1374. this.loginBrowser = await puppeteer.launch({
  1375. executablePath: this.initPath(),
  1376. userDataDir: this.initDataDir('jd'),
  1377. args: [
  1378. '--start-maximized',
  1379. '--no-sandbox',
  1380. '--disable-setuid-sandbox',
  1381. '--disable-blink-features=AutomationControlled',
  1382. '--window-size=1280,800'
  1383. ]
  1384. });
  1385. const page = await this.loginBrowser.newPage();
  1386. await page.setViewport({ width: 1280, height: 800 });
  1387. let testUrl = 'https://www.jd.com';
  1388. await page.goto(testUrl, {waitUntil : 'networkidle2'});
  1389. let loginInfo = await page.evaluate(() => {
  1390. let navTags = document.querySelector('.link-login');
  1391. let userTags = document.querySelector('.nickname');
  1392. let userTags2 = document.querySelector('.nick'); //企业账号
  1393. let userInfo2 = document.querySelector('.login_info'); //页面右侧的登录信息
  1394. let userTags3 = false;
  1395. if(userInfo2 && userInfo2.innerText.indexOf('退出') > -1){
  1396. userTags3 = true;
  1397. }
  1398. if(navTags && navTags.innerHTML.indexOf('请登录') > -1 && !userTags3){
  1399. return false;
  1400. }else if(userTags || userTags2 || userTags3){
  1401. return true;
  1402. }else{
  1403. return false;
  1404. }
  1405. });
  1406. if(loginInfo){
  1407. this.jdStatus = 2;
  1408. }else{
  1409. this.jdStatus = 3;
  1410. }
  1411. resolve(this.jdStatus);
  1412. this.checkLoading = false;
  1413. await this.loginBrowser.close();
  1414. this.loginBrowser = null;
  1415. }catch(e){
  1416. this.checkLoading = false;
  1417. reject(3);
  1418. this.showError(e);
  1419. }
  1420. })();
  1421. });
  1422. },
  1423. // 京东下载
  1424. async jdScanImg(urlInfo, jdBrowser){
  1425. let task = await new Promise((resolve,reject) =>{
  1426. (async () => {
  1427. try{
  1428. let authority = this.$refs.headerRef.authority.isAuthority;
  1429. urlInfo.status = '2';
  1430. urlInfo.num = 0;
  1431. const page = await jdBrowser.newPage();
  1432. await page.evaluateOnNewDocument(() => {
  1433. const newProto = navigator.__proto__;
  1434. delete newProto.webdriver;
  1435. navigator.__proto__ = newProto;
  1436. window.navigator.chrome = {
  1437. runtime: {}
  1438. };
  1439. });
  1440. let jdImgInfo = {
  1441. mainImg: [],
  1442. skuImg: [],
  1443. commentImg: [],
  1444. detailImg: [],
  1445. video: []
  1446. };
  1447. let titleFlag = true;
  1448. let skuNum = 0, mainNum = 0, videoNum = 0;
  1449. page.on('response', async(response) => {
  1450. if(titleFlag){ // 第一次生成页面标题
  1451. if(urlInfo.title){
  1452. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
  1453. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  1454. } else {
  1455. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
  1456. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  1457. }
  1458. }else{
  1459. await this.getTitle(page, urlInfo); // 生成页面标题对应的文件夹
  1460. }
  1461. titleFlag = false;
  1462. }
  1463. // 检查响应的 MIME 类型是否以 'image/' 开头
  1464. if (response.headers()['content-type']) {
  1465. let detailUrl = '';
  1466. let videoUrl = '';
  1467. if(response.url().indexOf('/description/') > -1){ // 商品详情接口
  1468. detailUrl = response.url();
  1469. }
  1470. if(response.url().indexOf('/tencent/video_v3') > -1){ // 商品视频接口
  1471. videoUrl = response.url();
  1472. }
  1473. urlInfo.status = '3';
  1474. if(detailUrl && this.settingArr.indexOf('detailImg') > -1){ // jd商品详情
  1475. try {
  1476. let data = await response.text();
  1477. if(data.indexOf('showdesc(') > -1){
  1478. data = data.slice(0, -1).replace('showdesc(', '');
  1479. }
  1480. let detailInfo = JSON.parse(data);
  1481. let regex = /\/\/img[0-9]+.360buyimg.com\S+.(jpg|jpeg|png|gif|avif|tif|tiff)/g;
  1482. let detailImgArr = [];
  1483. if(detailInfo && detailInfo.content){
  1484. if(detailInfo.content.match(regex)){
  1485. detailImgArr = detailInfo.content.match(regex);
  1486. }
  1487. }
  1488. jdImgInfo.detailImg = detailImgArr;
  1489. for(let i = 0; i < detailImgArr.length; i++){
  1490. let imgUrl = 'https:' + detailImgArr[i];
  1491. imgUrl = imgUrl.replace('.avif', '');
  1492. let fileName = imgUrl.split('/').pop();
  1493. if(fileName){
  1494. let queryIndex = fileName.indexOf('?');
  1495. if (queryIndex !== -1) {
  1496. fileName = fileName.substr(0, queryIndex);
  1497. }
  1498. let num = Number(i) + 1;
  1499. let suffix = '';
  1500. if(fileName.lastIndexOf('.') > -1){
  1501. suffix = fileName.substr(fileName.lastIndexOf('.'));
  1502. }
  1503. if (!fs.existsSync(urlInfo.newPath + '\\详情图')) {
  1504. fs.mkdirSync(urlInfo.newPath + '\\详情图');
  1505. }
  1506. let outputPath = urlInfo.newPath + '\\详情图\\详情图' + num + suffix;
  1507. if(!authority && i < this.execNum){
  1508. await this.downloadImage(imgUrl, outputPath, urlInfo);
  1509. }
  1510. if(authority){
  1511. await this.downloadImage(imgUrl, outputPath, urlInfo);
  1512. }
  1513. }
  1514. }
  1515. } catch (error) {
  1516. console.error('详情图片解析失败:', error);
  1517. }
  1518. }
  1519. if(videoUrl && this.settingArr.indexOf('video') > -1){ // jd商品视频
  1520. try {
  1521. let data = await response.text();
  1522. data = data.slice(0, -1).replace(/^jQuery[0-9]+\(/, '');
  1523. let videoInfo = JSON.parse(data);
  1524. let videoUrl = videoInfo.playUrl;
  1525. jdImgInfo.video.push(videoUrl);
  1526. let fileName = videoUrl.split('/').pop();
  1527. if(fileName){
  1528. let queryIndex = fileName.indexOf('?');
  1529. if (queryIndex !== -1) {
  1530. fileName = fileName.substr(0, queryIndex);
  1531. }
  1532. if (!fs.existsSync(urlInfo.newPath + '\\视频')) {
  1533. fs.mkdirSync(urlInfo.newPath + '\\视频');
  1534. }
  1535. let outputPath = urlInfo.newPath + '\\视频\\' + fileName;
  1536. await this.downloadImage(videoUrl, outputPath, urlInfo);
  1537. }
  1538. } catch (error) {
  1539. console.error('视频解析失败:', error);
  1540. }
  1541. }
  1542. }
  1543. });
  1544. await page.goto(urlInfo.url, {waitUntil : 'networkidle2'});
  1545. let pageInfo = await page.evaluate(() => {
  1546. let cHeight = document.documentElement.clientHeight;
  1547. let scrollHeight = document.body.scrollHeight;
  1548. return {'scrollHeight': scrollHeight, 'cHeight': cHeight}
  1549. });
  1550. let scrollHeight = pageInfo.scrollHeight;
  1551. let cHeight = pageInfo.cHeight;
  1552. let num = Math.ceil(scrollHeight / cHeight);
  1553. let start = -1;
  1554. let scrollTime = this.initMs();
  1555. let scrollInt = setInterval(async() => {
  1556. start ++;
  1557. if(this.settingArr.indexOf('detailImg') > -1){ // 选择详情图
  1558. let scrollHeight2 = await page.evaluate((start) => {
  1559. let scrollHeight = document.body.scrollHeight;
  1560. let cHeight = document.documentElement.clientHeight;
  1561. let obj = document.querySelector('.detail-content') || document.querySelector('.detail-content-item');
  1562. if(obj && obj.getBoundingClientRect().top < 0){
  1563. return -1;
  1564. }
  1565. window.scrollTo({
  1566. top: cHeight * start,
  1567. behavior: "smooth"
  1568. });
  1569. return scrollHeight;
  1570. }, start);
  1571. if(scrollHeight2 > 0){
  1572. num = Math.ceil(scrollHeight2 / cHeight);
  1573. }else{
  1574. num = 0;
  1575. }
  1576. }else{
  1577. num = 0;
  1578. }
  1579. if(start > num || start > 20){ // 防止页面过长,滚动20次自动停止
  1580. clearInterval(scrollInt);
  1581. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  1582. const imgInfo = await page.evaluate((authority, execNum) => {
  1583. let outObj = {
  1584. mainImg: [],
  1585. skuImg: [],
  1586. detailImg: []
  1587. };
  1588. //主图
  1589. let arr1 = document.querySelectorAll('#spec-list img');
  1590. for(let i=0; i< arr1.length; i++){
  1591. let mainImgUrl = arr1[i].src;
  1592. let reg = /\/n[0-9]+\/jfs\//;
  1593. let reg2 = /\/n[0-9]+\/s([0-9]+)x([0-9]+)_jfs\//;
  1594. let reg3 = /![a-z]+_[0-9]+x[0-9]+(.avif)?/;
  1595. let replaceStr = '/n5/s800x800_jfs/';
  1596. if(mainImgUrl.match(/\/n[0-9]+\/s50x66_jfs\//)){
  1597. replaceStr = '/n5/s750x1000_jfs/';
  1598. }
  1599. mainImgUrl = mainImgUrl.replace(reg, replaceStr).replace(reg2, replaceStr).replace(reg3, '').replace('.avif', '');
  1600. if(!authority && i < execNum){
  1601. outObj.mainImg.push(mainImgUrl);
  1602. }
  1603. if(authority){
  1604. outObj.mainImg.push(mainImgUrl);
  1605. }
  1606. }
  1607. //sku图片
  1608. let arr2 = document.querySelectorAll('#choose-attr-1 img');
  1609. for(let i=0; i< arr2.length; i++){
  1610. let skuImgUrl = arr2[i].src;
  1611. let skuReg = /\/n[0-9]+\/s([0-9]+)x([0-9]+)_jfs\//;
  1612. let replaceStr = '/n5/s800x800_jfs/';
  1613. if(skuImgUrl.match(/\/n[0-9]+\/s60x80_jfs\//)){
  1614. replaceStr = '/n5/s750x1000_jfs/';
  1615. }
  1616. skuImgUrl = skuImgUrl.replace(skuReg, replaceStr).replace('.avif', '');
  1617. if(!authority && i < execNum){
  1618. outObj.skuImg.push(skuImgUrl);
  1619. }
  1620. if(authority){
  1621. outObj.skuImg.push(skuImgUrl);
  1622. }
  1623. }
  1624. //详情图 - 图片类目需要网页直接抓取
  1625. let arr3 = document.querySelectorAll('.book-detail-content img');
  1626. for(let i=0; i< arr3.length; i++){
  1627. let detailImgUrl = arr3[i].src;
  1628. detailImgUrl = detailImgUrl.replace('.avif', '');
  1629. if(!authority && i < execNum){
  1630. outObj.detailImg.push(detailImgUrl);
  1631. }
  1632. if(authority){
  1633. outObj.detailImg.push(detailImgUrl);
  1634. }
  1635. }
  1636. return outObj;
  1637. }, authority, this.execNum);
  1638. if(this.settingArr.indexOf('mainImg') > -1){
  1639. // 主图下载
  1640. for(let j = 0; j < imgInfo.mainImg.length; j++){
  1641. let fileName = imgInfo.mainImg[j].split('/').pop();
  1642. if(fileName){
  1643. let queryIndex = fileName.indexOf('?');
  1644. if (queryIndex !== -1) {
  1645. fileName = fileName.substr(0, queryIndex);
  1646. }
  1647. let num = Number(j) + 1;
  1648. let suffix = '';
  1649. if(fileName.lastIndexOf('.') > -1){
  1650. suffix = fileName.substr(fileName.lastIndexOf('.'));
  1651. }
  1652. if (!fs.existsSync(urlInfo.newPath + '\\主图')) {
  1653. fs.mkdirSync(urlInfo.newPath + '\\主图');
  1654. }
  1655. let outputPath = urlInfo.newPath + '\\主图\\主图' + num + suffix;
  1656. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  1657. }
  1658. }
  1659. }
  1660. // sku图片下载
  1661. if(this.settingArr.indexOf('skuImg') > -1){
  1662. for(let j = 0; j < imgInfo.skuImg.length; j++){
  1663. let fileName = imgInfo.skuImg[j].split('/').pop();
  1664. if(fileName){
  1665. let queryIndex = fileName.indexOf('?');
  1666. if (queryIndex !== -1) {
  1667. fileName = fileName.substr(0, queryIndex);
  1668. }
  1669. let num = Number(j) + 1;
  1670. let suffix = '';
  1671. if(fileName.lastIndexOf('.') > -1){
  1672. suffix = fileName.substr(fileName.lastIndexOf('.'));
  1673. }
  1674. if (!fs.existsSync(urlInfo.newPath + '\\sku图')) {
  1675. fs.mkdirSync(urlInfo.newPath + '\\sku图');
  1676. }
  1677. let outputPath = urlInfo.newPath + '\\sku图\\sku图' + num + suffix;
  1678. await this.downloadImage(imgInfo.skuImg[j], outputPath, urlInfo);
  1679. }
  1680. }
  1681. }
  1682. // 详情图下载 --图书类目
  1683. if(this.settingArr.indexOf('detailImg') > -1 && jdImgInfo.detailImg.length == 0){
  1684. for(let j = 0; j < imgInfo.detailImg.length; j++){
  1685. let fileName = imgInfo.detailImg[j].split('/').pop();
  1686. if(fileName){
  1687. let queryIndex = fileName.indexOf('?');
  1688. if (queryIndex !== -1) {
  1689. fileName = fileName.substr(0, queryIndex);
  1690. }
  1691. let num = Number(j) + 1;
  1692. let suffix = '';
  1693. if(fileName.lastIndexOf('.') > -1){
  1694. suffix = fileName.substr(fileName.lastIndexOf('.'));
  1695. }
  1696. if (!fs.existsSync(urlInfo.newPath + '\\详情图')) {
  1697. fs.mkdirSync(urlInfo.newPath + '\\详情图');
  1698. }
  1699. let outputPath = urlInfo.newPath + '\\详情图\\详情图' + num + suffix;
  1700. await this.downloadImage(imgInfo.detailImg[j], outputPath, urlInfo);
  1701. }
  1702. }
  1703. }
  1704. /**end**/
  1705. await page.close();
  1706. urlInfo.status = '4';
  1707. await this.delay();
  1708. resolve(true);
  1709. this.loading = false;
  1710. }
  1711. }, scrollTime);
  1712. }catch(e){
  1713. reject(e);
  1714. this.showError(e);
  1715. }
  1716. })();
  1717. });
  1718. },
  1719. // 检查天猫淘宝登录状态
  1720. checkLogin(){
  1721. this.checkLoading = true;
  1722. this.tbStatus = 1;
  1723. return new Promise((resolve, reject) => {
  1724. (async () => {
  1725. try{
  1726. if(this.loginBrowser){
  1727. await this.loginBrowser.close();
  1728. this.loginBrowser = null;
  1729. }
  1730. this.loginBrowser = await puppeteer.launch({
  1731. executablePath: this.initPath(),
  1732. args: ['--window-size=1280,800'],
  1733. userDataDir: this.initDataDir()
  1734. });
  1735. const page = await this.loginBrowser.newPage();
  1736. await page.setViewport({ width: 1280, height: 800 });
  1737. let testUrl = 'https://www.taobao.com';
  1738. await page.goto(testUrl, {waitUntil : 'networkidle2'});
  1739. let loginInfo = await page.evaluate(() => {
  1740. let navTags = document.querySelector('.site-nav-sign a');
  1741. let userTags = document.querySelector('.site-nav-user a');
  1742. if(navTags && navTags.innerHTML.indexOf('登录') > -1){
  1743. return false;
  1744. }else if(userTags){
  1745. return true;
  1746. }else{
  1747. return false;
  1748. }
  1749. });
  1750. if(loginInfo){
  1751. this.tbStatus = 2;
  1752. }else{
  1753. this.tbStatus = 3;
  1754. }
  1755. resolve(this.tbStatus);
  1756. this.checkLoading = false;
  1757. await this.loginBrowser.close();
  1758. this.loginBrowser = null;
  1759. }catch(e){
  1760. this.checkLoading = false;
  1761. reject(3);
  1762. this.showError(e);
  1763. }
  1764. })();
  1765. });
  1766. },
  1767. // 淘宝天猫扫描下载图片
  1768. async tbScanImg(urlInfo, tbBrowser){
  1769. let task = await new Promise((resolve,reject) =>{
  1770. (async () => {
  1771. try{
  1772. let authority = this.$refs.headerRef.authority.isAuthority;
  1773. urlInfo.status = '2';
  1774. urlInfo.num = 0;
  1775. let page = await tbBrowser.newPage();
  1776. let responseVideo = [];
  1777. page.on('response', async(response) => {
  1778. // 检查响应的 MIME 类型是否以 'video/' 开头
  1779. if (response.headers()['content-type'] && response.headers()['content-type'].startsWith('video/')) {
  1780. if(responseVideo.indexOf(response.url()) < 0 && !response.url().startsWith('blob:https://')){
  1781. responseVideo.push(response.url());
  1782. }
  1783. }
  1784. });
  1785. let waitUntil = 'networkidle2';
  1786. waitUntil = this.initDevelop().waitUntil;
  1787. await page.goto(urlInfo.url, {waitUntil : waitUntil});
  1788. // 特殊处理
  1789. let nextBtn = await page.$x("//button[contains(text(), '快速进入')]");
  1790. if(nextBtn && nextBtn.length > 0){
  1791. nextBtn[0].click({force: true});
  1792. await page.waitForTimeout(3000);
  1793. }
  1794. if(this.settingArr.indexOf('video') > -1){ // 用户选择下载视频的时候才会触发
  1795. //鼠标放在主图第一张,生成视频
  1796. const elementHandle = await page.$('[class*=thumbnail--]');
  1797. if(elementHandle){
  1798. const classListProperty = await elementHandle.getProperty('classList');
  1799. const classList = await classListProperty.jsonValue();
  1800. const classesArray = Object.values(classList);
  1801. const allClasses = classesArray.join('.');
  1802. if(allClasses && allClasses.indexOf('active-') < 0){
  1803. await page.hover('.'+allClasses);
  1804. }
  1805. }
  1806. }
  1807. let frames = await page.$$('iframe');
  1808. if(frames.length == 1){ // 就一个
  1809. let isAdVisible = false;
  1810. try{ //判断是否是隐藏弹窗iframe
  1811. isAdVisible = await page.$eval('iframe', ad => {
  1812. return getComputedStyle(ad).display !== 'none';
  1813. });
  1814. }catch(e){
  1815. }
  1816. if(isAdVisible){
  1817. let m2 = await page.$('img[class*=thumbnailPic--]');
  1818. if(!m2){ // 出现弹窗而且没有主图,判断为拦截模式
  1819. await page.close();
  1820. urlInfo.status = '6';
  1821. resolve(true);
  1822. this.loading = false;
  1823. return false;
  1824. }
  1825. }
  1826. }else if(frames.length > 1){ //多个弹窗就判断是否有图片显示
  1827. let m2 = await page.$('img[class*=thumbnailPic--]');
  1828. if(!m2){ // 出现弹窗而且没有主图,判断为拦截模式
  1829. await page.close();
  1830. urlInfo.status = '6';
  1831. resolve(true);
  1832. this.loading = false;
  1833. return false;
  1834. }
  1835. }
  1836. let pageInfo = await page.evaluate(() => {
  1837. let cHeight = document.documentElement.clientHeight;
  1838. let scrollHeight = document.body.scrollHeight;
  1839. return {'scrollHeight': scrollHeight, 'cHeight': cHeight}
  1840. });
  1841. let scrollHeight = pageInfo.scrollHeight;
  1842. let cHeight = pageInfo.cHeight;
  1843. let num = Math.ceil(scrollHeight / cHeight);
  1844. let start = -1;
  1845. let scrollTime = this.initMs();
  1846. let scrollInt = setInterval(async() => {
  1847. start ++;
  1848. if((this.settingArr.indexOf('skuImg') > -1 || this.settingArr.indexOf('commentImg') > -1) && this.settingArr.indexOf('detailImg') < 0){ // 选择了评论图没选择详情图
  1849. let scrollHeight2 = await page.evaluate((start) => {
  1850. let scrollHeight = document.body.scrollHeight;
  1851. let cHeight = document.documentElement.clientHeight;
  1852. let skuObj = document.querySelectorAll('div[class*=skuValueWrap--]');
  1853. let scrollObj = document.getElementById('tbpcDetail_SkuPanelBody');
  1854. if(skuObj.length > 0 && scrollObj){
  1855. document.getElementById('tbpcDetail_SkuPanelBody').scrollTo({top: 10000,behavior: "smooth" })
  1856. }
  1857. let obj = document.getElementById('container') || document.getElementById('content');
  1858. if(obj && obj.getBoundingClientRect().top < 0){
  1859. return -1;
  1860. }
  1861. window.scrollTo({
  1862. top: cHeight * start,
  1863. behavior: "smooth"
  1864. });
  1865. return scrollHeight;
  1866. }, start);
  1867. if(scrollHeight2 > 0){
  1868. num = Math.ceil(scrollHeight2 / cHeight);
  1869. }else{
  1870. num = 0;
  1871. }
  1872. }
  1873. if(this.settingArr.indexOf('detailImg') > -1){ // 选择详情图
  1874. let tag = false;
  1875. if(this.settingArr.indexOf('skuImg') > -1){ // 选择sku
  1876. tag = true;
  1877. }
  1878. let scrollHeight2 = await page.evaluate((start, tag) => {
  1879. let scrollHeight = document.body.scrollHeight;
  1880. let cHeight = document.documentElement.clientHeight;
  1881. if(tag){
  1882. let skuObj = document.querySelectorAll('div[class*=skuValueWrap--]');
  1883. let scrollObj = document.getElementById('tbpcDetail_SkuPanelBody');
  1884. if(skuObj.length > 0 && scrollObj){
  1885. document.getElementById('tbpcDetail_SkuPanelBody').scrollTo({top: 10000,behavior: "smooth" })
  1886. }
  1887. }
  1888. let obj = document.getElementById('container') || document.getElementById('content');
  1889. if(obj && obj.getBoundingClientRect().bottom < 100){
  1890. return -1;
  1891. }
  1892. window.scrollTo({
  1893. top: cHeight * start,
  1894. behavior: "smooth"
  1895. });
  1896. return scrollHeight;
  1897. }, start, tag);
  1898. if(scrollHeight2 > 0){
  1899. num = Math.ceil(scrollHeight2 / cHeight);
  1900. }else{
  1901. num = 0;
  1902. }
  1903. }
  1904. // if(this.settingArr.indexOf('skuImg') > -1 && this.settingArr.indexOf('commentImg') < 0 && this.settingArr.indexOf('detailImg') < 0){ // 选择了sku图片没选择评论和详情
  1905. // let scrollHeight2 = await page.evaluate((start) => {
  1906. // let scrollHeight = document.body.scrollHeight;
  1907. // let cHeight = document.documentElement.clientHeight;
  1908. // let obj = document.querySelector('div[class*=SkuContent--]');
  1909. // if(!obj){
  1910. // obj = document.querySelector('div[class*=skuValueWrap--]');
  1911. // }
  1912. // if(obj && obj.getBoundingClientRect().bottom < 500){
  1913. // return -1;
  1914. // }
  1915. // window.scrollTo({
  1916. // top: cHeight * start,
  1917. // behavior: "smooth"
  1918. // });
  1919. // document.getElementById('tbpcDetail_SkuPanelBody').scrollTo({top:1000,behavior: "smooth" })
  1920. // return scrollHeight;
  1921. // }, start);
  1922. // if(scrollHeight2 > 0){
  1923. // num = Math.ceil(scrollHeight2 / cHeight);
  1924. // }else{
  1925. // num = 0;
  1926. // }
  1927. // }
  1928. if(this.settingArr.indexOf('skuImg') < 0 && this.settingArr.indexOf('detailImg') < 0 && this.settingArr.indexOf('commentImg') < 0){ // 只有主图没有选择评论图和详情图
  1929. num = 0;
  1930. }
  1931. if(start > num || start > 200){ // 防止页面过长,滚动200次自动停止
  1932. urlInfo.status = '3';
  1933. clearInterval(scrollInt);
  1934. if(urlInfo.title){
  1935. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
  1936. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  1937. } else {
  1938. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
  1939. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  1940. }
  1941. }else{
  1942. await this.getTitle(page, urlInfo); // 生成页面标题对应的文件夹
  1943. }
  1944. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  1945. const imgInfo = await page.evaluate((authority, execNum) => {
  1946. let outObj = {
  1947. mainImg: [],
  1948. detailImg: [],
  1949. skuImg: [],
  1950. commentImg: [],
  1951. video: [],
  1952. test: []
  1953. };
  1954. // 正则表达式匹配字符 重写图片路径
  1955. let regex = /\.(.{3,4})_[0-9a-zA-z]+\.(.{3,4})_\.(.{3,4})/;
  1956. //主图
  1957. let arr1 = document.querySelectorAll('img[class^=PicGallery--thumbnailPic--]');
  1958. if(arr1.length === 0){
  1959. arr1 = document.querySelectorAll('img[class*=thumbnailPic--]');
  1960. }
  1961. for(let i=0; i< arr1.length; i++){
  1962. let mainImgUrl = arr1[i].src;
  1963. let result = regex.exec(mainImgUrl);
  1964. if(result){
  1965. mainImgUrl = mainImgUrl.replace(result[0], '.'+result[1]);
  1966. }
  1967. if(!authority && i < execNum){
  1968. outObj.mainImg.push(mainImgUrl);
  1969. }
  1970. if(authority){
  1971. outObj.mainImg.push(mainImgUrl);
  1972. }
  1973. }
  1974. //sku图片
  1975. let arr2 = document.querySelectorAll('img[class^=SkuContent--valueItemImg--]');
  1976. if(arr2.length === 0){
  1977. arr2 = document.querySelectorAll('img[class*=valueItemImg--]');
  1978. }
  1979. for(let i=0; i< arr2.length; i++){
  1980. let skuImgUrl = arr2[i].src;
  1981. outObj.test.push(arr2[i].src);
  1982. let result = regex.exec(skuImgUrl);
  1983. if(result){
  1984. skuImgUrl = skuImgUrl.replace(result[0], '.'+result[1]);
  1985. }
  1986. if(!authority && i < execNum){
  1987. outObj.skuImg.push(skuImgUrl);
  1988. }
  1989. if(authority){
  1990. outObj.skuImg.push(skuImgUrl);
  1991. }
  1992. }
  1993. //详情图片
  1994. let arr3 = document.querySelectorAll('#content img');
  1995. for(let i=0; i< arr3.length; i++){
  1996. let detailImgUrl = arr3[i].src;
  1997. let lazyUrl = arr3[i].getAttribute('data-src');
  1998. if(arr3[i].src.indexOf('/s.gif') > -1 && lazyUrl){
  1999. detailImgUrl = lazyUrl;
  2000. if(!/^http/.exec(lazyUrl)){
  2001. detailImgUrl = 'https:' + lazyUrl;
  2002. }
  2003. }
  2004. let result = regex.exec(detailImgUrl);
  2005. if(result){
  2006. detailImgUrl = detailImgUrl.replace(result[0], '.'+result[1]);
  2007. }
  2008. if(!authority && i < execNum){
  2009. outObj.detailImg.push(detailImgUrl);
  2010. }
  2011. if(authority){
  2012. outObj.detailImg.push(detailImgUrl);
  2013. }
  2014. }
  2015. //评论图片
  2016. let arr4 = document.querySelectorAll('div[class*=Comments--] img');
  2017. if(arr4.length === 0){
  2018. arr4 = document.querySelectorAll('div[class*=comments--] img');
  2019. }
  2020. for(let i=0; i< arr4.length; i++){
  2021. if(arr4[i].src.indexOf('/avatar/sns/user/flag/sns_logo') == -1 && arr4[i].className.indexOf('creditImg') == -1){ //过滤淘宝用户头像
  2022. if(!authority && i < execNum){
  2023. outObj.commentImg.push(arr4[i].src);
  2024. }
  2025. if(authority){
  2026. outObj.commentImg.push(arr4[i].src);
  2027. }
  2028. }
  2029. }
  2030. // 视频
  2031. let arr5 = document.querySelectorAll('video');
  2032. for(let i=0; i< arr5.length; i++){
  2033. if(outObj.video.indexOf(arr5[i].src) == -1){
  2034. if(!authority && i < execNum){
  2035. outObj.video.push(arr5[i].src);
  2036. }
  2037. if(authority){
  2038. outObj.video.push(arr5[i].src);
  2039. }
  2040. }
  2041. }
  2042. return outObj;
  2043. }, authority, this.execNum);
  2044. if(responseVideo.length > 0){
  2045. for(let l=0; l<responseVideo.length; l++){
  2046. if(imgInfo.video.indexOf(responseVideo[l]) == -1){
  2047. imgInfo.video.push(responseVideo[l]);
  2048. }
  2049. }
  2050. }
  2051. //console.log(imgInfo.test)
  2052. if(this.settingArr.indexOf('mainImg') > -1){
  2053. // 主图下载
  2054. for(let j = 0; j < imgInfo.mainImg.length; j++){
  2055. let fileName = imgInfo.mainImg[j].split('/').pop();
  2056. if(fileName){
  2057. let queryIndex = fileName.indexOf('?');
  2058. if (queryIndex !== -1) {
  2059. fileName = fileName.substr(0, queryIndex);
  2060. }
  2061. let num = Number(j) + 1;
  2062. let suffix = '';
  2063. if(fileName.lastIndexOf('.') > -1){
  2064. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2065. }
  2066. if (!fs.existsSync(urlInfo.newPath + '\\主图')) {
  2067. fs.mkdirSync(urlInfo.newPath + '\\主图');
  2068. }
  2069. let outputPath = urlInfo.newPath + '\\主图\\主图' + num + suffix;
  2070. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  2071. }
  2072. }
  2073. }
  2074. // sku图片下载
  2075. if(this.settingArr.indexOf('skuImg') > -1){
  2076. for(let j = 0; j < imgInfo.skuImg.length; j++){
  2077. let fileName = imgInfo.skuImg[j].split('/').pop();
  2078. if(fileName){
  2079. let queryIndex = fileName.indexOf('?');
  2080. if (queryIndex !== -1) {
  2081. fileName = fileName.substr(0, queryIndex);
  2082. }
  2083. let num = Number(j) + 1;
  2084. let suffix = '';
  2085. if(fileName.lastIndexOf('.') > -1){
  2086. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2087. }
  2088. if (!fs.existsSync(urlInfo.newPath + '\\sku图')) {
  2089. fs.mkdirSync(urlInfo.newPath + '\\sku图');
  2090. }
  2091. let outputPath = urlInfo.newPath + '\\sku图\\sku图' + num + suffix;
  2092. await this.downloadImage(imgInfo.skuImg[j], outputPath, urlInfo);
  2093. }
  2094. }
  2095. }
  2096. //详情图下载
  2097. if(this.settingArr.indexOf('detailImg') > -1){
  2098. for(let j = 0; j < imgInfo.detailImg.length; j++){
  2099. let fileName = imgInfo.detailImg[j].split('/').pop();
  2100. if(fileName){
  2101. let queryIndex = fileName.indexOf('?');
  2102. if (queryIndex !== -1) {
  2103. fileName = fileName.substr(0, queryIndex);
  2104. }
  2105. let num = Number(j) + 1;
  2106. let suffix = '';
  2107. if(fileName.lastIndexOf('.') > -1){
  2108. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2109. }
  2110. if (!fs.existsSync(urlInfo.newPath + '\\详情图')) {
  2111. fs.mkdirSync(urlInfo.newPath + '\\详情图');
  2112. }
  2113. let outputPath = urlInfo.newPath + '\\详情图\\详情图' + num + suffix;
  2114. await this.downloadImage(imgInfo.detailImg[j], outputPath, urlInfo);
  2115. }
  2116. }
  2117. }
  2118. //评论图下载
  2119. if(this.settingArr.indexOf('commentImg') > -1){
  2120. for(let j = 0; j < imgInfo.commentImg.length; j++){
  2121. let fileName = imgInfo.commentImg[j].split('/').pop();
  2122. if(fileName){
  2123. let queryIndex = fileName.indexOf('?');
  2124. if (queryIndex !== -1) {
  2125. fileName = fileName.substr(0, queryIndex);
  2126. }
  2127. let num = Number(j) + 1;
  2128. let suffix = '';
  2129. if(fileName.lastIndexOf('.') > -1){
  2130. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2131. }
  2132. if (!fs.existsSync(urlInfo.newPath + '\\评论图')) {
  2133. fs.mkdirSync(urlInfo.newPath + '\\评论图');
  2134. }
  2135. let outputPath = urlInfo.newPath + '\\评论图\\评论图' + num + suffix;
  2136. await this.downloadImage(imgInfo.commentImg[j], outputPath, urlInfo);
  2137. }
  2138. }
  2139. }
  2140. //视频下载
  2141. if(this.settingArr.indexOf('video') > -1){
  2142. for(let j = 0; j < imgInfo.video.length; j++){
  2143. let fileName = imgInfo.video[j].split('/').pop();
  2144. if(fileName){
  2145. let queryIndex = fileName.indexOf('?');
  2146. if (queryIndex !== -1) {
  2147. fileName = fileName.substr(0, queryIndex);
  2148. }
  2149. if (!fs.existsSync(urlInfo.newPath + '\\视频')) {
  2150. fs.mkdirSync(urlInfo.newPath + '\\视频');
  2151. }
  2152. let outputPath = urlInfo.newPath + '\\视频\\' + fileName;
  2153. await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
  2154. }
  2155. }
  2156. }
  2157. await page.close();
  2158. urlInfo.status = '4';
  2159. await this.delay();
  2160. resolve(true);
  2161. this.loading = false;
  2162. }
  2163. }, scrollTime);
  2164. }catch(e){
  2165. reject(e);
  2166. this.showError(e);
  2167. }
  2168. })();
  2169. });
  2170. },
  2171. // 阿里巴巴 - 扫描并下载图片
  2172. async alibabaScanImg(browser, page, urlInfo, authority){
  2173. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  2174. const imgInfo = await page.evaluate((authority, execNum) => {
  2175. let outObj = {
  2176. mainImg: [],
  2177. detailImg: [],
  2178. skuImg: [],
  2179. commentImg: [],
  2180. video: []
  2181. };
  2182. //主图
  2183. let arr1 = document.querySelectorAll('img[class*="-gallery-img"]');
  2184. for(let i=0; i< arr1.length; i++){
  2185. let srcUrl = arr1[i].src;
  2186. if(srcUrl.endsWith('_b.jpg')){
  2187. srcUrl = srcUrl.replace(/_b\.jpg$/, '');
  2188. }
  2189. if(!authority && i < execNum){
  2190. outObj.mainImg.push(srcUrl);
  2191. }
  2192. if(authority){
  2193. outObj.mainImg.push(srcUrl);
  2194. }
  2195. }
  2196. //sku图片
  2197. let type = 'bg';
  2198. let arr2 = document.querySelectorAll('.prop-img');
  2199. if(arr2.length == 0){
  2200. arr2 = document.querySelectorAll('.sku-item-image');
  2201. }
  2202. if(arr2.length == 0){
  2203. arr2 = document.querySelectorAll('.ant-image-img');
  2204. type = 'img';
  2205. }
  2206. for(let i=0; i< arr2.length; i++){
  2207. let src;
  2208. if(type == 'bg'){
  2209. src = window.getComputedStyle(arr2[i]).backgroundImage.replace(/url\(["']?(.+?)["']?\)/i, '$1');
  2210. }
  2211. if(type == 'img'){
  2212. src = arr2[i].src;
  2213. }
  2214. if(src.endsWith('_sum.jpg')){
  2215. src = src.replace(/_sum\.jpg$/, '');
  2216. }
  2217. if(!authority && i < execNum){
  2218. outObj.skuImg.push(src);
  2219. }
  2220. if(authority){
  2221. outObj.skuImg.push(src);
  2222. }
  2223. }
  2224. //详情图片
  2225. let arr3 = document.querySelectorAll('img.desc-img-loaded');
  2226. if(arr3.length == 0){
  2227. if(document.getElementById('description') && document.getElementById('description').querySelector('.html-description')){
  2228. arr3 = document.getElementById('description').querySelector('.html-description').shadowRoot.querySelectorAll('img');
  2229. }
  2230. }
  2231. for(let i=0; i< arr3.length; i++){
  2232. if(!authority && i < execNum){
  2233. outObj.detailImg.push(arr3[i].src);
  2234. }
  2235. if(authority){
  2236. outObj.detailImg.push(arr3[i].src);
  2237. }
  2238. }
  2239. // 视频
  2240. let arr5 = document.querySelectorAll('video');
  2241. for(let i=0; i< arr5.length; i++){
  2242. if(outObj.video.indexOf(arr5[i].src) == -1){
  2243. if(!authority && i < execNum){
  2244. outObj.video.push(arr5[i].src);
  2245. }
  2246. if(authority){
  2247. outObj.video.push(arr5[i].src);
  2248. }
  2249. }
  2250. }
  2251. return outObj;
  2252. }, authority, this.execNum);
  2253. // 主图下载
  2254. if(this.settingArr.indexOf('mainImg') > -1){
  2255. for(let j = 0; j < imgInfo.mainImg.length; j++){
  2256. let fileName = imgInfo.mainImg[j].split('/').pop();
  2257. if(fileName){
  2258. let queryIndex = fileName.indexOf('?');
  2259. if (queryIndex !== -1) {
  2260. fileName = fileName.substr(0, queryIndex);
  2261. }
  2262. let num = Number(j) + 1;
  2263. let suffix = '';
  2264. if(fileName.lastIndexOf('.') > -1){
  2265. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2266. }
  2267. if (!fs.existsSync(urlInfo.newPath + '\\主图')) {
  2268. fs.mkdirSync(urlInfo.newPath + '\\主图');
  2269. }
  2270. let outputPath = urlInfo.newPath + '\\主图\\主图' + num + suffix;
  2271. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  2272. }
  2273. }
  2274. }
  2275. // sku图片下载
  2276. if(this.settingArr.indexOf('skuImg') > -1){
  2277. for(let j = 0; j < imgInfo.skuImg.length; j++){
  2278. let fileName = imgInfo.skuImg[j].split('/').pop();
  2279. if(fileName){
  2280. let queryIndex = fileName.indexOf('?');
  2281. if (queryIndex !== -1) {
  2282. fileName = fileName.substr(0, queryIndex);
  2283. }
  2284. let num = Number(j) + 1;
  2285. let suffix = '';
  2286. if(fileName.lastIndexOf('.') > -1){
  2287. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2288. }
  2289. if (!fs.existsSync(urlInfo.newPath + '\\sku图')) {
  2290. fs.mkdirSync(urlInfo.newPath + '\\sku图');
  2291. }
  2292. let outputPath = urlInfo.newPath + '\\sku图\\sku图' + num + suffix;
  2293. await this.downloadImage(imgInfo.skuImg[j], outputPath, urlInfo);
  2294. }
  2295. }
  2296. }
  2297. //详情图下载
  2298. if(this.settingArr.indexOf('detailImg') > -1){
  2299. for(let j = 0; j < imgInfo.detailImg.length; j++){
  2300. let fileName = imgInfo.detailImg[j].split('/').pop();
  2301. if(fileName){
  2302. let queryIndex = fileName.indexOf('?');
  2303. if (queryIndex !== -1) {
  2304. fileName = fileName.substr(0, queryIndex);
  2305. }
  2306. let num = Number(j) + 1;
  2307. let suffix = '';
  2308. if(fileName.lastIndexOf('.') > -1){
  2309. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2310. }
  2311. if (!fs.existsSync(urlInfo.newPath + '\\详情图')) {
  2312. fs.mkdirSync(urlInfo.newPath + '\\详情图');
  2313. }
  2314. let outputPath = urlInfo.newPath + '\\详情图\\' + '详情图' + num + suffix;
  2315. await this.downloadImage(imgInfo.detailImg[j], outputPath, urlInfo);
  2316. }
  2317. }
  2318. }
  2319. //视频下载
  2320. if(this.settingArr.indexOf('video') > -1){
  2321. for(let j = 0; j < imgInfo.video.length; j++){
  2322. let fileName = imgInfo.video[j].split('/').pop();
  2323. if(fileName){
  2324. let queryIndex = fileName.indexOf('?');
  2325. if (queryIndex !== -1) {
  2326. fileName = fileName.substr(0, queryIndex);
  2327. }
  2328. if (!fs.existsSync(urlInfo.newPath + '\\视频')) {
  2329. fs.mkdirSync(urlInfo.newPath + '\\视频');
  2330. }
  2331. let outputPath = urlInfo.newPath + '\\视频\\' + fileName;
  2332. await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
  2333. }
  2334. }
  2335. }
  2336. await page.close(); // 关闭页面但不关闭浏览器
  2337. },
  2338. // 检查小红书登录状态
  2339. checkRedLogin(){
  2340. this.checkLoading = true;
  2341. this.redStatus = 1;
  2342. return new Promise((resolve, reject) => {
  2343. (async () => {
  2344. try{
  2345. if(this.loginBrowser){
  2346. await this.loginBrowser.close();
  2347. this.loginBrowser = null;
  2348. }
  2349. puppeteer.use(StealthPlugin());
  2350. this.loginBrowser = await puppeteer.launch({
  2351. executablePath: this.initPath(),
  2352. userDataDir: this.initDataDir(),
  2353. args: [
  2354. '--start-maximized',
  2355. '--no-sandbox',
  2356. '--disable-setuid-sandbox',
  2357. '--disable-blink-features=AutomationControlled',
  2358. '--window-size=1280,800'
  2359. ],
  2360. });
  2361. const page = await this.loginBrowser.newPage();
  2362. await page.setViewport({ width: 1280, height: 800 });
  2363. let testUrl = "https://www.xiaohongshu.com";
  2364. await page.goto(testUrl, {waitUntil : 'networkidle2'});
  2365. let loginBtn = await page.$$('#login-btn');
  2366. let loginContainer = await page.$$('.login-container');
  2367. if(loginContainer.length > 0 || loginBtn.length > 0){
  2368. this.redStatus = 3; //未登录
  2369. }else{
  2370. this.redStatus = 2;
  2371. }
  2372. resolve(this.redStatus);
  2373. this.checkLoading = false;
  2374. await this.loginBrowser.close();
  2375. this.loginBrowser = null;
  2376. }catch(e){
  2377. this.checkLoading = false;
  2378. reject(3);
  2379. this.showError(e);
  2380. }
  2381. })();
  2382. });
  2383. },
  2384. // 5-小红书下载
  2385. async redDownload(urlInfo, redBrowser){
  2386. let task = await new Promise((resolve,reject) =>{
  2387. (async () => {
  2388. try{
  2389. let authority = this.$refs.headerRef.authority.isAuthority;
  2390. let number = 0;
  2391. urlInfo.status = '2';
  2392. urlInfo.num = 0;
  2393. const page = await redBrowser.newPage();
  2394. let responseVideo = [];
  2395. page.on('response', async(response) => {
  2396. // 检查响应的 MIME 类型是否以 'video/' 开头
  2397. if (response.headers()['content-type'] && response.headers()['content-type'].startsWith('video/')) {
  2398. if(responseVideo.indexOf(response.url()) < 0 && !response.url().startsWith('blob:https://')){
  2399. responseVideo.push(response.url());
  2400. }
  2401. }
  2402. });
  2403. await page.goto(urlInfo.url, {waitUntil : 'networkidle2'});
  2404. if(urlInfo.title){
  2405. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
  2406. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  2407. } else {
  2408. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
  2409. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  2410. }
  2411. }else{
  2412. await this.getTitle(page, urlInfo); // 生成页面标题对应的文件夹
  2413. }
  2414. urlInfo.status = '3';
  2415. // 定位元素
  2416. const handle = await page.$$('.pagination-media-container .pagination-item');
  2417. if(handle.length > 0 && this.settingArr.indexOf('video') > -1){ // 模拟鼠标拖动 将鼠标移动到元素的中心,然后开始拖动
  2418. let handleLength = handle.length;
  2419. const box = await handle[0].boundingBox();
  2420. const boxEnd = await handle[handleLength - 1].boundingBox();
  2421. if(box && boxEnd){ //确保元素可见,防止报错
  2422. const center = {
  2423. x: box.x + box.width / 2,
  2424. y: box.y + box.height / 2
  2425. };
  2426. const centerEnd = {
  2427. x: boxEnd.x + boxEnd.width / 2,
  2428. y: boxEnd.y + boxEnd.height / 2
  2429. };
  2430. await page.mouse.move(center.x, center.y);
  2431. await page.mouse.down();
  2432. await page.mouse.move(centerEnd.x, centerEnd.y, { steps: 50 }); // 新的位置,可以根据需要调整步骤数
  2433. }
  2434. }
  2435. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  2436. const imgInfo = await page.evaluate((authority, execNum) => {
  2437. let outObj = {
  2438. mainImg: [],
  2439. detailImg: [],
  2440. skuImg: [],
  2441. commentImg: [],
  2442. video: []
  2443. };
  2444. // 正则表达式匹配字符 重写图片路径
  2445. let regex = /\.(.{3,4})_[0-9a-zA-z]+\.(.{3,4})_\.(.{3,4})/;
  2446. //主图
  2447. let arr1 = document.querySelectorAll('img[class^=note-slider-img]');
  2448. for(let i=0; i< arr1.length; i++){
  2449. let mainImgUrl = arr1[i].src;
  2450. let result = regex.exec(mainImgUrl);
  2451. if(result){
  2452. mainImgUrl = mainImgUrl.replace(result[0], '.'+result[1]);
  2453. }
  2454. if(!authority && i < execNum){
  2455. outObj.mainImg.push(mainImgUrl);
  2456. }
  2457. if(authority){
  2458. outObj.mainImg.push(mainImgUrl);
  2459. }
  2460. }
  2461. // 视频
  2462. let arr5 = document.querySelectorAll('video.lib-video');
  2463. for(let i=0; i< arr5.length; i++){
  2464. if(outObj.video.indexOf(arr5[i].src) == -1){
  2465. if(!authority && i < execNum){
  2466. outObj.video.push(arr5[i].src);
  2467. }
  2468. if(authority){
  2469. outObj.video.push(arr5[i].src);
  2470. }
  2471. }
  2472. }
  2473. return outObj;
  2474. }, authority, this.execNum);
  2475. if(imgInfo.mainImg.length >= 3 && authority){
  2476. imgInfo.mainImg = imgInfo.mainImg.slice(1, imgInfo.mainImg.length-1); //小红书轮播图第一个/最后一个和内容重复去掉
  2477. }
  2478. imgInfo.video = responseVideo;
  2479. if(this.settingArr.indexOf('mainImg') > -1){
  2480. // 主图下载
  2481. for(let j = 0; j < imgInfo.mainImg.length; j++){
  2482. let fileName = imgInfo.mainImg[j].split('/').pop();
  2483. if(fileName){
  2484. let queryIndex = fileName.indexOf('?');
  2485. if (queryIndex !== -1) {
  2486. fileName = fileName.substr(0, queryIndex);
  2487. }
  2488. let num = Number(j) + 1;
  2489. let suffix = '.jpg';
  2490. if(fileName.lastIndexOf('.') > -1){
  2491. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2492. }
  2493. let outputPath = urlInfo.newPath + '\\文章图' + num + suffix;
  2494. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  2495. }
  2496. }
  2497. }
  2498. if(this.settingArr.indexOf('video') > -1){
  2499. //视频下载
  2500. for(let j = 0; j < imgInfo.video.length; j++){
  2501. let fileName = imgInfo.video[j].split('/').pop();
  2502. if(fileName){
  2503. let queryIndex = fileName.indexOf('?');
  2504. if (queryIndex !== -1) {
  2505. fileName = fileName.substr(0, queryIndex);
  2506. }
  2507. let num = Number(j) + 1;
  2508. let suffix = '.mp4';
  2509. if(fileName.lastIndexOf('.') > -1){
  2510. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2511. }
  2512. let outputPath = urlInfo.newPath + '\\视频' + num + suffix;
  2513. await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
  2514. }
  2515. }
  2516. }
  2517. await page.close();
  2518. urlInfo.status = '4';
  2519. await this.delay();
  2520. resolve(true);
  2521. this.loading = false;
  2522. }catch(e){
  2523. urlInfo.status = '5';
  2524. reject(e);
  2525. this.showError(e);
  2526. }
  2527. })();
  2528. });
  2529. },
  2530. /**************************阿里国际商品图片下载*******************************************************************************************/
  2531. // 6 - 阿里国际 - 扫描并下载图片
  2532. async aliguojiScanImg(browser, page, urlInfo, authority){
  2533. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  2534. const imgInfo = await page.evaluate((authority, execNum) => {
  2535. let outObj = {
  2536. mainImg: [],
  2537. detailImg: [],
  2538. skuImg: [],
  2539. commentImg: [],
  2540. video: []
  2541. };
  2542. //主图
  2543. let arr1 = document.querySelectorAll('.module_productImage img');
  2544. for(let i=0; i< arr1.length; i++){
  2545. if(!authority && i < execNum){
  2546. outObj.mainImg.push(arr1[i].src);
  2547. }
  2548. if(authority){
  2549. outObj.mainImg.push(arr1[i].src);
  2550. }
  2551. }
  2552. //sku图片
  2553. let arr2 = document.querySelectorAll('.module_sku img[class*="-object-contain"]');
  2554. for(let i=0; i< arr2.length; i++){
  2555. if(!authority && i < execNum){
  2556. outObj.skuImg.push(arr2[i].src);
  2557. }
  2558. if(authority){
  2559. outObj.skuImg.push(arr2[i].src);
  2560. }
  2561. }
  2562. //详情图片
  2563. let arr3 = document.querySelectorAll('#description-layout img');
  2564. // if(arr3.length == 0){
  2565. // if(document.getElementById('description') && document.getElementById('description').querySelector('.html-description')){
  2566. // arr3 = document.getElementById('description').querySelector('.html-description').shadowRoot.querySelectorAll('img');
  2567. // }
  2568. // }
  2569. if(arr3.length == 0){
  2570. if(document.querySelector('#description-layout').querySelector('iframe')){
  2571. arr3 = document.querySelector('#description-layout').querySelector('iframe').contentDocument.querySelectorAll('img')
  2572. }
  2573. }
  2574. for(let i=0; i< arr3.length; i++){
  2575. if(!authority && i < execNum){
  2576. outObj.detailImg.push(arr3[i].src);
  2577. }
  2578. if(authority){
  2579. outObj.detailImg.push(arr3[i].src);
  2580. }
  2581. }
  2582. // 视频
  2583. let arr5 = document.querySelectorAll('video');
  2584. for(let i=0; i< arr5.length; i++){
  2585. if(arr5[i].src && outObj.video.indexOf(arr5[i].src) == -1){
  2586. if(!authority && i < execNum){
  2587. outObj.video.push(arr5[i].src);
  2588. }
  2589. if(authority){
  2590. outObj.video.push(arr5[i].src);
  2591. }
  2592. }
  2593. }
  2594. return outObj;
  2595. }, authority, this.execNum);
  2596. // 主图下载
  2597. if(this.settingArr.indexOf('mainImg') > -1){
  2598. for(let j = 0; j < imgInfo.mainImg.length; j++){
  2599. let fileName = imgInfo.mainImg[j].split('/').pop();
  2600. if(fileName){
  2601. let queryIndex = fileName.indexOf('?');
  2602. if (queryIndex !== -1) {
  2603. fileName = fileName.substr(0, queryIndex);
  2604. }
  2605. let num = Number(j) + 1;
  2606. let suffix = '';
  2607. if(fileName.lastIndexOf('.') > -1){
  2608. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2609. }
  2610. if (!fs.existsSync(urlInfo.newPath + '\\主图')) {
  2611. fs.mkdirSync(urlInfo.newPath + '\\主图');
  2612. }
  2613. let outputPath = urlInfo.newPath + '\\主图\\主图' + num + suffix;
  2614. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  2615. }
  2616. }
  2617. }
  2618. // sku图片下载
  2619. if(this.settingArr.indexOf('skuImg') > -1){
  2620. for(let j = 0; j < imgInfo.skuImg.length; j++){
  2621. let fileName = imgInfo.skuImg[j].split('/').pop();
  2622. if(fileName){
  2623. let queryIndex = fileName.indexOf('?');
  2624. if (queryIndex !== -1) {
  2625. fileName = fileName.substr(0, queryIndex);
  2626. }
  2627. let num = Number(j) + 1;
  2628. let suffix = '';
  2629. if(fileName.lastIndexOf('.') > -1){
  2630. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2631. }
  2632. if (!fs.existsSync(urlInfo.newPath + '\\sku图')) {
  2633. fs.mkdirSync(urlInfo.newPath + '\\sku图');
  2634. }
  2635. let outputPath = urlInfo.newPath + '\\sku图\\sku图' + num + suffix;
  2636. await this.downloadImage(imgInfo.skuImg[j], outputPath, urlInfo);
  2637. }
  2638. }
  2639. }
  2640. //详情图下载
  2641. if(this.settingArr.indexOf('detailImg') > -1){
  2642. for(let j = 0; j < imgInfo.detailImg.length; j++){
  2643. let fileName = imgInfo.detailImg[j].split('/').pop();
  2644. if(fileName){
  2645. let queryIndex = fileName.indexOf('?');
  2646. if (queryIndex !== -1) {
  2647. fileName = fileName.substr(0, queryIndex);
  2648. }
  2649. let num = Number(j) + 1;
  2650. let suffix = '';
  2651. if(fileName.lastIndexOf('.') > -1){
  2652. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2653. }
  2654. if (!fs.existsSync(urlInfo.newPath + '\\详情图')) {
  2655. fs.mkdirSync(urlInfo.newPath + '\\详情图');
  2656. }
  2657. let outputPath = urlInfo.newPath + '\\详情图\\' + '详情图' + num + suffix;
  2658. await this.downloadImage(imgInfo.detailImg[j], outputPath, urlInfo);
  2659. }
  2660. }
  2661. }
  2662. //视频下载
  2663. if(this.settingArr.indexOf('video') > -1){
  2664. for(let j = 0; j < imgInfo.video.length; j++){
  2665. let fileName = imgInfo.video[j].split('/').pop();
  2666. if(fileName){
  2667. let queryIndex = fileName.indexOf('?');
  2668. if (queryIndex !== -1) {
  2669. fileName = fileName.substr(0, queryIndex);
  2670. }
  2671. if (!fs.existsSync(urlInfo.newPath + '\\视频')) {
  2672. fs.mkdirSync(urlInfo.newPath + '\\视频');
  2673. }
  2674. let outputPath = urlInfo.newPath + '\\视频\\' + fileName;
  2675. await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
  2676. }
  2677. }
  2678. }
  2679. await page.close(); // 关闭页面但不关闭浏览器
  2680. },
  2681. /*********************************************************************************************************************/
  2682. /**************************百度爱采购商品图片下载*******************************************************************************************/
  2683. // 7 - 百度爱采购 - 扫描并下载图片
  2684. async acaigouScanImg(browser, page, urlInfo, authority){
  2685. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  2686. const imgInfo = await page.evaluate((authority, execNum) => {
  2687. let outObj = {
  2688. mainImg: [],
  2689. detailImg: [],
  2690. skuImg: [],
  2691. commentImg: [],
  2692. video: []
  2693. };
  2694. //主图
  2695. let arr1 = document.querySelectorAll('.album .img-container .img');
  2696. for(let i=0; i< arr1.length; i++){
  2697. let src = window.getComputedStyle(arr1[i]).backgroundImage.replace(/url\(["']?(.+?)["']?\)/i, '$1');
  2698. if(src && outObj.mainImg.indexOf(src) == -1){
  2699. if(!authority && i < execNum){
  2700. outObj.mainImg.push(src);
  2701. }
  2702. if(authority){
  2703. outObj.mainImg.push(src);
  2704. }
  2705. }
  2706. }
  2707. //sku图片
  2708. // let arr2 = document.querySelectorAll('.module_sku img[class*="-object-contain"]');
  2709. // for(let i=0; i< arr2.length; i++){
  2710. // if(!authority && i < execNum){
  2711. // outObj.skuImg.push(arr2[i].src);
  2712. // }
  2713. // if(authority){
  2714. // outObj.skuImg.push(arr2[i].src);
  2715. // }
  2716. // }
  2717. //详情图片
  2718. let arr3 = document.querySelectorAll('.details .questionable-detail img');
  2719. for(let i=0; i< arr3.length; i++){
  2720. if(!authority && i < execNum){
  2721. outObj.detailImg.push(arr3[i].src);
  2722. }
  2723. if(authority){
  2724. outObj.detailImg.push(arr3[i].src);
  2725. }
  2726. }
  2727. // 视频
  2728. let arr5 = document.querySelectorAll('.album video');
  2729. for(let i=0; i< arr5.length; i++){
  2730. if(arr5[i].src && outObj.video.indexOf(arr5[i].src) == -1){
  2731. if(!authority && i < execNum){
  2732. outObj.video.push(arr5[i].src);
  2733. }
  2734. if(authority){
  2735. outObj.video.push(arr5[i].src);
  2736. }
  2737. }
  2738. }
  2739. return outObj;
  2740. }, authority, this.execNum);
  2741. // 主图下载
  2742. if(this.settingArr.indexOf('mainImg') > -1){
  2743. for(let j = 0; j < imgInfo.mainImg.length; j++){
  2744. let fileName = imgInfo.mainImg[j].split('/').pop();
  2745. if(fileName){
  2746. let queryIndex = fileName.indexOf('?');
  2747. if (queryIndex !== -1) {
  2748. fileName = fileName.substr(0, queryIndex);
  2749. }
  2750. let num = Number(j) + 1;
  2751. let suffix = '.webp';
  2752. if(fileName.lastIndexOf('.') > -1){
  2753. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2754. }
  2755. if (!fs.existsSync(urlInfo.newPath + '\\主图')) {
  2756. fs.mkdirSync(urlInfo.newPath + '\\主图');
  2757. }
  2758. let outputPath = urlInfo.newPath + '\\主图\\主图' + num + suffix;
  2759. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  2760. }
  2761. }
  2762. }
  2763. // sku图片下载
  2764. if(this.settingArr.indexOf('skuImg') > -1){
  2765. for(let j = 0; j < imgInfo.skuImg.length; j++){
  2766. let fileName = imgInfo.skuImg[j].split('/').pop();
  2767. if(fileName){
  2768. let queryIndex = fileName.indexOf('?');
  2769. if (queryIndex !== -1) {
  2770. fileName = fileName.substr(0, queryIndex);
  2771. }
  2772. let num = Number(j) + 1;
  2773. let suffix = '';
  2774. if(fileName.lastIndexOf('.') > -1){
  2775. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2776. }
  2777. if (!fs.existsSync(urlInfo.newPath + '\\sku图')) {
  2778. fs.mkdirSync(urlInfo.newPath + '\\sku图');
  2779. }
  2780. let outputPath = urlInfo.newPath + '\\sku图\\sku图' + num + suffix;
  2781. await this.downloadImage(imgInfo.skuImg[j], outputPath, urlInfo);
  2782. }
  2783. }
  2784. }
  2785. //详情图下载
  2786. if(this.settingArr.indexOf('detailImg') > -1){
  2787. for(let j = 0; j < imgInfo.detailImg.length; j++){
  2788. let fileName = imgInfo.detailImg[j].split('/').pop();
  2789. if(fileName){
  2790. let queryIndex = fileName.indexOf('?');
  2791. if (queryIndex !== -1) {
  2792. fileName = fileName.substr(0, queryIndex);
  2793. }
  2794. let num = Number(j) + 1;
  2795. let suffix = '.webp';
  2796. if(fileName.lastIndexOf('.') > -1){
  2797. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2798. }
  2799. if (!fs.existsSync(urlInfo.newPath + '\\详情图')) {
  2800. fs.mkdirSync(urlInfo.newPath + '\\详情图');
  2801. }
  2802. let outputPath = urlInfo.newPath + '\\详情图\\' + '详情图' + num + suffix;
  2803. await this.downloadImage(imgInfo.detailImg[j], outputPath, urlInfo);
  2804. }
  2805. }
  2806. }
  2807. //视频下载
  2808. if(this.settingArr.indexOf('video') > -1){
  2809. for(let j = 0; j < imgInfo.video.length; j++){
  2810. let fileName = imgInfo.video[j].split('/').pop();
  2811. if(fileName){
  2812. let queryIndex = fileName.indexOf('?');
  2813. if (queryIndex !== -1) {
  2814. fileName = fileName.substr(0, queryIndex);
  2815. }
  2816. if (!fs.existsSync(urlInfo.newPath + '\\视频')) {
  2817. fs.mkdirSync(urlInfo.newPath + '\\视频');
  2818. }
  2819. let outputPath = urlInfo.newPath + '\\视频\\' + fileName;
  2820. await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
  2821. }
  2822. }
  2823. }
  2824. await page.close(); // 关闭页面但不关闭浏览器
  2825. },
  2826. /*********************************************************************************************************************/
  2827. /**************************亚马逊商品图片下载*******************************************************************************************/
  2828. // 8 - 亚马逊 - 扫描并下载图片
  2829. async amazonScanImg(browser, page, urlInfo, authority){
  2830. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  2831. const imgInfo = await page.evaluate((authority, execNum) => {
  2832. let outObj = {
  2833. mainImg: [],
  2834. detailImg: [],
  2835. skuImg: [],
  2836. commentImg: [],
  2837. video: []
  2838. };
  2839. //主图
  2840. let arr1 = document.querySelectorAll('#leftCol img.a-dynamic-image');
  2841. for(let i=0; i< arr1.length; i++){
  2842. if(!authority && i < execNum){
  2843. outObj.mainImg.push(arr1[i].src);
  2844. }
  2845. if(authority){
  2846. outObj.mainImg.push(arr1[i].src);
  2847. }
  2848. }
  2849. //sku图片
  2850. let arr2 = document.querySelectorAll('.module_sku img[class*="-object-contain"]');
  2851. for(let i=0; i< arr2.length; i++){
  2852. if(!authority && i < execNum){
  2853. outObj.skuImg.push(arr2[i].src);
  2854. }
  2855. if(authority){
  2856. outObj.skuImg.push(arr2[i].src);
  2857. }
  2858. }
  2859. //详情图片
  2860. let arr3 = document.querySelectorAll('#description-layout img');
  2861. // if(arr3.length == 0){
  2862. // if(document.getElementById('description') && document.getElementById('description').querySelector('.html-description')){
  2863. // arr3 = document.getElementById('description').querySelector('.html-description').shadowRoot.querySelectorAll('img');
  2864. // }
  2865. // }
  2866. for(let i=0; i< arr3.length; i++){
  2867. if(!authority && i < execNum){
  2868. outObj.detailImg.push(arr3[i].src);
  2869. }
  2870. if(authority){
  2871. outObj.detailImg.push(arr3[i].src);
  2872. }
  2873. }
  2874. // 视频
  2875. let arr5 = document.querySelectorAll('#description-layout video');
  2876. for(let i=0; i< arr5.length; i++){
  2877. if(arr5[i].src && outObj.video.indexOf(arr5[i].src) == -1){
  2878. if(!authority && i < execNum){
  2879. outObj.video.push(arr5[i].src);
  2880. }
  2881. if(authority){
  2882. outObj.video.push(arr5[i].src);
  2883. }
  2884. }
  2885. }
  2886. return outObj;
  2887. }, authority, this.execNum);
  2888. // 主图下载
  2889. if(this.settingArr.indexOf('mainImg') > -1){
  2890. for(let j = 0; j < imgInfo.mainImg.length; j++){
  2891. let fileName = imgInfo.mainImg[j].split('/').pop();
  2892. if(fileName){
  2893. let queryIndex = fileName.indexOf('?');
  2894. if (queryIndex !== -1) {
  2895. fileName = fileName.substr(0, queryIndex);
  2896. }
  2897. let num = Number(j) + 1;
  2898. let suffix = '';
  2899. if(fileName.lastIndexOf('.') > -1){
  2900. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2901. }
  2902. if (!fs.existsSync(urlInfo.newPath + '\\主图')) {
  2903. fs.mkdirSync(urlInfo.newPath + '\\主图');
  2904. }
  2905. let outputPath = urlInfo.newPath + '\\主图\\主图' + num + suffix;
  2906. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  2907. }
  2908. }
  2909. }
  2910. // sku图片下载
  2911. if(this.settingArr.indexOf('skuImg') > -1){
  2912. for(let j = 0; j < imgInfo.skuImg.length; j++){
  2913. let fileName = imgInfo.skuImg[j].split('/').pop();
  2914. if(fileName){
  2915. let queryIndex = fileName.indexOf('?');
  2916. if (queryIndex !== -1) {
  2917. fileName = fileName.substr(0, queryIndex);
  2918. }
  2919. let num = Number(j) + 1;
  2920. let suffix = '';
  2921. if(fileName.lastIndexOf('.') > -1){
  2922. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2923. }
  2924. if (!fs.existsSync(urlInfo.newPath + '\\sku图')) {
  2925. fs.mkdirSync(urlInfo.newPath + '\\sku图');
  2926. }
  2927. let outputPath = urlInfo.newPath + '\\sku图\\sku图' + num + suffix;
  2928. await this.downloadImage(imgInfo.skuImg[j], outputPath, urlInfo);
  2929. }
  2930. }
  2931. }
  2932. //详情图下载
  2933. if(this.settingArr.indexOf('detailImg') > -1){
  2934. for(let j = 0; j < imgInfo.detailImg.length; j++){
  2935. let fileName = imgInfo.detailImg[j].split('/').pop();
  2936. if(fileName){
  2937. let queryIndex = fileName.indexOf('?');
  2938. if (queryIndex !== -1) {
  2939. fileName = fileName.substr(0, queryIndex);
  2940. }
  2941. let num = Number(j) + 1;
  2942. let suffix = '';
  2943. if(fileName.lastIndexOf('.') > -1){
  2944. suffix = fileName.substr(fileName.lastIndexOf('.'));
  2945. }
  2946. if (!fs.existsSync(urlInfo.newPath + '\\详情图')) {
  2947. fs.mkdirSync(urlInfo.newPath + '\\详情图');
  2948. }
  2949. let outputPath = urlInfo.newPath + '\\详情图\\' + '详情图' + num + suffix;
  2950. await this.downloadImage(imgInfo.detailImg[j], outputPath, urlInfo);
  2951. }
  2952. }
  2953. }
  2954. //视频下载
  2955. if(this.settingArr.indexOf('video') > -1){
  2956. for(let j = 0; j < imgInfo.video.length; j++){
  2957. let fileName = imgInfo.video[j].split('/').pop();
  2958. if(fileName){
  2959. let queryIndex = fileName.indexOf('?');
  2960. if (queryIndex !== -1) {
  2961. fileName = fileName.substr(0, queryIndex);
  2962. }
  2963. if (!fs.existsSync(urlInfo.newPath + '\\视频')) {
  2964. fs.mkdirSync(urlInfo.newPath + '\\视频');
  2965. }
  2966. let outputPath = urlInfo.newPath + '\\视频\\' + fileName;
  2967. await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
  2968. }
  2969. }
  2970. }
  2971. await page.close(); // 关闭页面但不关闭浏览器
  2972. },
  2973. /*********************************************************************************************************************/
  2974. /***********拼多多商品下载**********/
  2975. // 检查pdd登录状态
  2976. checkPddLogin(){
  2977. this.checkLoading = true;
  2978. this.pddStatus = 1;
  2979. return new Promise((resolve, reject) => {
  2980. (async () => {
  2981. try{
  2982. if(this.loginBrowser){
  2983. await this.loginBrowser.close();
  2984. this.loginBrowser = null;
  2985. }
  2986. puppeteer.use(StealthPlugin());
  2987. this.loginBrowser = await puppeteer.launch({
  2988. executablePath: this.initPath(),
  2989. userDataDir: this.initDataDir(),
  2990. args: [
  2991. '--start-maximized',
  2992. '--no-sandbox',
  2993. '--disable-setuid-sandbox',
  2994. '--disable-blink-features=AutomationControlled',
  2995. '--window-size=1280,800'
  2996. ],
  2997. });
  2998. const page = await this.loginBrowser.newPage();
  2999. await page.setViewport({ width: 1280, height: 800 });
  3000. let testUrl = "https://mobile.yangkeduo.com/personal.html";
  3001. await page.goto(testUrl, {waitUntil : 'networkidle2'});
  3002. let loginBtn = await page.$('.login-box');
  3003. if(loginBtn){
  3004. let searchValue = await page.$eval('.login-box', el => el.innerText);
  3005. if(searchValue == '手机登录' || searchValue.indexOf('登录') > -1){
  3006. this.pddStatus = 3; //未登录
  3007. }else{
  3008. this.pddStatus = 2;
  3009. }
  3010. }else{
  3011. this.pddStatus = 2;
  3012. }
  3013. resolve(this.pddStatus);
  3014. this.checkLoading = false;
  3015. await this.loginBrowser.close();
  3016. this.loginBrowser = null;
  3017. }catch(e){
  3018. this.checkLoading = false;
  3019. reject(3);
  3020. this.showError(e);
  3021. }
  3022. })();
  3023. });
  3024. },
  3025. // 9-pdd图片下载
  3026. async pddDownload(urlInfo, pddBrowser){
  3027. let task = await new Promise((resolve,reject) =>{
  3028. (async () => {
  3029. try{
  3030. let authority = this.$refs.headerRef.authority.isAuthority;
  3031. let number = 0;
  3032. urlInfo.status = '2';
  3033. urlInfo.num = 0;
  3034. const page = await pddBrowser.newPage();
  3035. await page.goto(urlInfo.url, {waitUntil : 'networkidle2'});
  3036. if(urlInfo.title){
  3037. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
  3038. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  3039. } else {
  3040. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
  3041. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  3042. }
  3043. }else{
  3044. // 获取商品标题
  3045. let titleHandle = await page.$$('span.enable-select');
  3046. if(titleHandle && titleHandle.length > 0){
  3047. let titleValue = await page.$eval('span.enable-select', el => el.innerText);
  3048. await this.getTitle(page, urlInfo, titleValue); // 生成页面标题对应的文件夹
  3049. }else{
  3050. await this.getTitle(page, urlInfo, '拼多多商品-'+new Date().getTime()); // 生成页面标题对应的文件夹
  3051. }
  3052. }
  3053. urlInfo.status = '3';
  3054. // 被平台限制浏览
  3055. let notSale = await page.$$('.not-sale');
  3056. if(notSale && notSale.length > 0){
  3057. let notValue = await page.$eval('.not-sale', el => el.innerText);
  3058. if(notValue.indexOf('商品已售罄') > -1 || notValue.indexOf('推荐以下') > -1){
  3059. await page.close();
  3060. urlInfo.status = '7';
  3061. resolve(true);
  3062. this.loading = false;
  3063. return false;
  3064. }
  3065. }
  3066. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  3067. const imgInfo = await page.evaluate((authority, execNum) => {
  3068. let outObj = {
  3069. mainImg: [],
  3070. detailImg: [],
  3071. skuImg: [],
  3072. commentImg: [],
  3073. video: [],
  3074. skuName: []
  3075. };
  3076. let skuHandle = document.querySelector('div[class*=sku-plus] img');
  3077. if(skuHandle){
  3078. skuHandle.click({force: true});
  3079. }
  3080. //主图
  3081. let mainDiv = document.querySelectorAll('#main > div > div')[0];
  3082. let arr1 = mainDiv.querySelectorAll('img');
  3083. for(let i=0; i< arr1.length; i++){
  3084. // if(i > 0 && i < arr1.length-1){ // 去掉首尾重复
  3085. let mainImgUrl = arr1[i].src || arr1[i].dataset.src;
  3086. if(outObj.mainImg.indexOf(mainImgUrl) == -1){
  3087. if(!authority && i < execNum){
  3088. outObj.mainImg.push(mainImgUrl);
  3089. }
  3090. if(authority){
  3091. outObj.mainImg.push(mainImgUrl);
  3092. }
  3093. }
  3094. // }
  3095. }
  3096. //sku
  3097. let arr2 = document.querySelectorAll('#skuImageSlider img');
  3098. for(let i=0; i< arr2.length; i++){
  3099. //if(i > 0 && i < arr2.length-1){ // 去掉首尾重复 -去掉重复图片
  3100. let skuImgUrl = arr2[i].src || arr2[i].dataset.src;
  3101. if(outObj.skuImg.indexOf(skuImgUrl) == -1){
  3102. let nextEle = arr2[i].parentElement.nextElementSibling;
  3103. let num = Number(i) + 1;
  3104. let name = 'sku图' + num + '.jpeg';
  3105. if(nextEle){
  3106. name = nextEle.innerText.split('\n')[0];
  3107. name = name.replace(/[\\|/|:|*|?|"|<|>||]/g, "");
  3108. }
  3109. if(!authority && i < execNum){
  3110. outObj.skuImg.push(skuImgUrl);
  3111. outObj.skuName.push(name);
  3112. }
  3113. if(authority){
  3114. outObj.skuImg.push(skuImgUrl);
  3115. outObj.skuName.push(name);
  3116. }
  3117. }
  3118. //}
  3119. }
  3120. //详情图
  3121. let arr3 = document.querySelectorAll('img[class*=pdd-lazy-image][aria-label="查看图片"]');
  3122. if(arr3.length == 0){
  3123. arr3 = [];
  3124. let imgArr = document.querySelectorAll('img[class*=pdd-lazy-image]');
  3125. for(let m = 0; m < imgArr.length; m++){
  3126. if(imgArr[m].parentElement.ariaLabel == '点击查看大图'){
  3127. arr3.push(imgArr[m]);
  3128. }
  3129. }
  3130. }
  3131. for(let i=0; i< arr3.length; i++){
  3132. let detailImgUrl = arr3[i].src || arr3[i].dataset.src;
  3133. if(!authority && i < execNum){
  3134. outObj.detailImg.push(detailImgUrl);
  3135. }
  3136. if(authority){
  3137. outObj.detailImg.push(detailImgUrl);
  3138. }
  3139. }
  3140. // 视频
  3141. let arr5 = document.querySelectorAll('video');
  3142. for(let i=0; i< arr5.length; i++){
  3143. if(outObj.video.indexOf(arr5[i].src) == -1){
  3144. if(!authority && i < execNum){
  3145. outObj.video.push(arr5[i].src);
  3146. }
  3147. if(authority){
  3148. outObj.video.push(arr5[i].src);
  3149. }
  3150. }
  3151. }
  3152. return outObj;
  3153. }, authority, this.execNum);
  3154. // 主图下载
  3155. if(this.settingArr.indexOf('mainImg') > -1){
  3156. for(let j = 0; j < imgInfo.mainImg.length; j++){
  3157. let imgUrl = imgInfo.mainImg[j];
  3158. let queryIndex = imgInfo.mainImg[j].indexOf('?');
  3159. if (queryIndex !== -1) {
  3160. imgUrl = imgUrl.substr(0, queryIndex);
  3161. }
  3162. let fileName = imgUrl.split('/').pop();
  3163. let num = Number(j) + 1;
  3164. let suffix = '.jpg';
  3165. if(fileName.lastIndexOf('.') > -1){
  3166. suffix = fileName.substr(fileName.lastIndexOf('.'));
  3167. }
  3168. if (!fs.existsSync(urlInfo.newPath + '\\主图')) {
  3169. fs.mkdirSync(urlInfo.newPath + '\\主图');
  3170. }
  3171. let outputPath = urlInfo.newPath + '\\主图\\主图' + num + suffix;
  3172. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  3173. }
  3174. }
  3175. // sku图片下载
  3176. if(this.settingArr.indexOf('skuImg') > -1){
  3177. for(let j = 0; j < imgInfo.skuImg.length; j++){
  3178. let imgUrl = imgInfo.skuImg[j];
  3179. let queryIndex = imgInfo.skuImg[j].indexOf('?');
  3180. if (queryIndex !== -1) {
  3181. imgUrl = imgUrl.substr(0, queryIndex);
  3182. }
  3183. let fileName = imgUrl.split('/').pop();
  3184. let num = Number(j) + 1;
  3185. let suffix = '.jpg';
  3186. if(fileName.lastIndexOf('.') > -1){
  3187. suffix = fileName.substr(fileName.lastIndexOf('.'));
  3188. }
  3189. if (!fs.existsSync(urlInfo.newPath + '\\sku图')) {
  3190. fs.mkdirSync(urlInfo.newPath + '\\sku图');
  3191. }
  3192. let outputPath = urlInfo.newPath + '\\sku图\\' + imgInfo.skuName[j] + suffix;
  3193. await this.downloadImage(imgInfo.skuImg[j], outputPath, urlInfo);
  3194. }
  3195. }
  3196. //详情图下载
  3197. if(this.settingArr.indexOf('detailImg') > -1){
  3198. for(let j = 0; j < imgInfo.detailImg.length; j++){
  3199. let imgUrl = imgInfo.detailImg[j];
  3200. let queryIndex = imgInfo.detailImg[j].indexOf('?');
  3201. if (queryIndex !== -1) {
  3202. imgUrl = imgUrl.substr(0, queryIndex);
  3203. }
  3204. let fileName = imgUrl.split('/').pop();
  3205. let num = Number(j) + 1;
  3206. let suffix = '.jpg';
  3207. if(fileName.lastIndexOf('.') > -1){
  3208. suffix = fileName.substr(fileName.lastIndexOf('.'));
  3209. }
  3210. if (!fs.existsSync(urlInfo.newPath + '\\详情图')) {
  3211. fs.mkdirSync(urlInfo.newPath + '\\详情图');
  3212. }
  3213. let outputPath = urlInfo.newPath + '\\详情图\\详情图' + num + suffix;
  3214. await this.downloadImage(imgInfo.detailImg[j], outputPath, urlInfo);
  3215. }
  3216. }
  3217. //视频下载
  3218. if(this.settingArr.indexOf('video') > -1){
  3219. for(let j = 0; j < imgInfo.video.length; j++){
  3220. let fileName = imgInfo.video[j].split('/').pop();
  3221. if(fileName){
  3222. let queryIndex = fileName.indexOf('?');
  3223. if (queryIndex !== -1) {
  3224. fileName = fileName.substr(0, queryIndex);
  3225. }
  3226. if (!fs.existsSync(urlInfo.newPath + '\\视频')) {
  3227. fs.mkdirSync(urlInfo.newPath + '\\视频');
  3228. }
  3229. let outputPath = urlInfo.newPath + '\\视频\\' + fileName;
  3230. await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
  3231. }
  3232. }
  3233. }
  3234. await page.close();
  3235. urlInfo.status = '4';
  3236. await this.delay();
  3237. resolve(true);
  3238. this.loading = false;
  3239. }catch(e){
  3240. urlInfo.status = '5';
  3241. reject(e);
  3242. this.showError(e);
  3243. }
  3244. })();
  3245. });
  3246. },
  3247. // 10-闲鱼图片下载
  3248. async goofishDownload(urlInfo, pddBrowser){
  3249. let task = await new Promise((resolve,reject) =>{
  3250. (async () => {
  3251. try{
  3252. let authority = this.$refs.headerRef.authority.isAuthority;
  3253. let number = 0;
  3254. urlInfo.status = '2';
  3255. urlInfo.num = 0;
  3256. const page = await pddBrowser.newPage();
  3257. await page.goto(urlInfo.url, {waitUntil : 'networkidle2'});
  3258. if(urlInfo.title){
  3259. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
  3260. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  3261. } else {
  3262. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
  3263. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  3264. }
  3265. }else{
  3266. await this.getTitle(page, urlInfo); // 生成页面标题对应的文件夹
  3267. }
  3268. urlInfo.status = '3';
  3269. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  3270. const imgInfo = await page.evaluate((authority, execNum) => {
  3271. let outObj = {
  3272. mainImg: [],
  3273. detailImg: [],
  3274. skuImg: [],
  3275. commentImg: [],
  3276. video: [],
  3277. skuName: []
  3278. };
  3279. //主图
  3280. let arr1 = document.querySelectorAll('div[class^=carousel-container] img[class*=ant-image-img]')
  3281. for(let i=0; i< arr1.length; i++){
  3282. // if(i > 0 && i < arr1.length-1){ // 去掉首尾重复
  3283. let mainImgUrl = arr1[i].src || arr1[i].dataset.src;
  3284. if(outObj.mainImg.indexOf(mainImgUrl) == -1){
  3285. if(!authority && i < execNum){
  3286. outObj.mainImg.push(mainImgUrl);
  3287. }
  3288. if(authority){
  3289. outObj.mainImg.push(mainImgUrl);
  3290. }
  3291. }
  3292. // }
  3293. }
  3294. // 视频
  3295. let arr5 = document.querySelectorAll('video source');
  3296. if(arr5.length == 0){
  3297. arr5 = document.querySelectorAll('video');
  3298. }
  3299. for(let i=0; i< arr5.length; i++){
  3300. if(outObj.video.indexOf(arr5[i].src) == -1){
  3301. if(!authority && i < execNum){
  3302. outObj.video.push(arr5[i].src);
  3303. }
  3304. if(authority){
  3305. outObj.video.push(arr5[i].src);
  3306. }
  3307. }
  3308. }
  3309. return outObj;
  3310. }, authority, this.execNum);
  3311. // 主图下载
  3312. if(this.settingArr.indexOf('mainImg') > -1){
  3313. for(let j = 0; j < imgInfo.mainImg.length; j++){
  3314. let imgUrl = imgInfo.mainImg[j];
  3315. let queryIndex = imgInfo.mainImg[j].indexOf('?');
  3316. if (queryIndex !== -1) {
  3317. imgUrl = imgUrl.substr(0, queryIndex);
  3318. }
  3319. let fileName = imgUrl.split('/').pop();
  3320. let num = Number(j) + 1;
  3321. let suffix = '.jpg';
  3322. if(fileName.lastIndexOf('.') > -1){
  3323. suffix = fileName.substr(fileName.lastIndexOf('.'));
  3324. }
  3325. if(suffix == '.webp'){
  3326. suffix = '.jpg';
  3327. }
  3328. if (!fs.existsSync(urlInfo.newPath + '\\主图')) {
  3329. fs.mkdirSync(urlInfo.newPath + '\\主图');
  3330. }
  3331. let outputPath = urlInfo.newPath + '\\主图\\主图' + num + suffix;
  3332. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  3333. }
  3334. }
  3335. //视频下载
  3336. if(this.settingArr.indexOf('video') > -1){
  3337. for(let j = 0; j < imgInfo.video.length; j++){
  3338. let fileName = imgInfo.video[j].split('/').pop();
  3339. if(fileName){
  3340. let queryIndex = fileName.indexOf('?');
  3341. if (queryIndex !== -1) {
  3342. fileName = fileName.substr(0, queryIndex);
  3343. }
  3344. if (!fs.existsSync(urlInfo.newPath + '\\视频')) {
  3345. fs.mkdirSync(urlInfo.newPath + '\\视频');
  3346. }
  3347. let outputPath = urlInfo.newPath + '\\视频\\' + fileName + '.mp4';
  3348. await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
  3349. }
  3350. }
  3351. }
  3352. await page.close();
  3353. urlInfo.status = '4';
  3354. await this.delay();
  3355. resolve(true);
  3356. this.loading = false;
  3357. }catch(e){
  3358. urlInfo.status = '5';
  3359. reject(e);
  3360. this.showError(e);
  3361. }
  3362. })();
  3363. });
  3364. },
  3365. // 12-抖店图片下载
  3366. async dyDownload(urlInfo, pddBrowser){
  3367. let task = await new Promise((resolve,reject) =>{
  3368. (async () => {
  3369. try{
  3370. let authority = this.$refs.headerRef.authority.isAuthority;
  3371. let number = 0;
  3372. urlInfo.status = '2';
  3373. urlInfo.num = 0;
  3374. const page = await pddBrowser.newPage();
  3375. await page.goto(urlInfo.url, {waitUntil : 'networkidle2'});
  3376. if(urlInfo.title){
  3377. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
  3378. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  3379. } else {
  3380. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
  3381. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
  3382. }
  3383. }else{
  3384. // 获取商品标题
  3385. let titleHandle = await page.$$('div.title-info');
  3386. if(titleHandle && titleHandle.length > 0){
  3387. let titleValue = await page.$eval('div.title-info', el => el.innerText);
  3388. await this.getTitle(page, urlInfo, titleValue); // 生成页面标题对应的文件夹
  3389. }else{
  3390. await this.getTitle(page, urlInfo, '抖店商品-'+new Date().getTime()); // 生成页面标题对应的文件夹
  3391. }
  3392. }
  3393. urlInfo.status = '3';
  3394. // 被限制验证码拦截
  3395. let notSale = await page.$$('#captcha_container');
  3396. if(notSale && notSale.length > 0){
  3397. await page.close();
  3398. urlInfo.status = '6';
  3399. resolve(true);
  3400. this.loading = false;
  3401. return false;
  3402. }
  3403. //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
  3404. const imgInfo = await page.evaluate((authority, execNum) => {
  3405. let outObj = {
  3406. mainImg: [],
  3407. detailImg: [],
  3408. skuImg: [],
  3409. commentImg: [],
  3410. video: [],
  3411. skuName: []
  3412. };
  3413. let skuHandle = document.querySelector('img[class*=video__play-icon]');
  3414. if(skuHandle){
  3415. skuHandle.click({force: true});
  3416. }
  3417. //主图
  3418. let arr1 = document.querySelectorAll('div[class*=swiper-slide] div');
  3419. if(arr1.length == 0){
  3420. arr1 = document.querySelectorAll('div[class^=head-figure__media-view]');
  3421. }
  3422. for(let i=0; i< arr1.length; i++){
  3423. let mainImgUrl = window.getComputedStyle(arr1[i]).backgroundImage.replace(/url\(["']?(.+?)["']?\)/i, '$1');
  3424. if(outObj.mainImg.indexOf(mainImgUrl) == -1){
  3425. if(!authority && i < execNum){
  3426. outObj.mainImg.push(mainImgUrl);
  3427. }
  3428. if(authority){
  3429. outObj.mainImg.push(mainImgUrl);
  3430. }
  3431. }
  3432. }
  3433. //详情图
  3434. let arr3 = document.querySelectorAll('div[class=product-big-img-list] img');
  3435. if(arr3.length == 0){
  3436. arr3 = document.querySelectorAll('div[class=partial-detail-wrapper] img');
  3437. if(arr3.length == 0){
  3438. arr3 = document.querySelectorAll('img[class^=product-big-img-list]');
  3439. }
  3440. }
  3441. for(let i=0; i< arr3.length; i++){
  3442. let detailImgUrl = arr3[i].src || arr3[i].dataset.src;
  3443. if(!authority && i < execNum){
  3444. outObj.detailImg.push(detailImgUrl);
  3445. }
  3446. if(authority){
  3447. outObj.detailImg.push(detailImgUrl);
  3448. }
  3449. }
  3450. // 视频
  3451. let arr5 = document.querySelectorAll('video');
  3452. for(let i=0; i< arr5.length; i++){
  3453. if(outObj.video.indexOf(arr5[i].src) == -1){
  3454. if(!authority && i < execNum){
  3455. outObj.video.push(arr5[i].src);
  3456. }
  3457. if(authority){
  3458. outObj.video.push(arr5[i].src);
  3459. }
  3460. }
  3461. }
  3462. return outObj;
  3463. }, authority, this.execNum);
  3464. // 主图下载
  3465. if(this.settingArr.indexOf('mainImg') > -1){
  3466. for(let j = 0; j < imgInfo.mainImg.length; j++){
  3467. let imgUrl = imgInfo.mainImg[j];
  3468. let queryIndex = imgInfo.mainImg[j].indexOf('?');
  3469. if (queryIndex !== -1) {
  3470. imgUrl = imgUrl.substr(0, queryIndex);
  3471. }
  3472. let fileName = imgUrl.split('/').pop();
  3473. let num = Number(j) + 1;
  3474. let suffix = '.jpg';
  3475. if(fileName.lastIndexOf('.') > -1){
  3476. suffix = fileName.substr(fileName.lastIndexOf('.'));
  3477. }
  3478. if(suffix == '.webp'){
  3479. suffix = '.jpg';
  3480. }
  3481. if (!fs.existsSync(urlInfo.newPath + '\\主图')) {
  3482. fs.mkdirSync(urlInfo.newPath + '\\主图');
  3483. }
  3484. let outputPath = urlInfo.newPath + '\\主图\\主图' + num + suffix;
  3485. await this.downloadImage(imgInfo.mainImg[j], outputPath, urlInfo);
  3486. }
  3487. }
  3488. //详情图下载
  3489. if(this.settingArr.indexOf('detailImg') > -1){
  3490. for(let j = 0; j < imgInfo.detailImg.length; j++){
  3491. let imgUrl = imgInfo.detailImg[j];
  3492. let queryIndex = imgInfo.detailImg[j].indexOf('?');
  3493. if (queryIndex !== -1) {
  3494. imgUrl = imgUrl.substr(0, queryIndex);
  3495. }
  3496. let fileName = imgUrl.split('/').pop();
  3497. let num = Number(j) + 1;
  3498. let suffix = '.jpg';
  3499. if(fileName.lastIndexOf('.') > -1){
  3500. suffix = fileName.substr(fileName.lastIndexOf('.'));
  3501. }
  3502. if (!fs.existsSync(urlInfo.newPath + '\\详情图')) {
  3503. fs.mkdirSync(urlInfo.newPath + '\\详情图');
  3504. }
  3505. let outputPath = urlInfo.newPath + '\\详情图\\详情图' + num + suffix;
  3506. await this.downloadImage(imgInfo.detailImg[j], outputPath, urlInfo);
  3507. }
  3508. }
  3509. //视频下载
  3510. if(this.settingArr.indexOf('video') > -1){
  3511. for(let j = 0; j < imgInfo.video.length; j++){
  3512. let fileName = imgInfo.video[j].split('/').pop();
  3513. if(fileName){
  3514. if (!fs.existsSync(urlInfo.newPath + '\\视频')) {
  3515. fs.mkdirSync(urlInfo.newPath + '\\视频');
  3516. }
  3517. let outputPath = urlInfo.newPath + '\\视频\\视频.mp4' ;
  3518. await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
  3519. }
  3520. }
  3521. }
  3522. await page.close();
  3523. urlInfo.status = '4';
  3524. await this.delay();
  3525. resolve(true);
  3526. this.loading = false;
  3527. }catch(e){
  3528. urlInfo.status = '5';
  3529. reject(e);
  3530. this.showError(e);
  3531. }
  3532. })();
  3533. });
  3534. },
  3535. //
  3536. downloadExample(){
  3537. let url = 'https://www.xingyousoft.com/soft/XYCapture/example.xlsx';
  3538. if (!fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName)) {
  3539. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName);
  3540. }
  3541. let path = this.downloadDir + separator + pjson.softInfo.softName + '\\链接模板下载.xlsx';
  3542. this.downloadImage(url, path, 'example');
  3543. },
  3544. // 下载网址链接的图片
  3545. async downloadImage(imageUrl, outputPath, urlInfo) {
  3546. let _this = this;
  3547. let received_bytes = 0;
  3548. let total_bytes = 0;
  3549. try {
  3550. let req = request({
  3551. method: 'GET', uri: imageUrl, strictSSL: false
  3552. });
  3553. let out = fs.createWriteStream(outputPath);
  3554. req.pipe(out);
  3555. return new Promise((resolve, reject) => {
  3556. req.on('response', (data) => {
  3557. total_bytes = parseInt(data.headers['content-length']);
  3558. const status = data.statusCode;
  3559. if (status < 200 || status >= 300) {
  3560. //reject(false);
  3561. this.$notify.error({
  3562. title: '网络图片访问异常!- 1',
  3563. message: imageUrl.slice(0,50)
  3564. });
  3565. }else if(isNaN(total_bytes)){
  3566. //reject(false);
  3567. this.$notify.error({
  3568. title: '网络图片访问异常!- 2',
  3569. message: imageUrl.slice(0,50)
  3570. });
  3571. }else{
  3572. // console.log('下载中...')
  3573. }
  3574. });
  3575. req.on('data', (chunk) => {
  3576. received_bytes += chunk.length;
  3577. });
  3578. req.on('end', ()=> {
  3579. if(urlInfo != 'example'){
  3580. if(total_bytes < 1024 && outputPath.indexOf('评论图') > -1){
  3581. if (fs.existsSync(outputPath)) {
  3582. fs.unlinkSync(outputPath);
  3583. }
  3584. }else{
  3585. urlInfo.num += 1;
  3586. }
  3587. }else{
  3588. this.$msgbox({
  3589. title: '消息',
  3590. message: '模板下载成功,保存位置:' + this.downloadDir + separator + pjson.softInfo.softName,
  3591. showCancelButton: true,
  3592. confirmButtonText: '去查看',
  3593. cancelButtonText: '取消',
  3594. }).then(action => {
  3595. this.openFolder();
  3596. }).catch(action => {
  3597. });
  3598. }
  3599. //console.log('下载完成', outputPath)
  3600. resolve(true);
  3601. });
  3602. });
  3603. } catch (error) {
  3604. console.error(imageUrl, `Failed to download image: ${error.message}`);
  3605. throw error;
  3606. }
  3607. },
  3608. // 获取页面标题 - 生成对应的文件夹
  3609. async getTitle(page, urlInfo, tagStr){
  3610. // 已页面标题作为新建文件夹,保留前50个字
  3611. let title = await page.title();
  3612. if(!title){
  3613. title = '无标题-'+new Date().getTime();
  3614. }
  3615. if(tagStr){
  3616. title = tagStr.replace(/\.\.\./g, '');
  3617. }
  3618. if(title){
  3619. title = title.substring(0, 50).trim();
  3620. if(this.containsAnyChar(title, ['\\', '/', ':', '*', '?', '"', '<', '>', '|', '.'])){ //判断是否含有特殊字符
  3621. title = title.replace(/[\\|/|:|*|?|.|"|<|>||]/g, "");
  3622. }
  3623. if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + title)) {
  3624. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + title;
  3625. } else {
  3626. fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + title);
  3627. urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + title;
  3628. }
  3629. }
  3630. },
  3631. // 下载base64位的图片
  3632. async downloadBaseImage(base64String, outputPath, urlInfo) {
  3633. const buffer = Buffer.from(base64String, 'base64');
  3634. const writeStream = fs.createWriteStream(outputPath);
  3635. writeStream.write(buffer);
  3636. writeStream.end();
  3637. writeStream.on('finish', () => {
  3638. urlInfo.num += 1;
  3639. });
  3640. // 监听错误事件
  3641. writeStream.on('error', (err) => {
  3642. console.error('base64位写入文件时出错:', err);
  3643. });
  3644. },
  3645. // 错误提示
  3646. showError(e){
  3647. let str = '';
  3648. if(e.toString().indexOf('ERR_NAME_NOT_RESOLVE') > -1){
  3649. str = '无法解析该网址,请查看网址是否正确!-1';
  3650. }else if(e.toString().indexOf('Cannot navigate to invalid URL') > -1){
  3651. str = '无效的网址,请查看网址格式是否正确!-2';
  3652. }else if(e.toString().indexOf('ERR_CONNECTION_TIMED_OUT') > -1){
  3653. str = '链接请求超时,请查看网络状态!-3';
  3654. }else if(e.toString().indexOf('TimeoutError') > -1){
  3655. str = '链接请求超时,请查看网络状态!-4';
  3656. }else if(e.toString().indexOf('operation not permitted') > -1){
  3657. str = '权限受限,请以管理员权限运行软件!-5';
  3658. }else if(e.toString().indexOf('browser has disconnected') > -1){
  3659. str = '浏览器已关闭!-6';
  3660. }else if(e.toString().indexOf('Failed to launch the browser') > -1){
  3661. str = '浏览器启动失败,请查看设置是否正确或重启电脑后重试!-7';
  3662. }else{
  3663. str = e.toString();
  3664. //console.log(e);
  3665. }
  3666. this.loading = false;
  3667. this.$notify.error({
  3668. title: '提示',
  3669. message: str
  3670. });
  3671. },
  3672. // 是否包含特殊字符
  3673. containsAnyChar(str, charsArray) {
  3674. for (let i = 0; i < charsArray.length; i++) {
  3675. if (str.includes(charsArray[i])) {
  3676. return true;
  3677. }
  3678. }
  3679. return false;
  3680. },
  3681. // 随机生成字符
  3682. randomString(length) {
  3683. let result = '';
  3684. const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  3685. const charactersLength = characters.length;
  3686. for (let i = 0; i < length; i++ ) {
  3687. result += characters.charAt(Math.floor(Math.random() * charactersLength));
  3688. }
  3689. return result;
  3690. }
  3691. }
  3692. };
  3693. </script>
  3694. <style lang="scss">
  3695. @import "../assets/css/fontx/iconfont.css";
  3696. @import "../assets/css/home.scss";
  3697. .ivu-input-number-controls-outside-btn i {
  3698. font-weight: 800;
  3699. }
  3700. .update-point {
  3701. display: inline-block;
  3702. width: 8px;
  3703. height: 8px;
  3704. border-radius: 8px;
  3705. background: #ff0000;
  3706. top: 14px;
  3707. position: absolute;
  3708. left: -13px;
  3709. }
  3710. .menu-item {
  3711. padding: 8px 0;
  3712. font-size: 14px;
  3713. .iconfont {
  3714. font-size: 32px;
  3715. }
  3716. &:hover,
  3717. &.active {
  3718. color: #ed4014;
  3719. }
  3720. }
  3721. .ivu-progress-show-info .ivu-progress-outer {
  3722. padding-right: 40px !important;
  3723. margin-right: -40px !important;
  3724. }
  3725. .tips {
  3726. text-align: center;
  3727. padding: 10px 0;
  3728. color: #ed4014;
  3729. font-size: 12px;
  3730. }
  3731. .handle-desc {
  3732. display: inline-block;
  3733. width: calc(100% - 100px);
  3734. overflow: hidden;
  3735. }
  3736. .ivu-menu-submenu-title {
  3737. font-weight: 600;
  3738. }
  3739. .ivu-menu .ivu-menu-item {
  3740. line-height: 1;
  3741. }
  3742. // new-el
  3743. .el-menu {
  3744. border-right: none !important;
  3745. }
  3746. .cmenu-item {
  3747. padding: 0 20px 20px;
  3748. margin-bottom: 15px;
  3749. .cmenu-title {
  3750. font-size: 18px;
  3751. font-weight: 600;
  3752. padding-bottom: 20px;
  3753. }
  3754. .citem-nav {
  3755. text-align: center;
  3756. border-radius: 10px;
  3757. min-height: 110px;
  3758. padding: 15px 0;
  3759. background-color: #fff;
  3760. font-size: 15px;
  3761. cursor: pointer;
  3762. &.bg-linear1 {
  3763. color: #fff;
  3764. font-size: 20px;
  3765. background: linear-gradient(to right bottom, #2A56CA, #5795F4);
  3766. }
  3767. &.bg-linear2 {
  3768. color: #fff;
  3769. font-size: 20px;
  3770. background: linear-gradient(to right top, #147FBB, #5EB3E3);
  3771. }
  3772. &.bg-linear3 {
  3773. color: #fff;
  3774. font-size: 20px;
  3775. background: linear-gradient(to right bottom, #2F9E8A, #56CDB1);
  3776. }
  3777. &:hover {
  3778. margin-top: -5px;
  3779. box-shadow: 3px 3px 6px #ccc, -3px -3px 6px #ccc;
  3780. }
  3781. .citem-img {
  3782. width: 50px;
  3783. margin-bottom: 10px;
  3784. }
  3785. }
  3786. }
  3787. .popper-open{
  3788. text-align: center !important;
  3789. padding: 10px !important;
  3790. background: #303133 !important;
  3791. color: #fff !important;
  3792. min-width: 120px !important;
  3793. opacity: 0.8;
  3794. }
  3795. .popper-open[x-placement^=bottom] .popper__arrow::after{
  3796. border-bottom-color: #303133 !important;
  3797. }
  3798. textarea.el-textarea__inner{
  3799. height: 100% !important;
  3800. font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
  3801. }
  3802. .set-item{
  3803. margin-right: 15px;
  3804. .set-title{
  3805. font-size: 13px;
  3806. }
  3807. }
  3808. .outarea{
  3809. height: 100%;
  3810. border: 1px solid #DCDFE6;
  3811. background-color: #4851a415;
  3812. padding: 15px;
  3813. font-size: 20px;
  3814. overflow: hidden auto;
  3815. }
  3816. .outtext{
  3817. height: 100%;
  3818. font-size: 20px;
  3819. overflow: hidden auto;
  3820. textarea{
  3821. background-color: #4851a415;
  3822. }
  3823. }
  3824. .pin-tips{
  3825. font-size: 14px;
  3826. position: absolute;
  3827. bottom: 10px;
  3828. color: #ff0000;
  3829. left: 0;
  3830. right: 0;
  3831. margin: auto;
  3832. text-align: center;
  3833. }
  3834. .outarea.red-border{
  3835. border: 1px solid #F56C6C;
  3836. }
  3837. .outtext.red-border textarea{
  3838. border: 1px solid #F56C6C;
  3839. }
  3840. h3{
  3841. margin: 0;
  3842. }
  3843. .m-image{
  3844. width: 20px;
  3845. margin-right: 5px;
  3846. }
  3847. .dialog-footer-center{
  3848. text-align: center;
  3849. }
  3850. .visible-tips-style{
  3851. font-size: 18px;
  3852. color: #f73131;
  3853. font-weight: 600;
  3854. padding: 30px 40px 0;
  3855. }
  3856. .no-select{
  3857. user-select: none;
  3858. }
  3859. .tips-flex{
  3860. display: flex;
  3861. flex-wrap: nowrap;
  3862. justify-content: space-around;
  3863. align-items: center;
  3864. .el-icon-s-opportunity{
  3865. font-size: 50px;
  3866. color: #f73131;
  3867. margin-right: 10px;
  3868. }
  3869. .m-title{
  3870. flex: 1;
  3871. color: #f73131;
  3872. }
  3873. }
  3874. .el-menu-item{
  3875. height: 45px !important;
  3876. line-height: 45px !important;
  3877. }
  3878. </style>