【问题标题】:Selenium - How can I scrape this table?Selenium - 我怎样才能刮掉这张桌子?
【发布时间】:2020-07-16 12:50:01
【问题描述】:

我希望从https://www.worldometers.info/coronavirus/ 中抓取数据,但似乎表格的tr 和td 在整个行中不断变化。到目前为止,我有下面的代码,但它不起作用。

public ArrayList<Data>getAllData(){
        ArrayList<Data>allData = new ArrayList<Data>();
        try {
        Thread.sleep(10000);
        WebDriver browser = load();
        int row = browser.findElements(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr")).size();
        int col = browser.findElements(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr[1]/td")).size();
        for ( int i = 3; i < row; i++) {
            for ( int j = 1; j < col; j++) {
        Data data = new Data();
        data.setId(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setCountry(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setTotalCases(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setNewCases(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setTotalDeaths(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setNewDeaths(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setTotalRecovered(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setActiveCases(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setSeriousCases(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setTotalCasesPerMillionPop(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setTotalDeathsPerMillionPop(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setTotalTests(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());
        data.setTestsPerMillion(browser.findElement(By.xpath("/html[1]/body[1]/div[3]/div[3]/div[1]/div[4]/div[1]/div[1]/table[1]/tbody[1]/tr["+i+"]/td["+j+"]")).getText());       
        allData.add(data);
            }
        }
        browser.quit();
        browser.close();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    
        return allData;
        }

【问题讨论】:

    标签: java selenium web-scraping


    【解决方案1】:

    您当前正在做的是查找与行和列匹配的所有元素 - 但随后您正在导航表上的索引位置,而不是您找到的实际元素。

    如果您在开发工具中查看表格主体,您会发现它包含从视图中隐藏的总行数。 USA 是第 3 行(在 devtools 中突出显示),但第 4、5 和 6 行是总数。

    如果展开则列号和内容会有所不同。

    建议:

    尝试更智能的 xpath 来获取所有行:(这似乎跳过了那些标题)

    //table[@id="main_table_countries_today"]//tr[@role="row"]
    

    然后,使用 foreach 循环(不是通过 xpath 索引)迭代您找到的行元素。 并且,在该循环中,获取每行中的 td 标签。

    例如:

    public void GettingAllTheData(){
    
                //Get all the ROWS that match
                var rows = driver.findElements(By.xpath("//table[@id='main_table_countries_today']//tr[@role='row']"));
    
                //loop all rows
                for (var row : rows) {
                    //Then get the columns within the row object!
                    var cols = row.findElements(By.tagName("td"));
    
                    //replace this with writing out your data 
                    //this is jut to make sure it writes out as expected. 
                    //You might not need a second loop 
                    for (var col : cols)
                    {
                        System.out.println(col.getText());
                    }
                }
        }
    

    我不想重新创建您的数据对象,所以我只是使用打印。对我来说,这似乎始终如一地写出结果。

    第一次迭代:

    1
    USA
    3,619,643
    +2,816
    140,200
    +56
    1,646,683
    1,832,760
    16,459
    10,933
    423
    44,867,389
    135,518
    331,081,677
    

    第二次迭代:

    2
    Brazil
    1,972,072
    +1,163
    75,568
    +45
    1,366,775
    529,729
    8,318
    9,275
    355
    4,911,063
    23,098
    212,620,008
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 2010-11-21
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 1970-01-01
    • 2021-09-30
    相关资源
    最近更新 更多