Парсинг данных столбцов таблицы HTML с помощью scrapy и xpath
Нужно сделать паука, который будет следующие данные по странам:
- '#' (Стартовая страница)
- Страна (Стартовая страница)
- Население (Стартовая страница)
- Городское население (Страницы стран)
- Мировое население (Страницы стран)
Стартовая ссылка: https://www.worldometers.info/world-population/population-by-country/
На страницах стран таблицы имеют разное количестве столбцов, из-за чего некорректно указать в xpath индекс конкретного td, где содержатся данные городского и мирового населения.
Сначала я попробовала использовать count(), чтобы посчитать номер строки нужных заголовков. Но функция count() почему-то не работает:
urban = row.xpath('.//tbody/tr[td[normalize-space(text())="2023"]]/td[count(thead/tr/th[normalize-space(text())="Urban Population"]/preceding-sibling::*)+1]/text()').get().replace(',', '') # if float(row.xpath('.//td[6]/text()').get().replace(',', '')) else row.xpath('.//td[6]/text()').get().replace(',', '')
world = row.xpath('.//tbody/tr[td[normalize-space(text())="2023"]]/td[count(thead/tr/th[normalize-space(text())="World Population"]/preceding-sibling::*)+1]/text()').get().replace(',', '')
Затем попробовала собрать заголовки в список, чтобы по индексу найти нужную td и применить полученную строку в xpath. Но здесь есть ошибка, заголовки не собираются в список:
def parse_country(self, response):
headers = response.xpath("//div[5]/table/thead/tr")
headers_list = []
for head in headers.xpath('.//*th/text()').get():
headers_list.append(head)
urban_link = f'.//tr[td[normalize-space(text())="2023"]]/td[{headers_list.index("Urban Population") + 1}]/text()'
world_link = f'.//tr[td[normalize-space(text())="2023"]]/td[{headers_list.index("World population") + 1}]/text()'
rows = response.xpath("//div[5]/table/tbody")
for row in rows:
urban = row.xpath(urban_link).get().replace(',', '')
world = row.xpath(world_link).get().replace(',', '')
Может есть более оптимальное решение?
Ответы (1 шт):
Вопрос решен без применения count():
response = response.replace(body=re.sub(
b'</?\s*\s*br\s*/?\s*>', b'', response.body))
response = response.replace(body=re.sub(
b'</?\s*\s*br\s*/?\s*>', b'', response.body))
headers = [head.strip() for head in response.xpath(
"//div[5]/table/thead/tr/th/text()").getall() if head.strip()]
datas = [data.strip() for data in response.xpath(
"//div[5]/table/tbody/tr/td/text()").getall() if data.strip()]