【问题标题】:Using an iterator in conjunction with a scraper of multiple URLs to avoid lengthy repetitive script将迭代器与多个 URL 的抓取器结合使用,以避免冗长的重复脚本
【发布时间】:2021-12-23 10:08:02
【问题描述】:

大家好,提前感谢您的帮助。

我的编码风格(根本不是编码员)是借用现有的东西并尝试使其适合我的情况。

在这种情况下,我借用刮板来刮取价格和商品编号,然后将其写入谷歌表格。有用。但是在输入 100 个项目中的 25 个项目后,我想知道是否可以迭代该过程(for 循环?),以避免 1000 行脚本?

我已经附上了原始刮板(有效),它也有变化的开始(url1、name1、price1 等的函数)

function runGraingerScraperRemoveOld(){
     priceScraper();
     outWithTheOldInWithTheNew();
}

function priceScraper() {
    var url1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('TotalList').getRange('H9').getValue();
//    const url2 = 'https://www.grainger.com/product/CONDOR-Sorbent-Boom-35ZR66' 
//    const url3 = 'https://www.grainger.com/product/EAGLE-95-gal-Yellow-Polyethylene-5PW10'
//    const url4 = 'https://www.grainger.com/product/GRAINGER-APPROVED-55-gal-Yellow-Steel-Open-Head-4GY35'
//    const url5 = 'https://www.grainger.com/product/5EET0'

    
    // parse the data, return the price     
    const price1 = getData(url1).replace("$","").replace(/\s/g, "")
//    const price2 = getData(url2).replace("$","").replace(/\s/g, "")
//    const price3 = getData(url3).replace("$","").replace(/\s/g, "")
//    const price4 = getData(url4).replace("$","").replace(/\s/g, "")
//    const price5 = getData(url5).replace("$","").replace(/\s/g, "")

    
    // reference name (Item #)
    const name1 = getItemNumber(url1);
//    var name2 = '35ZR66'
//    var name3 = '5PW10'
//    var name4 = '4GY35'
//    var name5 = '5EET0'

    
    // input data into spreadsheet
    var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Graingerscrape');
    sheet1.appendRow([name1, new Date(), price1]);
//    var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Graingerscrape');
//    sheet1.appendRow([name2, new Date(), price2]);
//    var sheet3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Graingerscrape');
//    sheet1.appendRow([name3, new Date(), price3]);
//    var sheet4 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Graingerscrape');
//    sheet1.appendRow([name4, new Date(), price4]);
//    var sheet5 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Graingerscrape');
}

function outWithTheOldInWithTheNew() {
  var sh=SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Graingerscrape');
  var eA=sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn()).getValues();
  var tA=sh.getRange(2,1,sh.getLastRow()-1,1).getValues();
  var dA=sh.getRange(2,2,sh.getLastRow()-1,10).getValues();
  var uA=[];//ticket numbers
  var uB=[];//dates
  var uC=[];//entire rows
  for(var i=0;i<tA.length;i++) {
    var idx=uA.indexOf(tA[i][0]);
    if(idx==-1) {
      uA.push(tA[i][0]);
      uB.push(dA[i][0]);
      uC.push(eA[i]);
    }else if(new Date(dA[i][0]).valueOf() > new Date(uB[idx]).valueOf()) {
      uB.splice(idx,1,dA[i][0]);//replace newer dates
      uC.splice(idx,1,eA[i]);//replace newer rows
    }
  }
  sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn()).clearContent();
  sh.getRange(2,1,uC.length,uC[0].length).setValues(uC);//newest rows
}

