私はいくつかのデータを収集するために人形遣いアプリに取り組んでいます。
このコードは正常に動作しますが、データを取得できるように改善できる可能性があります。作業できる構造化された方法でデータを取得できるように改善したいと考えています。
const table1 = await page.$$eval('table:nth-child(3) tbody', tbodys => tbodys.map((tbody) => {
return tbody.innerText;
}));
つまり、tbody を使用すると、テーブル内のタグの数に関係なく、すべての TR タグと TD タグをスクレイピングできますが、テーブルにテーブル行があり、そのテーブル行内に 2 つのテーブルセルがあるという問題があります。最初の TD は、2 番目の TD のデータのヘッダーです。
次の HTML があります:
<tr class="header1"><th colspan="2">COS-MOD-000-CAB-PAP-123202</th></tr>
body > center > table > tbody > tr:nth-child(2) > td:nth-child(2) > div:nth-child(3) > table:nth-child(3) > tbody > tr:nth-child(2)
//THIS IS THE BODY WHICH MY ORIGINAL CODE IS PULLING OUT THE TEXT OF. MY CODE LOOKS AT TDS ONLY WITHIN TRs.
<tbody><tr class="header1"><th colspan="2">COS-MOD-000-CAB-PAP-123202</th></tr>
<tr class="light">
<td style="text-align: right; width: 100px;"><strong>Status:</strong></td>//HEADER
<td valign="top">Wrong </td> //VALUE
</tr>
<tr class="dark">
<td style="text-align: right; width: 100px;"><strong>Created:</strong></td>//HEADER
<td valign="top">2019-09-09 17:18:53 </td>//VALUE
</tr>
<tr class="light">
<td style="text-align: right; width: 100px;"><strong>Modified:</strong></td>//HEADER
<td valign="top">2019-09-09 17:21:19 </td>//VALUE
</tr>
<tr class="dark">
<td style="text-align: right; width: 100px;"><strong>User:</strong></td>//HEADER
<td valign="top">fbibsan </td>//VALUE
</tr>
<tr class="light">
<td style="text-align: right; width: 100px;"><strong>BMS Account:</strong></td> //HEADER
<td valign="top">ABC123 SAS. (SAS) </td> //VALUE
</tr>
<tr class="dark">
<td style="text-align: right; width: 100px;"><strong>Mode:</strong></td>//HEADER
<td valign="top">FAF </td>//VALUE
</tr>
<tr class="light">
<td style="text-align: right; width: 100px;"><strong>Type:</strong></td>
<td valign="top">BOP </td>
</tr>
</tbody>
テーブル内の各行に必要な構造は次のとおりです。
HEADER:'VALUE'
誰かが助けてくれることを願っています。今、何日もかけて探していたので、とても感謝しています。
タスクを正しく理解していれば、テーブルから構造化データを取得する方法の簡単な例を次に示します。
const html = `
<!doctype html>
<html>
<head><meta charset='UTF-8'><title>Test</title></head>
<body>
<table><tbody>
<tr><th>Header</th><th>Header</th></tr>
<tr><td>Key 1</td><td>Value 1</td></tr>
<tr><td>Key 2</td><td>Value 2</td></tr>
</tbody></table>
</html>`;
const puppeteer = require('puppeteer');
(async function main() {
try {
const browser = await puppeteer.launch({ headless: false, defaultViewport: null });
const [page] = await browser.pages();
await page.goto(`data:text/html,${html}`);
const data = await page.evaluate(() => {
const dataObject = {};
const tbody = document.querySelector('table tbody');
for (const row of tbody.rows) {
if (!row.querySelector('td')) continue; // Skip headers.
const [keyCell, valueCell] = row.cells;
dataObject[keyCell.innerText] = valueCell.innerText;
}
return dataObject;
});
console.log(data); // { 'Key 1': 'Value 1', 'Key 2': 'Value 2' }
// await browser.close();
} catch (err) {
console.error(err);
}
})();
6
エラーが発生します: 評価に失敗しました: TypeError: プロパティ 'innerText' を読み取れません未定義の。 TR を行として定義する必要はありませんか?
– スキルを見せてください2020 年 9 月 5 日 13:27
いいえ、tbody.rows はすでにテーブルの TR です。このエラーは、TD が 2 未満の TR が存在することを意味している可能性があります。これは可能ですか?
– vsemozhebuty2020 年 9 月 5 日 13:37
エラーは、そもそもテーブル要素を見つけることにあるようです....テーブルはテーブル内のテーブルであるため、セレクターを使用して正確なテーブルを見つけることができません....これはセレクター const tbody = ドキュメントent.querySelector('テーブル:nth-child(3) tbody');それはうまくいきませんでしたが、HTML だけを使用してコードのテストを行ったところ、うまくいきました。ブラウザ内の特定のテーブルで動作させる方法はありますか?お時間と専門知識をありがとうございました!
– スキルを見せてください2020 年 9 月 5 日 13:47
表のあるページの URL を教えていただけますか?
– vsemozhebuty2020 年 9 月 5 日 13:51
OK - 問題が見つかりました - おっしゃるとおりです - テーブルの最初の TR に TD がありません....<tr class="header1"><thcolspan="2"> ;text</th></tr>...スキップできますか?
– スキルを見せてください2020 年 9 月 5 日 13:54
マップ コールバックでの tbody のタイプに応じて異なります。何らかの方法でその tbody オブジェクトを解析できることを願っています。
追加の PA が必要なだけだと思いますrsing を実行し、おそらく既存の関数にロジックを追加するだけで済みます。
私ならこうします:
const table1 = await page.$$eval('table:nth-child(3) tbody', tbodys => tbodys.map((tbody) => {
// add logic here!
let parsedTable = '';
let extractedTRs = tbody.match(/<tr>(.*?)<\/tr>/g); // find a way to deconstruct this or regex. what is the type of tbody?
extractedTRs.map( tr => {
const tr= str.match(/<td>(.*?)<\/td>/g); //this should return an array...someone check me :)
parsedTable += `tr[0]:'${tr[1]}' \n`);
}
return parsedTable;
}));
2020 年 9 月 4 日 21:49 に回答
オマールオマール
442
4
銀バッジ 4 個
10 個
銅バッジ 10 個
2
この解決策を試したところ、tr=str.match がすでに宣言されているという構文エラーが発生しました。 T彼は私の質問のHTMLコードに本文があります...それが完全な本文です。私の元のコードは trs 内の tds を取り出しますが、行の最初の列が実際にはヘッダーであり、2 番目の列が値である必要な形式ではありません。
– スキルを見せてください2020 年 9 月 4 日 22:28
ヘッダーと本文の値を明確にするために HTML コードを編集しました。
– スキルを見せてください9 月 4 日2020 年 22:36