【问题标题】:Error: failed to find element matching selector for <img data-src="url>错误:未能找到 <img data-src="url> 的元素匹配选择器
【发布时间】:2019-09-17 03:26:15
【问题描述】:

在 Puppeteer 上运行,全部更新。

预期的过程是转到网站,其中 url 是 url/{search item} 并遍历搜索名称列表。然后对于每个搜索项 --> 搜索页面,获取每个列表的名称、价格和图像 url。现在出现错误,找不到选择器。感谢您对此的任何帮助,非常感谢!

网站数据布局如下:

<div class="items-box-content">
   <section class="items-box">
      <a href="https://listingurl">
         <figure class="items-box-photo">
            <img data-src="https://imageurl.jpg" class=" lazyloaded" src="https://imageurl.jpg">
         </figure>
         <div class="items-box-main">
            <h3 class="items-box-name"> listing name </h3>

            <div class="items-box-figure">
               <div class="items-price font-4"> $29.95 </div> // item's price
            </h3>
         </div>

而我现在拥有的是(引发错误):

const puppeteer = require('puppeteer');
const searches = ["a", "b", "c"]; //appended to url
(async () => {
   const browser = await puppeteer.launch({ headless: false });
   let results =[];
   for (const search of searches) {
         try {
            page = await browser.newPage();
            await page.goto(`https://weburl/?keyword=${search}`);
            await page.evaluate(() => { document.querySelector('div[class*="items-box"]').scrollIntoView();});
            let elements = await page.$$('div[class*="items-box"]');
            for (let element of elements) {
               let listImg = await element.$eval(('img[class="items-box-photo]'), img => img.getAttribute('src'));
               let listTitle = await element.$eval(('d[class="items-box-main"] > h[class="items-box-name"]'), node => node.innerText.trim());
               let listPrice = await element.$eval(('d[class="items-box-figure"] > d[class="items-price"]'), node => node.innerText.trim());
               let listUrl = await element.$eval(('d[class="items-box-content"] > a[class*="items-box"]'), node => node.getAttribute('href'));

               results.push({ 
                  listImg, 
                  listTitle, 
                  listPrice, 
                  listUrl 
               })
               return results;
            }
         } finally {
            await page.close
         }
   }
})();

抛出的错误是

(节点:5168)UnhandledPromiseRejectionWarning:错误:错误:未能 查找匹配选择器“img[class="items-box-photo]”的元素

【问题讨论】:

    标签: javascript node.js xpath puppeteer


    【解决方案1】:

    问题就在错误消息中 (Error: failed to find element matching selector ...)。

    选择器在以下几行中是错误的:

    let listImg = await element.$eval(('img[class="items-box-photo]'), img => img.getAttribute('src'));
    let listTitle = await element.$eval(('d[class="items-box-main"] > h[class="items-box-name"]'), node => node.innerText.trim());
    let listPrice = await element.$eval(('d[class="items-box-figure"] > d[class="items-price"]'), node => node.innerText.trim());
    let listUrl = await element.$eval(('d[class="items-box-content"] > a[class*="items-box"]'), node => node.getAttribute('href'));
    

    根据你给出的 HTML 代码,这些应该是:

    let listImg = await element.$eval('img.lazyloaded', img => img.getAttribute('src'));
    let listTitle = await element.$eval('h3.items-box-name', node => node.innerText.trim());
    let listPrice = await element.$eval('div.items-price', node => node.innerText.trim());
    let listUrl = await element.$eval('div.items-box-content a', node => node.getAttribute('href'));
    

    注意,查询类的正确方法不是使用[class=...],而是使用class selector.

    【讨论】:

    • 对于href的最后一个,它允许嵌套吗?在这种情况下,它的 div > section > a href。
    • 在我这边,工作得很好node.getAttribute('href')
    • @Thinkerer 当然,我最后使用的选择器是指adiv 内部,类items-box-content。使用选择器时不需要指定确切的层次结构(但当然可以)。代码不工作吗?
    • 我做了一些简单的调试,选择器工作正常。我把“调试器;”在“返回结果”之前,它显示了第一个列表的正确数据。问题是如果我在没有调试器的情况下运行它,它会在第一页停止。控制台中没有显示数据或错误。它应该遍历搜索关键字列表。然后对于每个关键字,打开一个页面(关键字附加到 url)并复制所有列表数据。然后使用列表中的另一个关键字关闭并打开一个新页面。页面是一页一页打开的,而不是同时打开的。
    • @Thinkerer 刚刚看到,您的循环中有 return 语句。所以在第一次迭代之后,外部函数将返回并停止。您可能希望将 return 移出循环。
    【解决方案2】:

    我用我的测试/调试更新了你的代码。

    const puppeteer = require('puppeteer');
    
    const searches = ["a"];
    
    (async () => {
    
        const browser = await puppeteer.launch({ headless: false });
    
        function delay(timeout) {
            return new Promise((resolve) => {
                setTimeout(resolve, timeout);
            });
        }
    
        let results = [];
    
        for (const search of searches) {
    
            try {
                page = await browser.newPage();
                await page.goto(`https:url/`);
    
                await page.evaluate(() => { document.querySelector('section[class*="items-box"]').scrollIntoView(); });
    
                let elements = await page.$$('section[class*="items-box"]');
                console.log(elements.length)
                console.log('wait 6  seconds')
                await delay(6000);
    
                for (let element of elements) {
                    // await delay(6000);
    
                    let listImg = await element.$eval(('img'), img => img.getAttribute('src'));
                    let listTitle = await element.$eval(('h3[class="items-box-name font-2"]'), node => node.innerText.trim());
                    let listPrice = await element.$eval(('div[class="items-box-price font-5"]'), node => node.innerText.trim());
                    let listUrl = await element.$eval(('div[class="items-box-content clearfix"] a'), node => node.getAttribute('href'));
    
                    results.push({
                        listImg,
                        listTitle,
                        listPrice,
                        listUrl
                    });
                }
    
                debugger;
    
            } catch (error) {
                console.log(error)
            } finally {
                //await page.close
                await browser.close
            }
        }
        console.log(results)
        return results;
    })();
    

    更新内容:
    1. return resultfor 循环中

    for(){
       return result;
    }
    

    =>

    for(){
    
    }
    return result;
    
    1. 更新querySelector
    section[class*="items-box"]
    
    img  // There is only one img tags in "element"
    
    h3[class="items-box-name font-2"]  // removed outer 'element'
    
    div[class="items-box-figure"] > div[class="items-price font-4"]
    
    div[class="items-box-price font-5  // updated class name? on my side 
    
    items-box-price
    
    div[class="items-box-content clearfix"] a 
    
    1. 更新睡眠持续时间 6 秒,这是相对网络速度(网络加载持续时间)。

    2. trycatchfinally
      catch帮助您处理下一步,尽管一步崩溃。

    【讨论】:

    • 带href的那一行好像也遇到了同样的错误,觉得别人不错!
    • 得到这个错误 (node:6297) UnhandledPromiseRejectionWarning: E​​rror: Error: failed to find element matching selector "div[class="items-box-content"] a"
    • 请提供您的在线网址,以供我方测试。
    • 如果 HTML 是 &lt;div class="items-box-content&gt; ?,为什么不是 &lt;div class="items-box-content"&gt;?,缺少 "
    • 对不起你的权利。它的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    相关资源
    最近更新 更多