4/20 下午 Emily 第五堂課,課堂程式片段

Amazon 商品搜尋.csv

name,low_price,high_price
藍牙耳機,100,150
筆記型電腦,1500,2000

範例 5,Amazon 商品搜尋

初步嘗試

document.getElementsByClassName("s-result-list");

修正後,只找到 1 筆才對。

document.querySelectorAll("div.s-main-slot.s-result-list");

使用後代選擇器 div.s-result-item 撈出商品項目

document.querySelectorAll(
    "div.s-main-slot.s-result-list div.s-result-item");

加入 .s-asin 限縮撈出的結果

document.querySelectorAll(
    "div.s-main-slot.s-result-list div.s-result-item.s-asin");

使用 :not() 選取器,濾掉不需要的 AdHolder

document.querySelectorAll(
    "div.s-main-slot.s-result-list div.s-result-item.s-asin:not(.AdHolder)");

進一步撈出商品標題跟價格

//這個選取器撈出來的是 16 個商品項目的『右邊』部分
let product_blocks = document.querySelectorAll(
    "div.s-main-slot.s-result-list div.s-result-item.s-asin:not(.AdHolder) div.sg-col-inner .s-list-col-right");

//根據撈出來的右邊區塊,再往下撈出商品標題跟商品價格
product_blocks.forEach(product_block=>{
    let product_title = product_block.querySelectorAll("div.sg-col-inner span.a-text-normal")[0].innerText;
    let product_price = product_block.querySelectorAll("div.sg-row span.a-offscreen")[0].innerText;
    // 將商品標題,商品價格作成一個物件,然後個別印出
    console.log({
        "product_title": product_title,
        "product_price": product_price
    });
});

將撈出的商品標題,商品價格作成一個物件,並蒐集到一個陣列中

let product_results = [];
let product_blocks = document.querySelectorAll(
    "div.s-main-slot.s-result-list div.s-result-item.s-asin:not(.AdHolder) div.sg-col-inner .s-list-col-right");

product_blocks.forEach(product_block=>{
    let product_title = product_block.querySelectorAll("div.sg-col-inner span.a-text-normal")[0].innerText;
    let product_price = product_block.querySelectorAll("div.sg-row span.a-offscreen")[0].innerText;
    product_results.push({
        "product_title": product_title,
        "product_price": product_price
    });
});
console.log(product_results);

然後存成檔案

let product_results = [];
let product_blocks = document.querySelectorAll(
    "div.s-main-slot.s-result-list div.s-result-item.s-asin:not(.AdHolder) div.sg-col-inner .s-list-col-right");

product_blocks.forEach(product_block=>{
    let product_title = product_block.querySelectorAll("div.sg-col-inner span.a-text-normal")[0].innerText;
    let product_price = product_block.querySelectorAll("div.sg-row span.a-offscreen")[0].innerText;
    product_results.push({
        "product_title": product_title,
        "product_price": product_price
    });
});

write("product_result.txt", JSON.stringify(product_results));

使用 click() 方法切換搜尋結果到下一頁

 document.querySelectorAll("a.s-pagination-item.s-pagination-next")[0].click();

最終完成的執行腳本程式碼

let loop_count;
try {
    loop_count = JSON.parse(read("loop_count.txt"));
} catch(e){
    loop_count = 0;
}
let product_results;
try{
    product_results = JSON.parse(read("product_result.txt"));
}catch(e){
    product_results = [];
}

let product_blocks = document.querySelectorAll(
    "div.s-main-slot.s-result-list div.s-result-item.s-asin:not(.AdHolder) div.sg-col-inner .s-list-col-right");

product_blocks.forEach(product_block=>{
    try{
        let product_title = product_block.querySelectorAll("div.sg-col-inner span.a-text-normal")[0].innerText;
        let product_price = product_block.querySelectorAll("div.sg-row span.a-offscreen")[0].innerText;
        product_results.push({
            "product_title": product_title,
            "product_price": product_price
        });
    }catch(e){
        console.error(e);
    }
});
write("product_result.txt", JSON.stringify(product_results));

if(loop_count < 2){ 
    write("loop_count.txt", JSON.stringify(loop_count+1));
    
    repeat(true, 3000);
    
    document.querySelectorAll("a.s-pagination-item.s-pagination-next")[0].click();
} else {
    remove("loop_count.txt");
}

CSV 表格建立用的程式碼

console.log(input);

let products = JSON.parse(input['product_result']);

products.forEach(element =>{
  output.push({
    "product_name": element.product_title,
    "product_price": element.product_price
  });
})

有遇到因為缺乏商品價格而導致上課進行時,程式執行錯誤。
在此附上修正後的程式碼。

此版程式有考慮了商品價格從缺的情況

//這個選取器撈出來的是 16 個商品項目的『右邊』部分
let product_blocks = document.querySelectorAll(
    "div.s-main-slot.s-result-list div.s-result-item.s-asin:not(.AdHolder) div.sg-col-inner .s-list-col-right");

//根據撈出來的右邊區塊,再往下撈出商品標題跟商品價格
product_blocks.forEach(product_block=>{
    let product_title = product_block.querySelectorAll("div.sg-col-inner span.a-text-normal")[0].innerText;
    
    let price = "";
    let product_price = product_block.querySelectorAll(".a-price span.a-offscreen")[0];
    if( product_price ){
      price = product_price.innerText;
      console.log(product_price.innerText);
    } else {
      price = "free";
      console.log("free"); 
    }
    
    // 將商品標題,商品價格作成一個物件,然後個別印出
    console.log({
        "product_title": product_title,
        "product_price": price
    });
});

加入價格是否存在的判斷

//這個選取器撈出來的是 16 個商品項目的『右邊』部分
let product_blocks = document.querySelectorAll(
  "div.s-main-slot.s-result-list div.s-result-item.s-asin:not(.AdHolder) div.sg-col-inner .s-list-col-right");

//根據撈出來的右邊區塊,再往下撈出商品標題跟商品價格
product_blocks.forEach(product_block=>{
  let product_title = product_block.querySelectorAll("div.sg-col-inner span.a-text-normal")[0].innerText;
  
  let product_price = "";
  //因為價格資訊有可能從缺
  let product_price_node = product_block.querySelectorAll(".a-price span.a-offscreen")[0];
  if( product_price_node ){ //所以在這裏作了一個 if 判斷,用來確認此節點是否存在
    product_price = product_price_node.innerText;
  } else {
    product_price = "free";
  }
  
  // 將商品標題,商品價格作成一個物件,然後個別印出
  console.log({
      "product_title": product_title,
      "product_price": product_price
  });
});