2025年7月2日 星期三

[Javascript]國立公共資訊圖書館的電子書服務平台進行複製標韱

 上篇:[ 國立公共資訊圖書館的電子書服務平台進行查詢所有符合的書目]



(1)先登入帳號1,將該帳號已標韱的書目產生"加入我的標韱"url


(async function () {

    const allUrls = [];

    const baseApi = "https://ebook.nlpi.edu.tw/personal/MyTagDetail";

    const tagName = "閱讀雲端-低年級";


    for (let start = 1; start <= 2; start++) {

        const url = `${baseApi}?tagName=${encodeURIComponent(tagName)}&start=${start}&limit=100&ajaxQuery=Y`;


        try {

            const response = await fetch(url);

            if (!response.ok) throw new Error(`API 錯誤:${response.status}`);

            const json = await response.json();


            if (Array.isArray(json.data)) {

                json.data.forEach(item => {

                    if (item.sid) {

                        const link = `https://ebook.nlpi.edu.tw/bookdetail/${item.sid}/booktag.add?tagName=${tagName}`;

                        allUrls.push(link);

                    }

                });

            }

        } catch (error) {

            console.error(`處理 start=${start} 時發生錯誤:`, error);

        }

    }


    // 將結果轉為純文字並下載

    const blob = new Blob([allUrls.join('\n')], { type: 'text/plain;charset=utf-8' });

    const downloadUrl = URL.createObjectURL(blob);

    const a = document.createElement('a');

    a.href = downloadUrl;

    a.download = 'booktag_links.txt';

    document.body.appendChild(a);

    a.click();

    document.body.removeChild(a);

    URL.revokeObjectURL(downloadUrl);

})();


(2)改登入帳號2,將產生連結進行寫入

(async function () {

    const urls = [

        "https://ebook.nlpi.edu.tw/bookdetail/1559/booktag.add?tagName=閱讀雲端-低年級",

        "https://ebook.nlpi.edu.tw/bookdetail/1463/booktag.add?tagName=閱讀雲端-低年級",

        "https://ebook.nlpi.edu.tw/bookdetail/953/booktag.add?tagName=閱讀雲端-低年級",

        "https://ebook.nlpi.edu.tw/bookdetail/1066/booktag.add?tagName=閱讀雲端-低年級",

        // ...(請將所有 URL 放入此陣列)

        "https://ebook.nlpi.edu.tw/bookdetail/11041/booktag.add?tagName=閱讀雲端-低年級"

    ];


    for (let i = 0; i < urls.length; i++) {

        try {

            const response = await fetch(urls[i], {

                method: 'GET',

                headers: {

                    'Content-Type': 'application/json'

                }

            });


            if (!response.ok) {

                console.error(`❌ 第 ${i + 1} 筆失敗:${response.status} - ${urls[i]}`);

                continue;

            }


            const result = await response.text(); // 或 .json() 視 API 回傳格式

            console.log(`✅ 第 ${i + 1} 筆成功:`, result);

        } catch (err) {

            console.error(`⚠️ 第 ${i + 1} 筆錯誤:`, err);

        }

    }

})();


2025年7月1日 星期二

[Javascript]飛閱雲端 中文圖書認證列出所有的適讀年級的書目

彰化縣飛閱雲端的 中文圖書認證查詢功能太過於陽春,無法只列出特定適讀年級的書目

 飛關雲端的網站後先登入,然後使用下面JavaScript,按F12 進入開發者工具的「主控台」,把下面指令貼上後,可以把1 - 251 頁的資料都爬過一次,並將適讀年級為「低年級」的資料轉成檔案下載下來。



