首页 > 解决方案 > 遍历 div 元素

问题描述

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

在此处输入图像描述

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

HTML 对于 2 支球队之间的单场比赛(此示例下方的比赛有更多 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');

感谢您帮助指导我完成迭代部分。先感谢您

标签: javascripthtmlweb-scrapingpuppeteer

解决方案


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

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

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

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

确定哪些子元素包含相应的数据值很重要,例如:主俱乐部的名称是'div.game.played > a > div:nth-child(1) > 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)。


推荐阅读