【问题标题】:iterate through div elements遍历 div 元素
【发布时间】:2020-07-16 15:55:12
【问题描述】:

我是使用 puppeteer 进行 javascript 和网络抓取的完整初学者,我正在尝试获得简单的欧洲联赛回合的分数 https://www.euroleague.net/main/results?gamenumber=28&phasetypecode=RS&seasoncode=E2019

通过上面的分数列表inspecting,我发现分数列表是一个div 元素,其中包含其他divs 并显示统计信息。

HTML 用于两队之间的单场比赛(此示例下方的比赛有更多 div)

//score list 
    <div class="wp-module wp-module-asidegames wp-module-5lfarqnjesnirthi">
//the data-code increases to "euro_245" ...
    <div class="">      
        <div class="game played" data-code="euro_244" data-date="1583427600000" data-played="1">
            <a href="/main/results/showgame?gamecode=244&amp;seasoncode=E2019" class="game-link">
                <div class="club">
                    <span class="name">Zenit St Petersburg</span> 
                        <span class="score homepts winner">76</span>
                </div>
                <div class="club">
                    <span class="name">Zalgiris Kaunas</span>  
                        <span class="score awaypts ">75</span>
                </div>
                <div class="info">

                        <span class="date">March 5 18:00 CET</span>
                    <span class="live">
                        LIVE <span class="minute"></span>
                    </span>
                    <span class="final">
                        FINAL
                    </span>
                </div>
            </a>
        </div>
       //more teams 
    </div>
        
</div>

我想要的是遍历外部 div 元素,并获取参赛球队和每场比赛的得分,并将它们存储在 json 文件中。但是,由于我是一个完整的初学者,我不明白如何遍历上面的 html。 这是我获取元素的网页抓取代码:

const puppeteer = require('puppeteer');


const sleep = (delay) => new Promise((resolve) => setTimeout(resolve,delay));

async function getTeams(url){


const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);

await sleep(3000);

const games = await page.$x('//*[@id="main-one"]/div/div/div/div[1]/div[1]/div[3]');
//this is where I will execute the iteration part to get the matches with their scores 
await sleep(2000);


await browser.close();
}

getTeams('https://www.euroleague.net/main/results?gamenumber=28&phasetypecode=RS&seasoncode=E2019');

如果您能指导我完成迭代部分,我将不胜感激。 提前谢谢你

【问题讨论】:

    标签: javascript html web-scraping puppeteer


    【解决方案1】:

    游戏框最准确的选择器是div.game.played(一个同时具有.game.played CSS 类的div),您需要计算符合此条件的元素。 page.$$eval (page .$$eval (selector, pageFunction[, ...args])) 可以在页面内运行 Array.from(document.querySelectorAll(selector)) 并将其作为第一个参数传递给 pageFunction

    当我们为特定数据字段使用元素索引时,我们使用元素的长度运行常规 for 循环。

    如果您需要特定范围的“euro_xyz”,您可以使用page.evaluate 方法在Element.getAttribute 中获取data-code 属性值,并根据所需的“xyz”数字检查它们的数字。

    为了收集每个游戏的数据,我们可以定义一个收集器数组 (gameObj),它可以随着每次迭代而扩展。在每次迭代中,我们用实际数据填充 actualGame 对象。

    确定哪个child elements 包含相应的数据值很重要,例如:主俱乐部的名称是'div.game.played &gt; a &gt; div:nth-child(1) &gt; span:nth-child(1)' div 子编号选择俱乐部,而跨度子编号在俱乐部名称和积分之间决定。循环的[i] 索引负责获取正确的游戏框的值(这就是它在开始时被计算的原因)。

    例如:

    const allGames = await page.$$('div.game.played')
    const allGameLength = await page.$$eval('div.game.played', el => el.length)
    const gameObj = []
    for (let i = 0; i < allGameLength; i++) {
      try {
        let dataCode = await page.evaluate(el => el.getAttribute('data-code'), allGames[i])
        dataCode = parseInt(dataCode.replace('euro_', ''))
    
        if (dataCode > 243) {
          const actualGame = {
            homeClub: await page.evaluate(el => el.textContent, (await page.$$('div.game.played > a > div:nth-child(1) > span:nth-child(1)'))[i]),
            awayClub: await page.evaluate(el => el.textContent, (await page.$$('div.game.played > a > div:nth-child(2) > span:nth-child(1)'))[i]),
            homePoints: await page.evaluate(el => el.textContent, (await page.$$('div.game.played > a > div:nth-child(1) > span:nth-child(2)'))[i]),
            awayPoints: await page.evaluate(el => el.textContent, (await page.$$('div.game.played > a > div:nth-child(2) > span:nth-child(2)'))[i]),
            gameDate: await page.evaluate(el => el.textContent, (await page.$$('div.game.played > a > div:nth-child(3) > span:nth-child(1)'))[i])
          }
          gameObj.push(actualGame)
        }
      } catch (e) {
        console.error(e)
      }
    }
    
    console.log(JSON.stringify(gameObj))
    

    puppeteer 中有一个 page.waitFor 方法,其目的与您的 sleep 函数相同,但您也可以等待选择器出现 (page.waitForSelector)。

    【讨论】:

      猜你喜欢
      • 2017-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      • 1970-01-01
      • 1970-01-01
      • 2011-03-02
      相关资源
      最近更新 更多