(async () => {

  const result = [];

  const totalPage = 251; //總頁數,請自已輸入

  const targetGradeLevel = "低年級"; //要查詢的適讀年級,請自已輸入

  for (let page = 1; page <= totalPage; page++) {

    const url = `https://read.chc.edu.tw/item6/menu1.php?topage=${page}`;


    try {

      const response = await fetch(url);

      const htmlText = await response.text();


      const parser = new DOMParser();

      const doc = parser.parseFromString(htmlText, 'text/html');


      // 找出所有 table,搜尋包含指定表頭的那一個

      const tables = doc.querySelectorAll('table');

      let targetTable = null;


      for (const table of tables) {

        const headerRow = table.querySelector('tr[bgcolor="#CCCCCC"].font4');

    //console.error(headerRow);

        if (headerRow) {

          const headers = Array.from(headerRow.querySelectorAll('td')).map(td => td.textContent.trim());

  console.log(headers)

          if (

            headers.includes('書名') &&

            headers.includes('ISBN') &&

            headers.includes('書目類別') &&

            headers.includes('適讀年段') &&

            headers.includes('認證人數\n                  (通過/已認證)')

          ) {

            targetTable = table;

            break;

          }

        }

      }


      if (!targetTable){

        continue;

  }


      const rows = targetTable.querySelectorAll('tr');

      for (let i = 1; i < rows.length; i++) {

        const cells = rows[i].querySelectorAll('td');

        if (cells.length >= 4) {

          const title = cells[0].textContent.trim();

          const gradeLevel = cells[3].textContent.trim();

          if (gradeLevel.includes(targetGradeLevel)) {

            result.push(title);

          }

        }

      }

    } catch (err) {

      console.error(`第 ${page} 頁失敗:`, err);

    }

  }


  console.log('所有適讀年段為「'+targetGradeLevel+'」的書名如下:');

  console.log(result);

  

  console.log("轉成 CSV 字串");

  // 轉成 CSV 字串

  let csvContent = '書名\n';

  result.forEach(t => {

    const escapedTitle = t;

    csvContent += `"${escapedTitle}"\n`;

  });


  // 建立下載連結並觸發下載

  const blob = new Blob([csvContent], { type: 'text/csv;charset=big5;' });

  const urlObject = URL.createObjectURL(blob);

  const link = document.createElement('a');

  link.href = urlObject;

  link.setAttribute('download', targetGradeLevel + '書籍清單.txt');

  document.body.appendChild(link);

  link.click();

  document.body.removeChild(link);  

  

})();


====以下改為增加取得 ISBN==========


(async () => {


  const result = [];


  const totalPage = 252; //總頁數,請自已輸入


  const targetGradeLevel = "低年級"; //要查詢的適讀年級,請自已輸入


  for (let page = 1; page <= totalPage; page++) {


    const url = `https://read.chc.edu.tw/item6/menu1.php?topage=${page}`;




    try {


      const response = await fetch(url);


      const htmlText = await response.text();




      const parser = new DOMParser();


      const doc = parser.parseFromString(htmlText, 'text/html');




      // 找出所有 table,搜尋包含指定表頭的那一個


      const tables = doc.querySelectorAll('table');


      let targetTable = null;




      for (const table of tables) {


        const headerRow = table.querySelector('tr[bgcolor="#CCCCCC"].font4');



    //console.error(headerRow);


        if (headerRow) {


          const headers = Array.from(headerRow.querySelectorAll('td')).map(td => td.textContent.trim());


  console.log(headers)


          if (


            headers.includes('書名') &&


            headers.includes('ISBN') &&


            headers.includes('書目類別') &&


            headers.includes('適讀年段') &&


            headers.includes('認證人數\n                  (通過/已認證)')


          ) {


            targetTable = table;


            break;


          }


        }


      }




      if (!targetTable){


        continue;


  }




      const rows = targetTable.querySelectorAll('tr');


      for (let i = 1; i < rows.length; i++) {


        const cells = rows[i].querySelectorAll('td');


        if (cells.length >= 4) {


          const title = cells[0].textContent.trim();

          const ISBN = cells[1].textContent.trim();


          const gradeLevel = cells[3].textContent.trim();


          const goTest = cells[5].textContent.trim();

          //console.log(title,ISBN,goTest);

          if (gradeLevel.includes(targetGradeLevel) && goTest.includes("我要認證")) {


            result.push(ISBN + "," + title);


          }


        }


      }


    } catch (err) {


      console.error(`第 ${page} 頁失敗:`, err);


    }


  }




  console.log('所有適讀年段為「'+targetGradeLevel+'」的書名如下:');


  console.log(result);


  


  console.log("轉成 CSV 字串");


  // 轉成 CSV 字串


  let csvContent = 'ISBN,書名\n';


  result.forEach(t => {


    const escapedTitle = t;


    csvContent += `"${escapedTitle}"\n`;


  });




  // 建立下載連結並觸發下載


  const blob = new Blob([csvContent], { type: 'text/csv;charset=big5;' });


  const urlObject = URL.createObjectURL(blob);


  const link = document.createElement('a');


  link.href = urlObject;


  link.setAttribute('download', targetGradeLevel + '書籍清單.txt');


  document.body.appendChild(link);


  link.click();


  document.body.removeChild(link);  


  


})();


