Вот пример таблицы данных, которую я собираю:
Элементы красного цвета находятся в тегах <th>
, в то время как элементы зеленого цвета находятся в теге <td>
, тег <tr>
может отображаться в зависимости от того, как они сгруппированы (т.е. собственный <tr>
; фрагмент HTML:
РЕДАКТИРОВАТЬ: я забыл добавить окружающий div
<div class="table-cont">
<table class="tg-1">
<thead>
<tr>
<th class="tg-phtq">ID</td>
</tr>
</thead>
<tbody>
<tr>
<td class="tg-0pky">1</td>
<td class="tg-0pky">2</td>
<td class="tg-0pky">3</td>
</tr>
</tbody>
</table>
<table class="tg-2">
<thead>
<tr>
<th class="tg-phtq">Sample1</td>
<th class="tg-phtq">Sample2</td>
<...the rest of the table code matches the pattern...>
</tr>
</thead>
<tbody>
<tr>
<td class="tg-0pky">Swimm</td>
<td class="tg-dvpl">1:30</td>
<...>
</tr>
</tbody>
<...the rest of the table code...>
</table>
</div>
Как вы можете видеть, в HTML это фактически две разные таблицы, а в приведенном выше примере они отображаются только как одна. Я хочу сгенерировать объект JSON, в котором keys
и values
включают данные из двух таблиц, как если бы они были одной, и вывести один объект JSON.
Как я сейчас это делаю, это немного модифицированный код JavaScript, который я нашел в учебнике:
РЕДАКТИРОВАТЬ: ниже я пытался найти способ выбрать все соответствующие теги <th>
из обеих таблиц и вставить их в тот же массив, что и остальные массивы тегов <th>
, и сделать то же самое для <tr>
в теле таблицы; Я вполне уверен, что th
я могу просто вставить элемент отдельно перед остальными, но только потому, что есть один - у меня возникли проблемы с выяснением, как это сделать для обоих массивов, и чтобы убедиться, что все элементы в два массива корректно отображаются друг на друга
РЕДАКТИРОВАТЬ 2: Возможное решение? Я пытался использовать XPath Selectors
, и я могу использовать их в devTools, чтобы выбрать все, что я хочу, но page.evaluate
не принимает их и page.$x('XPath')
возвращает JSHandle@node
поскольку я пытаюсь создать массив, но я не знаю, куда идти дальше
let scrapeMemberTable = async (page) => {
await page.evaluate(() => {
let ths = Array.from(document.querySelectorAll('div.table-cont > table.tg-2 > thead > tr > th'));
let trs = Array.from(document.querySelectorAll('div.table-cont > table.tg-2 > tbody > tr'));
// the above two lines of code are the main problem area- I haven't been
//able to select all the head/body elements I want in just those two lines of code
// just removig the table id "tg-2" seems to deselect the whole thing
const headers = ths.map(th => th.textContent);
let results = [];
trs.forEach(tr => {
let r = {};
let tds = Array.from(tr.querySelectorAll('td')).map(td => td.textContent);
headers.forEach((k,i) => r[k] = tds[i]);
results.push(r);
});
return results; //results is OBJ in JSON format
}
}
...
results = results.concat( //merge into one array OBJ
await scrapeMemberTable(page)
);
...
Намеченный результат:
[
{
"ID": "1", <-- this is the goal
"Sample1": "Swimm",
"Sample2": "1:30",
"Sample3": "2:05",
"Sample4": "1:15",
"Sample5": "1:41"
}
]
Фактический результат:
[
{
"Sample1": "Swimm",
"Sample2": "1:30",
"Sample3": "2:05",
"Sample4": "1:15",
"Sample5": "1:41"
}
]