Scrapy извлечения строк из таблицы без заголовков - PullRequest
0 голосов
/ 11 сентября 2018

Итак, я пытаюсь извлечь таблицу с веб-сайта.Это таблица из двух столбцов:

Name      Foo
Number    Foo123
Address   10
          First Drive
          London
          AB34 5FG
Region    United Kingdom

Таблица не имеет заголовков, а строка «Адрес» содержит пустые ячейки в первом столбце для второго, города, почтового индекса и т. Д.

Мне удалось получить стол, просто отлично.

table = response.xpath('//table[@id="MemberDetails"]/tr/td//text()')

Это вывод:

[<Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'Name:\xa0'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\r\nFoo\xa0\r\n'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'Number:\xa0'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\r\nFoo123\xa0\r\n'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'Address:\xa0'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\r\n(10)\xa0\r\n'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\xa0'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\r\nFirst Drive\xa0\r\n'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\xa0'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\r\nLondon\xa0\r\n'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\xa0'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\r\nAB34 5FG\xa0\r\n'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\xa0'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\r\nUnited Kingdom\xa0\r\n'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'Region:\xa0'>,
 <Selector xpath='//table[@id="MemberDetails"]/tr/td//text()' data=u'\r\nUnited Kingdom\xa0\r\n'>]

Тем не менее, я озадачен тем, как я могу разобрать таблицу в правильную структуру.

1-й вопрос: Не уверен, как мне справиться с адресным полем.2-й вопрос: это таблица из двух столбцов.При сохранении этого я хотел бы транспонировать так, чтобы «Имя, Номер, Адрес, Регион» были заголовками столбцов.

Существуют тысячи подобных страниц, которые содержат подобные данные.

Цените, если кто-то может указать мне в правильном направлении.

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

Давайте работать с образцом, который вы нам предоставили.(Работа с этой ссылкой )

Давайте посмотрим, как форматируется строка таблицы.

<tr>
<td bgcolor="#7EADAD">
<strong>Membership Name:&nbsp;</strong>
</td>
<td>
MESSRS R J &amp; L A ACTON&nbsp;
</td>
</tr>

Это здорово для нас, у нас есть разные атрибуты для заголовков изначения: заголовки находятся внутри тегов strong внутри td с, а значения bgcolor находятся непосредственно внутри их td с.

Давайте посмотрим, как выглядят пустые строки для информации об адресе:

<tr>
<td bgcolor="#7EADAD">
<strong>&nbsp;</strong>
</td>
<td>
NORTHUMBERLAND&nbsp;
</td>
</tr>

Отлично, та же структура.

Это означает, что мы можем циклически проходить все tr s и получать их данные в зависимости от атрибутов, если нам это нужно.Вот минимальный пример, который не имеет отношения к ссылкам:

for tr in response.xpath('//table[@id="MemberDetails"]/tr'):
    header = tr.xpath('td/strong/text()').extract()[0].strip()
    value = tr.xpath('td')[1].xpath('text()').extract()[0].strip()
    print(u'{} -- {}'.format(header, value))

Следующим шагом является сбор данных (создание словаря? Отдельные списки? Запись непосредственно в файлы? Это ваш выбор.).

Для работы с адресом: вы можете создать переменную адреса в цикле для tr s, которая объединяется со значением, если заголовок пуст (при условии, что пустыми являются только заголовки адреса).Примерно так (опять же <минимальный пример): </p>

for tr in response.xpath('//table[@id="MemberDetails"]/tr'):
    address = ''
    header = tr.xpath('td/strong/text()').extract()[0].strip()
    value = tr.xpath('td')[1].xpath('text()').extract()[0].strip()
    if not header: # empty strings evaluate to False
        address += '' + value

Вам также нужно будет разобраться, как обращаться с заголовками / значениями, которые хранятся в тегах a.

0 голосов
/ 11 сентября 2018

Вы можете создать словарь для всех строк в вашей таблице:

def parse(self, response):

    table_data = {}
    current_key = None

    for tr in response.xpath('//table[@id="MemberDetails"]//tr'):

        key = tr.xpath('string(./td[1])').extract_first()
        value = tr.xpath('string(./td[2])').extract_first()

        if key:
            key = key.strip()
            key = key.replace(":", "")
        if value:
            value = value.strip()

        if key:
            current_key = key

        if current_key in table_data:
            table_data[current_key] += '\n' + value
        else:
            table_data[current_key] = value

    print(table_data["Address"])
0 голосов
/ 11 сентября 2018

Вы можете сделать что-то вроде этого:

data = {}
rows = response.css('table#MemberDetails tr')
for row in rows:
   label = row.css('td:nth-child(1) strong::text').extract_first().strip()
   value = row.css('td+td::text').extract_first().strip()
   if label:
       label = label.replace(':', '')
       data[label] = value
   else:
       data['Address'] = data['Address'] + ', ' + value
print(data)

Это не работает в каждой ситуации (например, в вашей ссылке Herd Completeness of Performance Rating: метка находится в теге <a>, а значение - изображение), но у вас есть начало решения:)

Другое решение:

name = response.css('td:contains("Membership Name:") + td::text').extract_first().strip()
...
address = response.css('td:contains("Address:") + td::text').extract_first().strip()
second = response.css('tr:contains("Address:") + tr td + td::text').extract_first().strip()
city = response.css('tr:contains("Address:") + tr + tr td + td::text').extract_first().strip()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...