Как заставить XPath выбрать несколько элементов таблицы с одинаковыми атрибутами id? - PullRequest
1 голос
/ 25 октября 2011

Я сейчас пытаюсь извлечь информацию из плохо отформатированной веб-страницы.В частности, страница использовала один и тот же атрибут id для нескольких элементов таблицы.Разметка эквивалентна примерно так:

<body>
    <div id="random_div">
        <p>Some content.</p>
        <table id="table_1">
            <tr>
                <td>Important text 1.</td>
            </tr>
        </table>
        <h4>Some heading in between</h4>
        <table id="table_1">
            <tr>
                <td>Important text 2.</td>
                <td>Important text 3.</td>
            </tr>
        </table>
        <p>How about some more text here.</p>
        <table id="table_1">
            <tr>
                <td>Important text 4.</td>
                <td>Important text 5.</td>
            </tr>
        </table>
    </div>
</body>

Очевидно, что это неправильно отформатированный HTML из-за многократного использования одного и того же идентификатора для элемента.

Я использую XPath дляпопытаться извлечь весь текст из различных элементов таблицы, используя язык через Scrapy framework.

Мой вызов выглядит примерно так:

hxs.select('//div[contains(@id, "random_div")]//table[@id="table_1"]//text()').extract()

Таким образомвыражение XPath: //div[contains(@id, "random_id")]//table[@id="table_1"]//text()

. Возвращает: [u'Important text 1.'], т. е. содержимое первой таблицы, соответствующее значению идентификатора "table_1".Мне кажется, что когда он встречает элемент с определенным идентификатором, он игнорирует любые будущие вхождения в разметке.Кто-нибудь может подтвердить это?

ОБНОВЛЕНИЕ

Спасибо за быстрый ответ ниже.Я проверил свой код на странице, размещенной локально, которая имеет тот же формат теста, что и выше, и возвращает правильный ответ, то есть

`[u'Important text 1.', u'Important text 2.', . . . . ,u'Important text 5.']`

Поэтому нет ничего плохого ни в выражении Xpath, ни в Pythonзвонки, которые я делаю.

Полагаю, это означает, что существует проблема на самой веб-странице, которая либо испортила XPath, либо html-парсер, который является libxml2.

Кто-нибудьу меня есть какой-нибудь совет относительно того, как я могу углубиться в это?

ОБНОВЛЕНИЕ 2

Я успешно изолировал проблему.Это на самом деле с базовой библиотекой синтаксического анализа, которая lxml (которая обеспечивает привязки Python для библиотеки libxml2 C.

Проблема в том, что синтаксический анализатор не может работать с вертикальными вкладками. У меня нетИдея, которая закодировала сайт, с которым я имею дело, но он состоит из полных вертикальных вкладок. Кажется, что веб-браузер может их игнорировать, поэтому запуск запросов XPath из Firebug на данном сайте, дляпример, успешны.

Далее, поскольку приведенный выше упрощенный пример не содержит вертикальных вкладок, он работает нормально. Для всех, кто сталкивался с этой проблемой в Scrapy (или вообще в python), мне помогло следующее исправление, чтобы удалить вертикальные вкладки из ответов HTML:

def parse_item(self, response):
    # remove all vertical tabs from the html response
    response.body = filter(lambda c: c != "\v", response.body)
    hxs = HtmlXPathSelector(response)
    items = hxs.select('//div[contains(@id, \"random_div\")]' \
                       '//table[@id="table_1"]//text()').extract()

Ответы [ 2 ]

1 голос
/ 25 октября 2011

С Firebug это выражение:

//table[@id='table_1']//td/text()

дает мне это:

[<TextNode textContent="Important text 1.">,
 <TextNode textContent="Important text 2.">,
 <TextNode textContent="Important text 3.">,
 <TextNode textContent="Important text 4.">,
 <TextNode textContent="Important text 5.">]

Я включил td фильтрацию, чтобы получить более хороший результат, так как в противном случае вы получите пробелы и переводы строки между тегами. Но в целом, похоже, работает.

Я заметил, что вы запрашиваете //div[contains(@id, "random_id")], в то время как ваш HTML-фрагмент содержит тег, который читает <div id="random_div"> - _id и _div отличаются. Я не знаю Scrapy, поэтому я не могу точно сказать, если это что-то делает, но разве это тоже не ваша проблема?

0 голосов
/ 25 октября 2011
count(//div[@id = "random_div"]/table[@id= "table_1"])

Этот xpath возвращает 3 для вашего образца ввода.Так что ваша проблема не в самом xpath, а в функциях, которые вы используете для извлечения узлов.

...