首页 文章

使用Xpath轴提取前一个元素

提问于
浏览
1

我正在尝试使用以下结构从网站上抓取数据 . 我想在每个 <li id="entry"> 中提取信息,但是这两个条目也应该从 <li id="category"> / <h2> 中提取类别信息

<ul class="html-winners">
    <li id="category">
        <h2>Redaktionell Print - Dagstidning</h2>
        <ul>
            <li id="entry">
                <div class="entry-info">
                    <div class="block">
                        <img src="bilder/tumme10/4.jpg" width="110" height="147">
                        <span class="gold">Guld: Svenska Dagbladet</span><br>
                         <strong><strong>Designer:</strong></strong> Anna W Thurfjell och SvD:s medarbetare<br>
                       <strong><strong>Motivering:</strong></strong> "Konsekvent design som är lätt igenkänningsbar. Små förändringar förnyar ständigt och blldmotiven utnyttjas föredömligt."
                    </div>
                </div>
          </li>
          <li  id="entry">
               <div class="entry-info">
                    <div class="block"><img src="bilder/tumme10/3.jpg" width="110" height="147">
                        <span class="silver">Silver: K2 - Kristianstadsbladet</span>
                    </div>
               </div>
            </li>
        </ul>
    </li>

我使用scrapy与以下代码:

start_urls = [
    "http://www.designpriset.se/vinnare.php?year=2010"
]

rules = (
    Rule(LinkExtractor(allow = "http://www.designpriset.se/", restrict_xpaths=('//*[@class="html-winners"]')), callback='parse_item'),
)

def parse(self, response):
    for sel in response.xpath('//*[@class="entry-info"]'):
        item = ByrauItem()
        annons_list = sel.xpath('//span[@class="gold"]/text()|//span[@class="silver"]/text()').extract()
        byrau_list = sel.xpath('//div/text()').extract()
        kategori_list = sel.xpath('/preceding::h2/text()').extract()
        for x in range(0,len(annons_list)):
            item['Annonsrubrik'] = annons_list[x]
            item['Byrau'] = byrau_list[x]
            item['Kategori'] = kategori_list[x]
            yield item

annons_list和byrau_list工作得很完美,他们使用xpath从起点 //*[@class="entry-info"] 开始下去 . 但是kategori_list给了我"IndexError: list index out of range" . 我是用错误的方式写出xpath之前的xpath吗?

1 回答

  • 2

    正如@kjhughes在评论中所提到的,您需要在 /// 之前添加 . ,以使您的XPath表达式相对于当前上下文元素 . 否则,表达式将被视为相对于根文档 . 这就是为什么表达式 /preceding::h2/text() 什么也没有返回 .

    对于 / ,您也可以将其从XPath表达式的开头删除,作为相对于当前上下文元素的替代方法:

    kategori_list = sel.xpath('preceding::h2/text()').extract()
    

    只需注意, preceding::h2 将返回位于 <div class="entry-info"> 之前的所有 h2 元素 . 根据发布的HTML,我认为以下XPath表达式更容易返回不需要的 h2 元素(误报):

    query = 'parent::li/parent::ul/preceding-sibling::h2/text()'
    kategori_list = sel.xpath(query).extract()
    

相关问题