2023年11月9日 星期四

.NET MVC 佈署到IIS後發生錯誤 HTTP Error 403.14 - Forbidden

 參考自StackOverFlow文章

Don't use runAllManagedModulesForAllRequests. You want to let IIS handle resources such as images.

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>

Instead add the MVC routing module

<system.webServer>
  <modules>
    <remove name="UrlRoutingModule-4.0" />
    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
  </modules>
</system.webServer>

使用TCP/IP連線SQL Server Express的方式

(1)啟用TCP:

     SQL Server Express預設沒有啟用TCP

     1. 開啟SQL Server Configuration Manager  > SQL Server 網路組態 > SQLEXPRES的通訊協定 > TCP/IP > 內容 >  IP位址 > 找到 IPAll > TCP通訊埠 (例如輸入1433)

     2. 重啟 SQL Server Express 服務


以下為截取自網路的SQL Express相關設定可做為參考

Step 1: Enable TCP/IP connections

use TCP/IP to connect to the SQL Server database, but SQL Server Express does not enable TCP support by default. To enable TCP/IP:

  1. In SQL Server Configuration Manager, expland the SQL Server Network Configuration > Protocols for SQLEXPRESS node.

  2. Right-click the TCP/IP item on the right; then select Properties.

  3. On the General tab, change Enabled to Yes.

  4. On the IP Addresses tab, under the IPAll node, clear the TCP Dynamic Ports box.

  5. In TCP Port, enter the port to listen on . For example, 1450. Remember this port, because it needs to be used in the connection string.

  6. Click OK.

  7. Restart the Microsoft SQL Server Express service using either the standard service control panel or the SQL Express tools.

Step 2: Enable SQL Server authentication

When require SQL Server authentication to be enabled on the instance of SQL Express. To do this:

  1. In SQL Server Management Studio Express tool, right-click the instance of SQL Express to configure; then select Properties.

  2. Select the Security section on the left.

  3. Change the Server Authentication to SQL Server and Windows Authentication mode.

  4. Restart the Microsoft SQL Server Express service using either the standard service control panel or the SQL Express tools.

Step 3: Create a database user

When require a user to connect to the database. To create this user:

  1. In SQL Server Management Studio Express tool, right-click the Security > Logins node; then select New Login.

  2. Enter the username (e.g.  web ).

  3. Change the Server Authentication to SQL Server and Windows Authentication mode.

  4. Enter the user’s password.

  5. Disable password expiration.

  6. Click OK.

  7. After creating database, assign this user db_owner permissions on the database, so that it can create the required database tables.

Step 4: Set statistics to auto update

  1. In SQL Server Management Studio Express, right-click the database; then select Properties.

    The Database Properties dialog is displayed.

  2. Scroll to the top of the Other options list.

  3. In Auto Update Statistics, select True.

  4. Click OK.