function getData(url1){
    var fromText = '<span class="pricing__price">';
    var toText = '</span>';
  
    var content = UrlFetchApp.fetch(url1).getContentText();
    var scraped = Parser
                      .data(content)
                      .from(fromText)
                      .to(toText)
                      .build();
    Logger.log(scraped);
    return scraped;
}
function getItemNumber(url1){
    var fromText = '<span class="product-detail__product-identifiers-description">';
    var toText = '</span>';
  
    var content = UrlFetchApp.fetch(url1).getContentText();
    var scraped = Parser
                      .data(content)
                      .from(fromText)
                      .to(toText)
                      .build();
    Logger.log(scraped);
    return scraped;
}
//function getData(url2){
//    var fromText = '<span class="pricing__price">';
//    var toText = '</span>';
//  
//    var content = UrlFetchApp.fetch(url2).getContentText();
//    var scraped = Parser
//                      .data(content)
//                      .from(fromText)
//                      .to(toText)
//                      .build();
//    Logger.log(scraped);
//    return scraped;
//}
//function getData(url3){
//    var fromText = '<span class="pricing__price">';
//    var toText = '</span>';
//  
//    var content = UrlFetchApp.fetch(url3).getContentText();
//    var scraped = Parser
//                      .data(content)
//                      .from(fromText)
//                      .to(toText)
//                      .build();
//    Logger.log(scraped);
//    return scraped;
//}
//function getData(url4){
//    var fromText = '<span class="pricing__price">';
//    var toText = '</span>';
//  
//    var content = UrlFetchApp.fetch(url4).getContentText();
//    var scraped = Parser
//                      .data(content)
//                      .from(fromText)
//                      .to(toText)
//                      .build();
//    Logger.log(scraped);
//    return scraped;
//}  
//function getData(url5){
//    var fromText = '<span class="pricing__price">';
//    var toText = '</span>';
//  
//    var content = UrlFetchApp.fetch(url5).getContentText();
//    var scraped = Parser
//                      .data(content)
//                      .from(fromText)
//                      .to(toText)
//                      .build();
//    Logger.log(scraped);
//    return scraped;
//}  
  

如您所见,原始代码需要输入 URL(例如 - const url2、const url3 等)。从那以后,我已经能够从工作表上的每个超链接中提取 URL,现在正在使用单元格引用(例如 - var url1)。

我卡住的地方是为 URL 检索创建一个迭代器,以及迭代解析出相应的 Item # - 函数 getItemNumber(url1) 和相应的价格函数 getData(url1)。

从那里(因为这都是在数据表中),我将根据相应的 URL 使用 offset 输入名称和价格。

添加了谷歌表格的截图

希望这是足够的信息?再次感谢。

【问题讨论】:

  • 由于我的原始帖子“看起来像垃圾邮件”,我将代码缩减为 5 个示例。感谢 Ivan Kutil 提供的爬虫代码,感谢 Youtube 上的 dev101 实现了 Kutil 先生的代码,并在 SO 上合作了 outWithTheOldInWithTheNew 代码。
  • 其他网址在哪里?是否在TotalList 的范围内?
  • 嗨,彼得 T。是的,他们是。我一直在搞乱的代码(并没有在此处发布)包括 var urlRangeArray = totalList.getRange(9,8,lr,1).getValues();,这是 URL 所在的位置。
  • 添加了谷歌表格“TotalList”的截图。

标签: loops google-apps-script web-scraping google-sheets iterator


【解决方案1】:

通过迭代 urls 列,在本例中为 H,您可以轻松地重用您在 priceScrapper 中使用过的代码。

这可以通过多种方式实现。我给你一个近似值。

示例代码

const loopedScraper = () => {
  const ss = SpreadsheetApp.openById(ID_SHEET)
  // Get the list of all URL, filtering it for clearing empty ones.
  const listUrl = ss.getRange('TotalList!H1:H' + ss.getLastRow())
    .getValues()
    .flat() // getValues() returns two dimension Array
    .filter(i => i != "") // clear empty ones
  // Iterate over them and reusing your code  
  for (let url of listUrl) {
    let price = getData(url).replace("$", "").replace(/\s/g, "")
    let name = getItemNumber(url)
    let newRow = [name, new Date(), price]
    ss.getSheetByName('Graingerscrape').appendRow(newRow)
  }
}

【讨论】:

  • 非常感谢您的代码。当我运行它时,它返回“ReferenceError:getData 未定义(第 10 行)”。 url 需要是变量还是常量?马库斯
  • getData 函数出现在您问题的代码示例中。检查该函数是否存在于您复制我的答案的同一个 GS 脚本中。
猜你喜欢
  • 2021-01-22
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-23
  • 2018-05-24
  • 1970-01-01
相关资源
最近更新 更多