utiller 1.0.430 → 1.0.432
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/spider/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty")),_index=require("../index.js");class Spider{constructor(e,{visible:t=!1,host:
|
|
1
|
+
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty")),_index=require("../index.js");class Spider{constructor(e,{visible:t=!1,host:o=""}){(0,_defineProperty2.default)(this,"browser",null),(0,_defineProperty2.default)(this,"puppeteer",void 0),(0,_defineProperty2.default)(this,"visible",!0),(0,_defineProperty2.default)(this,"getBrowser",async()=>{const e=await this.puppeteer.launch({headless:!this.visible});for(const t of await e.pages())await t.close();return e}),(0,_defineProperty2.default)(this,"initial",async()=>{this.browser=await this.getBrowser()}),(0,_defineProperty2.default)(this,"getContextPage",async({browser:e=this.browser,type:t="desktop",incognito:o=!1,href:a="",timeout:i=0})=>{let n,r;return o?(console.log(`開啟了無痕視窗 => ${a}`),r=await e.createBrowserContext(),n=await r.newPage()):n=await e.newPage(),this.randomViewport({page:n,type:t}),_index.utiller.isUndefinedNullEmpty(a)||await n.goto(a,{waitUntil:"networkidle2",timeout:i}),{context:r,page:n}}),(0,_defineProperty2.default)(this,"randomViewport",({page:e,type:t="desktop"})=>{const o=_index.utiller.getRandomValue(1080,1920),a=_index.utiller.getRandomValue(1080,1920);e.setViewport({width:o,height:a})}),(0,_defineProperty2.default)(this,"activateContextPage",async({browser:e=this.browser,type:t="desktop",timeout:o=0})=>this.getContextPage({browser:e,type:t,timeout:o})),(0,_defineProperty2.default)(this,"activatePage4Load",async({browser:e=this.browser,href:t="",type:o="desktop",timeout:a=0,incognito:i=!1})=>this.getContextPage({browser:e,href:t,type:o,timeout:a,incognito:i})),(0,_defineProperty2.default)(this,"activatePage4Task",async({browser:e=this.browser,href:t="",type:o="desktop",timeout:a=0,task:i=async e=>!0,incognito:n=!1})=>{const r=await this.activatePage4Load({browser:e,href:t,type:o,timeout:a,incognito:n}),s=await i(r.page);return await this.close(r),s}),(0,_defineProperty2.default)(this,"clickNextPageTilEnd",async({page:e,selector:t=".pagination-container .pagination > *",sign:o="»"})=>{try{const a=await e.$$(t);if(!a||0===a.length)return console.log("⚠️ 找不到頁面按鈕們"),!1;console.log(`📍 找到 ${a.length} 個頁面按鈕`);let i=null;for(const e of[...a].reverse())if(await this.fetchAttributeOfEl(e,await this.isElementTagBy(e,"a")?"":"a","innerText")===o){i=e;break}return i?(console.log("✅ 找到下一頁按鈕"),await i.evaluate(e=>e.disabled||e.classList.contains("disabled"))?(console.log("⚠️ 下一頁按鈕已禁用 (已是最後一頁)"),!1):(console.log("🖱️ 點擊下一頁按鈕..."),await i.click(),await e.waitForNavigation({waitUntil:"networkidle2",timeout:0}).catch(()=>{}),console.log("✅ 成功翻到下一頁"),!0)):(console.log("⚠️ 找不到下一頁按鈕 (»)"),!1)}catch(e){return console.log(`❌ 點擊下一頁出錯: ${e.message}`),!1}}),(0,_defineProperty2.default)(this,"fetchAttributesOfEl",async(e,t,o)=>{let a;if(t&&""!==t.trim()){if(a=await e.$(t),!a)return console.warn(`⚠️ 找不到元素: ${t}`),{}}else a=e;const i={},n={};for(const[e,t]of Object.entries(o)){if("object"==typeof t&&null!==t&&!Array.isArray(t)){Object.assign(n,t);continue}const o=String(t);if(o.startsWith("$$$")){const t=o.substring(3),a=parseFloat(t);isNaN(a)?(console.warn(`⚠️ 無法解析數字: ${o}`),n[e]=void 0):n[e]=a;continue}if(o.startsWith("###")){const t=o.substring(3);n[e]=t;continue}if(o.startsWith("@@@")){const t=o.substring(3).toLowerCase().trim();let a;"true"===t||"1"===t||"yes"===t||"y"===t||"on"===t?a=!0:("false"===t||"0"===t||"no"===t||"n"===t||"off"===t||""===t||console.warn(`⚠️ 無法解析布林值: ${o},默認為 false`),a=!1),n[e]=a;continue}i[e]=t}const r=await a.evaluate((e,t)=>{const o={};for(const[a,i]of Object.entries(t)){const t=void 0!==e[i]?e[i]:e.getAttribute(i);o[a]=null!==t?t:void 0}return o},i);return{...r,...n}}),(0,_defineProperty2.default)(this,"fetchAttributeOfEl",async(e,t,o)=>{let a;if(t&&""!==t.trim()){if(a=await e.$(t),!a)return void console.warn(`⚠️ 找不到元素: ${t}`)}else a=e;return await a.evaluate((e,t)=>{const o=void 0!==e[t]?e[t]:e.getAttribute(t);return null!==o?o:void 0},o)}),(0,_defineProperty2.default)(this,"isElementTagBy",async(e,t)=>await e.evaluate((e,t)=>e.tagName.toLowerCase()===t.toLowerCase(),t)),(0,_defineProperty2.default)(this,"waitForLoadingToVanish",async(e,t,o=1e4)=>{if(!t)return!0;try{return await e.waitForSelector(t,{hidden:!0,timeout:o}),!0}catch(e){return console.warn(`警告: Loading Bar ${t} 在 ${o}ms 內未消失,將強制繼續執行。`),!1}}),(0,_defineProperty2.default)(this,"scrollToBottomAndCheck",async(e,{minDelay:t=2e3,maxRetries:o=3,loadingSelector:a=null,loadingTimeout:i=6e3}={})=>{console.log("🚀 開始執行智能滾動檢查...");let n=await e.evaluate(()=>document.body.scrollHeight),r=0;for(;;){await e.evaluate(()=>window.scrollTo(0,document.body.scrollHeight)),await new Promise(e=>setTimeout(e,t)),a&&await this.waitForLoadingToVanish(e,a,i);let s=await e.evaluate(()=>document.body.scrollHeight);if(s===n){if(r++,r>=o){console.log(`✅ 連續 ${o} 次未檢測到新內容,判定已到達最底部。`);break}console.log(`🔄 高度未變化,正在重試等待... (${r}/${o})`),await new Promise(e=>setTimeout(e,1e3))}else console.log(`⬇️ 檢測到新內容 (高度: ${n} -> ${s}),繼續滾動...`),n=s,r=0}}),(0,_defineProperty2.default)(this,"getSelectorRoute",async(e,t)=>await e.evaluate(e=>(e=>{if(e.id)return`#${e.id}`;let t=[];for(;e.parentElement;){let o=e.tagName.toLowerCase();Array.from(e.parentElement.children).filter(t=>t.tagName===e.tagName).length>1&&(o+=`:nth-child(${Array.prototype.indexOf.call(e.parentElement.children,e)+1})`),t.unshift(o),e=e.parentElement}return t.join(" > ")})(e),t)),(0,_defineProperty2.default)(this,"waitForStyleAndClose",async(e,t,o)=>{try{await e.waitForFunction(e=>{const t=document.querySelector(e);return t&&"none"===window.getComputedStyle(t).display},{timeout:1e4},t),console.log(`元素 ${t} 的 display 設為 none 了!`)}catch(e){console.error(`元素 ${t} 的 display 沒有在指定時間內設為 none。`,e)}}),(0,_defineProperty2.default)(this,"waitSelectorTilAppear",async(e,t,o=1e4)=>{try{return await e.waitForSelector(t,{visible:!0,timeout:o}),console.log(`元素 ${t} 已在 ${e.url()} 上出現!`),!0}catch(e){const a=`元素 ${t} 未在 ${o/1e3} 秒內出現。`;console.error(a,e)}}),(0,_defineProperty2.default)(this,"close",async e=>{const t=async e=>{if(e&&e.close)try{await e.close()}catch(e){console.warn(`資源關閉時發生錯誤,可能已被提前關閉: ${e.message}`)}};e&&(e.context||e.page?(await t(e.page),await t(e.context)):await t(e))}),(0,_defineProperty2.default)(this,"terminate",async()=>{await this.browser.close()}),this.puppeteer=e,this.visible=t,this.host=o}async fetchElementsTilPageEnd({page:e,href:t="",fetcher:o=async(e),selectorOfPagingN:a,signOfPagingN:i="»",incognito:n=!1}){let r,s=e;e||(r=await this.activatePage4Load({href:t,incognito:n}),s=r.page);let l=[];try{do{await _index.utiller.syncDelay(10);const e=await o(s);l=l.concat(e)}while(await this.clickNextPageTilEnd({page:s,selector:a,sign:i}))}catch(e){return console.error(`抓取失敗: ${e.message}`),[]}finally{r?await this.close(r):e.close()}return l}async fetchElementsTilPageScrollEnd(){}async clearCookies(e){await e.deleteCookie(...await e.cookies())}async checkSelectorExists(e,t){return!!await e.$(t)}async finish(){await this.browser.close()}async clickSolution(e,t){await e.evaluate(e=>{e.click()},t)}async managePages(e,t=this.browser){t.on("targetcreated",async t=>{const o=await t.page();if(o){const t=`https://www.sachianail.com${new URL(o.url()).pathname}`;t!==e&&(console.log(`Closing page with path: ${t},should be ${e}`),await o.close())}});const o=await t.pages();for(const t of o){const o=`https://www.sachianail.com${new URL(t.url()).pathname}`;o!==e&&(console.log(`Closing page with path: ${o},should be ${e}`),await t.close())}await new Promise(e=>setTimeout(e,1e4))}async checkElementVisibleWithRetry(e,t,o=3e4,a=1e3){const i=Date.now();try{for(;Date.now()-i<o;){if(await e.$(t)){if(await e.evaluate(e=>{const t=document.querySelector(e);if(!t)return!1;const o=window.getComputedStyle(t);return"none"!==o.display&&"hidden"!==o.visibility&&"0"!==o.opacity},t))return console.log(`元素 ${t} 存在且可見`),!0;console.log(`元素 ${t} 存在但不可見,繼續等待...`)}else console.log(`元素 ${t} 不存在,繼續等待...`);await new Promise(e=>setTimeout(e,a))}return console.log(`超時:元素 ${t} 未在 ${o/1e3} 秒內變為可見`),!1}catch(e){return console.error(`發生錯誤: ${e.message}`),!1}}}var _default=exports.default=Spider;
|
package/package.json
CHANGED