2016-01-05 2 views
1

Я пытаюсь очистить данные с сайта с помощью этой структуры ниже. Я хочу, чтобы извлечь информацию в каждом из <li id="entry">, но обе записи должны также извлекать информацию о категории от <li id="category">/<h2>Использование осей Xpath для извлечения предыдущего элемента

<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: индекс индекса вне диапазона». Я пишу xpath предшествующий топор неправильно?

+1

Вы понимаете, что '// span' подберет все' span' элементы по всему документу и '.// span' будет ограничивать выбор« span »теми, кто находится под или ниже текущего узла, правильно? – kjhughes

+0

О, спасибо, что сообщили мне! Однако в этом случае текущие кодовые значения дают желаемый результат для annons_list и byrau_list =] – brrrglund

ответ

2

Как отметил @kjhughes в комментарии, вам нужно добавить . непосредственно перед / или //, чтобы сделать ваше XPath выражение относительно текущего контекста элемента. В противном случае выражение будет рассматриваться относительно корневого документа. И вот почему выражение /preceding::h2/text() ничего не вернуло.

В случае /, вы можете удалить его с самого начала своего выражения XPath как альтернативный способ, чтобы сделать на его относительно текущего контекста элемента:

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

Только примечание, preceding::h2 возвратит все h2 элементы, расположенные до <div class="entry-info">. Согласно HTML отвечал, я думаю, что следующее выражение XPath безопаснее от возвращения нежелательных h2 элементов (ложный положительный результат):

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

Большое спасибо, проблема решена! – brrrglund