Cheerio无法正确解析HTML

时间:2019-06-19 03:48:35

标签: javascript dom web-scraping puppeteer cheerio

我有一个行数组,这些行是从html表中解析出来的,存储在一个列表中。列表中的每一行都是一个看起来像这样的字符串:

["<td headers="DOCUMENT" class="t14data"><a target="6690-Exhibit-C-20190611-1" href="http://www.fara.gov/docs/6690-Exhibit-C-20190611-1.pdf" class="doj-analytics-processed"><span style="color:blue">Click Here </span></a></td><td headers="REGISTRATIONNUMBER" class="t14data">6690</td><td headers="REGISTRANTNAME" class="t14data">SKDKnickerbocker LLC</td><td headers="DOCUMENTTYPE" class="t14data">Exhibit C</td><td headers="STAMPED/RECEIVEDDATE" class="t14data">06/11/2019</td>","<td headers="DOCUMENT" class="t14data"><a target="5334-Supplemental-Statement-20190611-30" href="http://www.fara.gov/docs/5334-Supplemental-Statement-20190611-30.pdf" class="doj-analytics-processed"><span style="color:blue">Click Here </span></a></td><td headers="REGISTRATIONNUMBER" class="t14data">5334</td><td headers="REGISTRANTNAME" class="t14data">Commonwealth of Dominica Maritime Registry, Inc.</td><td headers="DOCUMENTTYPE" class="t14data">Supplemental Statement</td><td headers="STAMPED/RECEIVEDDATE" class="t14data">06/11/2019</td>"]

使用伪指令,使用以下page.evaluate函数从页面中提取代码。

然后我想用cheerio解析此代码,我发现它更简单易懂。但是,当我将html的每个字符串传递给cheerio时,它无法正确解析它们。这是我正在使用的当前功能:

    let data = res.map((tr) => {
        let $ = cheerio.load(tr);
        const link = $("a").attr("href");
        const number = $("td[headers='REGISTRATIONNUMBER']").text();
        const name = $("td[headers='REGISTRANTNAME']").text();
        const type = $("td[headers='DOCUMENTTYPE']").text();
        const date = $("td[headers='STAMPED/RECEIVEDDATE']").text();
        return { link, number, name, type, date };
    });

由于某些原因,只有“ a”标记对于每一行都有效。这意味着“ link”变量已正确定义,但其他变量均未定义。当我使用$(“ *”)返回所有td的列表时,它返回一个不寻常的节点列表:

enter image description here

我在做什么错,我如何通过各种标题及其文本内容访问td?谢谢!

2 个答案:

答案 0 :(得分:1)

通常看起来像这样:

let data = res.map((i, tr) => {
  const link   = $(tr).find("a").attr("href");
  const number = $(tr).find("td[headers='REGISTRATIONNUMBER']").text();
  const name   = $(tr).find("td[headers='REGISTRANTNAME']").text();
  const type   = $(tr).find("td[headers='DOCUMENTTYPE']").text();
  const date   = $(tr).find("td[headers='STAMPED/RECEIVEDDATE']").text();
  return { link, number, name, type, date };
}).get();

请记住,cheerio map的参数与js map的相反。

答案 1 :(得分:0)

我找到了解决方案。我只是通过puppeteer返回完整的html,而不是尝试获取单个行,然后使用上面的建议(来自@pguardiario)来解析文本:

 const res = await page.evaluate(() => {
            return document.body.innerHTML;
        });

 let $ = cheerio.load(res);
        let trs = $(".t14Standard tbody tr.highlight-row");

 let data = trs.map((i, tr) => {
        const link = $(tr).find("a").attr("href");
        const number = $(tr).find("td[headers='REGISTRATIONNUMBER']").text();
        const registrant = $(tr).find("td[headers='REGISTRANTNAME']").text();
        const type = $(tr).find("td[headers='DOCUMENTTYPE']").text();
        const date = moment($(tr).find("td[headers='STAMPED/RECEIVEDDATE']").text()).valueOf().toString();
        return { link, number, registrant, type, date };
    });