Парсинг данных столбцов таблицы 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 шт):

Автор решения: warella

Вопрос решен без применения 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()]
→ Ссылка