utiller 1.0.447 → 1.0.449
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:i=""}){(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,"getPuTeerPage",async({browser:e=this.browser,type:t="desktop",incognito:i=!1,href:o="",timeout:a=0})=>{let r;if(i){const t=await e.createBrowserContext();r=await t.newPage()}else r=await e.newPage();return await this.randomViewport({page:r,type:t}),_index.utiller.isUndefinedNullEmpty(o)||await r.goto(o,{waitUntil:"networkidle2",timeout:a}),r}),(0,_defineProperty2.default)(this,"randomViewport",async({page:e,type:t="desktop"})=>{const i=_index.utiller.getRandomValue(1080,1920),o=_index.utiller.getRandomValue(1680,1920);await e.setViewport({width:i,height:o})}),(0,_defineProperty2.default)(this,"getPageOfSilent",async({browser:e=this.browser,type:t="desktop",timeout:i=0})=>this.getPuTeerPage({browser:e,type:t,timeout:i})),(0,_defineProperty2.default)(this,"activatePage4Load",async({browser:e=this.browser,href:t="",type:i="desktop",timeout:o=0,incognito:a=!1})=>await this.getPuTeerPage({browser:e,href:t,type:i,timeout:o,incognito:a})),(0,_defineProperty2.default)(this,"activatePage4Task",async({browser:e=this.browser,href:t="",type:i="desktop",timeout:o=0,fetcher:a=async e=>!0,incognito:r=!1})=>{const n=await this.activatePage4Load({browser:e,href:t,type:i,timeout:o,incognito:r}),s=await a(n);return await this.close(n),s}),(0,_defineProperty2.default)(this,"auto",async({page:e,incognito:t=!1,href:i,timeout:o=0})=>this.isPuTeerPage(e)?(_index.utiller.isUndefinedNullEmpty(i)||await e.goto(i,{waitUntil:"networkidle2",timeout:o}),await this.randomViewport(e),e):await this.activatePage4Load({incognito:t,timeout:o,href:i})),(0,_defineProperty2.default)(this,"isPuTeerPage",e=>e?.focus),(0,_defineProperty2.default)(this,"clickNextPageTilEnd",async({page:e,selector:t=".pagination-container .pagination > *",sign:i="»"})=>{try{const o=await e.$$(t);if(!o||0===o.length)return console.log("⚠️ 找不到頁面按鈕們"),!1;console.log(`📍 找到 ${o.length} 個頁面按鈕`);let a=null;for(const e of[...o].reverse())if(await this.fetchAttributeOfEl(e,await this.isElementTagBy(e,"a")?"":"a","innerText")===i){a=e;break}return a?(console.log("✅ 找到下一頁按鈕"),await a.evaluate(e=>e.disabled||e.classList.contains("disabled"))?(console.log("⚠️ 下一頁按鈕已禁用 (已是最後一頁)"),!1):(console.log("🖱️ 點擊下一頁按鈕..."),await a.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,"fetchElementsTilPageScrollEnd",async({page:e,href:t="",fetcher:i=async e=>{},stringOfLoadingSelector:o,incognito:a=!1,timeout:r})=>{const n=await this.auto({page:e,incognito:a,href:t,timeout:r});await this.scrollToBottomAndCheck(n,{stringOfLoadingSelector:o});const s=await i(n);return await this.close(n),s}),(0,_defineProperty2.default)(this,"fetchAttributesOfEl",async(e,t,i)=>{let o;if(t&&""!==t.trim()){if(o=await e.$(t),!o)return console.warn(`⚠️ 找不到元素: ${t}`),{}}else o=e;const a={},r={};for(const[e,t]of Object.entries(i)){if("object"==typeof t&&null!==t&&!Array.isArray(t)){Object.assign(r,t);continue}const i=String(t);if(i.startsWith("$$$")){const t=i.substring(3),o=parseFloat(t);isNaN(o)?(console.warn(`⚠️ 無法解析數字: ${i}`),r[e]=void 0):r[e]=o;continue}if(i.startsWith("###")){const t=i.substring(3);r[e]=t;continue}if(i.startsWith("@@@")){const t=i.substring(3).toLowerCase().trim();let o;"true"===t||"1"===t||"yes"===t||"y"===t||"on"===t?o=!0:("false"===t||"0"===t||"no"===t||"n"===t||"off"===t||""===t||console.warn(`⚠️ 無法解析布林值: ${i},默認為 false`),o=!1),r[e]=o;continue}a[e]=t}const n=await o.evaluate((e,t)=>{const i={};for(const[o,a]of Object.entries(t)){const t=void 0!==e[a]?e[a]:e.getAttribute(a);i[o]=null!==t?t:void 0}return i},a);return{...n,...r}}),(0,_defineProperty2.default)(this,"fetchAttributeOfEl",async(e,t,i)=>{let o;if(t&&""!==t.trim()){if(o=await e.$(t),!o)return void console.warn(`⚠️ 找不到元素: ${t}`)}else o=e;return await o.evaluate((e,t)=>{const i=void 0!==e[t]?e[t]:e.getAttribute(t);return null!==i?i:void 0},i)}),(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,i=1e4)=>{if(!t)return!0;try{return await e.waitForSelector(t,{hidden:!0,timeout:i}),!0}catch(e){return console.warn(`警告: Loading Bar ${t} 在 ${i}ms 內未消失,將強制繼續執行。`),!1}}),(0,_defineProperty2.default)(this,"scrollToBottomAndCheck",async(e,{minDelay:t=2e3,maxRetries:i=3,stringOfLoadingSelector:o,loadingTimeout:a=6e3}={})=>{console.log("🚀 開始執行智能滾動檢查...");let r=await e.evaluate(()=>document.body.scrollHeight),n=0;for(;;){await e.evaluate(()=>window.scrollTo(0,document.body.scrollHeight)),await new Promise(e=>setTimeout(e,t)),o&&await this.waitForLoadingToVanish(e,o,a);let s=await e.evaluate(()=>document.body.scrollHeight);if(s===r){if(n++,n>=i){console.log(`✅ 連續 ${i} 次未檢測到新內容,判定已到達最底部。`);break}console.log(`🔄 高度未變化,正在重試等待... (${n}/${i})`),await new Promise(e=>setTimeout(e,1e3))}else console.log(`⬇️ 檢測到新內容 (高度: ${r} -> ${s}),繼續滾動...`),r=s,n=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 i=e.tagName.toLowerCase();Array.from(e.parentElement.children).filter(t=>t.tagName===e.tagName).length>1&&(i+=`:nth-child(${Array.prototype.indexOf.call(e.parentElement.children,e)+1})`),t.unshift(i),e=e.parentElement}return t.join(" > ")})(e),t)),(0,_defineProperty2.default)(this,"waitSelectorTilAppear",async(e,t,i=1e4)=>{try{return await e.waitForSelector(t,{visible:!0,timeout:i}),console.log(`元素 ${t} 已在 ${e.url()} 上出現!`),!0}catch(e){const o=`元素 ${t} 未在 ${i/1e3} 秒內出現。`;console.error(o,e)}}),(0,_defineProperty2.default)(this,"close",async e=>{if(e)try{const t=e.browserContext();t===e.browser().defaultBrowserContext()?await e.close():await t.close()}catch(e){console.error("關閉頁面/Context 時發生錯誤:",e)}}),(0,_defineProperty2.default)(this,"terminate",async()=>{await this.browser.close()}),this.puppeteer=e,this.visible=t,this.host=i}async fetchElementsTilPageEnd({page:e,href:t="",fetcher:i=async e=>[],selectorOfPagingN:o,signOfPagingN:a="»",incognito:r=!1,timeout:n=0}){const s=await this.auto({page:e,incognito:r,href:t,timeout:n});let l=[];try{do{await _index.utiller.syncDelay(10);const e=await i(s);l=l.concat(e)}while(await this.clickNextPageTilEnd({page:s,selector:o,sign:a}))}catch(e){return console.error(`抓取失敗: ${e.message}`),[]}finally{await this.close(s)}return l}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){const i=e=>{try{const t=new URL(e);return _index.utiller.getUrlPath(this.host,t.pathname)}catch(e){return null}};t.on("targetcreated",async t=>{if("page"===t.type())try{const o=await t.page();if(!o)return;const a=o.url();if("about:blank"===a)return;const r=i(a);r&&r!==e&&(console.log(`[攔截新分頁] 偵測到非法網址: ${r} (目標應為: ${e}),正在關閉...`),await o.close())}catch(e){console.error(`[新分頁檢查錯誤] 無法處理頁面: ${e.message}`)}});try{const o=await t.pages();for(const t of o){const o=t.url();if(t.isClosed()||"about:blank"===o)continue;const a=i(o);a&&a!==e&&(console.log(`[清理舊分頁] 發現非法網址: ${a} (目標應為: ${e}),正在關閉...`),await t.close())}}catch(e){console.error(`[舊分頁清理錯誤] ${e.message}`)}console.log("頁面管理已啟動,保持監聽 10 秒..."),await new Promise(e=>setTimeout(e,1e4))}async checkElementVisibleWithRetry(e,t,i=3e4,o=1e3){const a=Date.now();try{for(;Date.now()-a<i;){if(await e.$(t)){if(await e.evaluate(e=>{const t=document.querySelector(e);if(!t)return!1;const i=window.getComputedStyle(t);return"none"!==i.display&&"hidden"!==i.visibility&&"0"!==i.opacity},t))return console.log(`元素 ${t} 存在且可見`),!0;console.log(`元素 ${t} 存在但不可見,繼續等待...`)}else console.log(`元素 ${t} 不存在,繼續等待...`);await new Promise(e=>setTimeout(e,o))}return console.log(`超時:元素 ${t} 未在 ${i/1e3} 秒內變為可見`),!1}catch(e){return console.error(`發生錯誤: ${e.message}`),!1}}}var _default=exports.default=Spider;
|
|
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:i=""}){(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,"getPuTeerPage",async({browser:e=this.browser,type:t="desktop",incognito:i=!1,href:o="",timeout:a=0})=>{let r;if(i){const t=await e.createBrowserContext();r=await t.newPage()}else r=await e.newPage();return await this.randomViewport({page:r,type:t}),_index.utiller.isUndefinedNullEmpty(o)||await r.goto(o,{waitUntil:"networkidle2",timeout:a}),r}),(0,_defineProperty2.default)(this,"randomViewport",async({page:e,type:t="desktop"})=>{const i=_index.utiller.getRandomValue(1080,1920),o=_index.utiller.getRandomValue(1680,1920);await e.setViewport({width:i,height:o})}),(0,_defineProperty2.default)(this,"getPageOfSilent",async({browser:e=this.browser,type:t="desktop",timeout:i=0})=>this.getPuTeerPage({browser:e,type:t,timeout:i})),(0,_defineProperty2.default)(this,"activatePage4Load",async({browser:e=this.browser,href:t="",type:i="desktop",timeout:o=0,incognito:a=!1})=>await this.getPuTeerPage({browser:e,href:t,type:i,timeout:o,incognito:a})),(0,_defineProperty2.default)(this,"activatePage4Task",async({browser:e=this.browser,href:t="",type:i="desktop",timeout:o=0,fetcher:a=async e=>!0,incognito:r=!1})=>{const n=await this.activatePage4Load({browser:e,href:t,type:i,timeout:o,incognito:r}),s=await a(n);return await this.close(n),s}),(0,_defineProperty2.default)(this,"auto",async({page:e,incognito:t=!1,href:i,timeout:o=0})=>this.isPuTeerPage(e)?(_index.utiller.isUndefinedNullEmpty(i)||await e.goto(i,{waitUntil:"networkidle2",timeout:o}),await this.randomViewport(e),e):await this.activatePage4Load({incognito:t,timeout:o,href:i})),(0,_defineProperty2.default)(this,"isPuTeerPage",e=>e?.focus),(0,_defineProperty2.default)(this,"clickNextPageTilEnd",async({page:e,selector:t=".pagination-container .pagination > *",sign:i="»"})=>{try{const o=await e.$$(t);if(!o||0===o.length)return console.log("⚠️ 找不到頁面按鈕們"),!1;console.log(`📍 找到 ${o.length} 個頁面按鈕`);let a=null;for(const e of[...o].reverse())if(await this.fetchAttributeOfEl(e,await this.isElementTagBy(e,"a")?"":"a","innerText")===i){a=e;break}return a?(console.log("✅ 找到下一頁按鈕"),await a.evaluate(e=>e.disabled||e.classList.contains("disabled"))?(console.log("⚠️ 下一頁按鈕已禁用 (已是最後一頁)"),!1):(console.log("🖱️ 點擊下一頁按鈕..."),await a.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,"wait4Until",async(e,{timeout:t=0}={})=>{await e.waitForNavigation({waitUntil:"networkidle2",timeout:t}).catch(()=>{})}),(0,_defineProperty2.default)(this,"fetchElementsTilPageScrollEnd",async({page:e,href:t="",fetcher:i=async e=>{},stringOfLoadingSelector:o,incognito:a=!1,timeout:r})=>{const n=await this.auto({page:e,incognito:a,href:t,timeout:r});await this.scrollToBottomAndCheck(n,{stringOfLoadingSelector:o});const s=await i(n);return await this.close(n),s}),(0,_defineProperty2.default)(this,"fetchAttributesOfEl",async(e,t,i)=>{let o;if(t&&""!==t.trim()){if(o=await e.$(t),!o)return console.warn(`⚠️ 找不到元素: ${t}`),{}}else o=e;const a={},r={};for(const[e,t]of Object.entries(i)){if("object"==typeof t&&null!==t&&!Array.isArray(t)){Object.assign(r,t);continue}const i=String(t);if(i.startsWith("$$$")){const t=i.substring(3),o=parseFloat(t);isNaN(o)?(console.warn(`⚠️ 無法解析數字: ${i}`),r[e]=void 0):r[e]=o;continue}if(i.startsWith("###")){const t=i.substring(3);r[e]=t;continue}if(i.startsWith("@@@")){const t=i.substring(3).toLowerCase().trim();let o;"true"===t||"1"===t||"yes"===t||"y"===t||"on"===t?o=!0:("false"===t||"0"===t||"no"===t||"n"===t||"off"===t||""===t||console.warn(`⚠️ 無法解析布林值: ${i},默認為 false`),o=!1),r[e]=o;continue}a[e]=t}const n=await o.evaluate((e,t)=>{const i={};for(const[o,a]of Object.entries(t)){const t=void 0!==e[a]?e[a]:e.getAttribute(a);i[o]=null!==t?t:void 0}return i},a);return{...n,...r}}),(0,_defineProperty2.default)(this,"fetchAttributeOfEl",async(e,t,i)=>{let o;if(t&&""!==t.trim()){if(o=await e.$(t),!o)return void console.warn(`⚠️ 找不到元素: ${t}`)}else o=e;return await o.evaluate((e,t)=>{const i=void 0!==e[t]?e[t]:e.getAttribute(t);return null!==i?i:void 0},i)}),(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,i=1e4)=>{if(!t)return!0;try{return await e.waitForSelector(t,{hidden:!0,timeout:i}),!0}catch(e){return console.warn(`警告: Loading Bar ${t} 在 ${i}ms 內未消失,將強制繼續執行。`),!1}}),(0,_defineProperty2.default)(this,"scrollToBottomAndCheck",async(e,{minDelay:t=2e3,maxRetries:i=3,stringOfLoadingSelector:o,loadingTimeout:a=6e3}={})=>{console.log("🚀 開始執行智能滾動檢查...");let r=await e.evaluate(()=>document.body.scrollHeight),n=0;for(;;){await e.evaluate(()=>window.scrollTo(0,document.body.scrollHeight)),await new Promise(e=>setTimeout(e,t)),o&&await this.waitForLoadingToVanish(e,o,a);let s=await e.evaluate(()=>document.body.scrollHeight);if(s===r){if(n++,n>=i){console.log(`✅ 連續 ${i} 次未檢測到新內容,判定已到達最底部。`);break}console.log(`🔄 高度未變化,正在重試等待... (${n}/${i})`),await new Promise(e=>setTimeout(e,1e3))}else console.log(`⬇️ 檢測到新內容 (高度: ${r} -> ${s}),繼續滾動...`),r=s,n=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 i=e.tagName.toLowerCase();Array.from(e.parentElement.children).filter(t=>t.tagName===e.tagName).length>1&&(i+=`:nth-child(${Array.prototype.indexOf.call(e.parentElement.children,e)+1})`),t.unshift(i),e=e.parentElement}return t.join(" > ")})(e),t)),(0,_defineProperty2.default)(this,"waitSelectorTilAppear",async(e,t,i=1e4)=>{try{return await e.waitForSelector(t,{visible:!0,timeout:i}),console.log(`元素 ${t} 已在 ${e.url()} 上出現!`),!0}catch(e){const o=`元素 ${t} 未在 ${i/1e3} 秒內出現。`;console.error(o,e)}}),(0,_defineProperty2.default)(this,"close",async e=>{if(e)try{const t=e.browserContext();t===e.browser().defaultBrowserContext()?await e.close():await t.close()}catch(e){console.error("關閉頁面/Context 時發生錯誤:",e)}}),(0,_defineProperty2.default)(this,"terminate",async()=>{await this.browser.close()}),this.puppeteer=e,this.visible=t,this.host=i}async fetchElementsTilPageEnd({page:e,href:t="",fetcher:i=async e=>[],selectorOfPagingN:o,signOfPagingN:a="»",incognito:r=!1,timeout:n=0}){const s=await this.auto({page:e,incognito:r,href:t,timeout:n});let l=[];try{do{await _index.utiller.syncDelay(10);const e=await i(s);l=l.concat(e)}while(await this.clickNextPageTilEnd({page:s,selector:o,sign:a}))}catch(e){return console.error(`抓取失敗: ${e.message}`),[]}finally{await this.close(s)}return l}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){const i=e=>{try{const t=new URL(e);return _index.utiller.getUrlPath(this.host,t.pathname)}catch(e){return null}};t.on("targetcreated",async t=>{if("page"===t.type())try{const o=await t.page();if(!o)return;const a=o.url();if("about:blank"===a)return;const r=i(a);r&&r!==e&&(console.log(`[攔截新分頁] 偵測到非法網址: ${r} (目標應為: ${e}),正在關閉...`),await o.close())}catch(e){console.error(`[新分頁檢查錯誤] 無法處理頁面: ${e.message}`)}});try{const o=await t.pages();for(const t of o){const o=t.url();if(t.isClosed()||"about:blank"===o)continue;const a=i(o);a&&a!==e&&(console.log(`[清理舊分頁] 發現非法網址: ${a} (目標應為: ${e}),正在關閉...`),await t.close())}}catch(e){console.error(`[舊分頁清理錯誤] ${e.message}`)}console.log("頁面管理已啟動,保持監聽 10 秒..."),await new Promise(e=>setTimeout(e,1e4))}async checkElementVisibleWithRetry(e,t,i=3e4,o=1e3){const a=Date.now();try{for(;Date.now()-a<i;){if(await e.$(t)){if(await e.evaluate(e=>{const t=document.querySelector(e);if(!t)return!1;const i=window.getComputedStyle(t);return"none"!==i.display&&"hidden"!==i.visibility&&"0"!==i.opacity},t))return console.log(`元素 ${t} 存在且可見`),!0;console.log(`元素 ${t} 存在但不可見,繼續等待...`)}else console.log(`元素 ${t} 不存在,繼續等待...`);await new Promise(e=>setTimeout(e,o))}return console.log(`超時:元素 ${t} 未在 ${i/1e3} 秒內變為可見`),!1}catch(e){return console.error(`發生錯誤: ${e.message}`),!1}}}var _default=exports.default=Spider;
|
package/package.json
CHANGED