Scrapy Xpath с текстом () содержит

#xpath #scrapy

#xpath #scrapy

Вопрос:

Я использую scrapy и пытаюсь найти интервал, содержащий определенный текст. У меня есть:

 response.selector.xpath('//*[@class="ParamText"]/span/node()')
  

который возвращает:

 <Selector xpath='//*[@class="ParamText"]/span/text()' data=u' MILES STODOLINK'>,
<Selector xpath='//*[@class="ParamText"]/span/text()' data=u'C'>,

<Selector xpath='//*[@class="ParamText"]/span/text()' data=u'  MILES STODOLINK'>]
  

Однако, когда я запускаю:

 >>> response.selector.xpath('//*[@class="ParamText"]/span[contains(text(),"STODOLINK")]')
Out[11]: []
  

Почему функция contains не работает?

Ответ №1:

contains() невозможно оценить несколько узлов одновременно :

 /span[contains(text(),"STODOLINK")]
  

Итак, в случае, если внутри есть несколько текстовых узлов span , и "STODOLINK" не находится в первом дочернем текстовом узле span , то contains() в приведенном выше выражении это не сработает. Вы должны попытаться применить contains() проверку к отдельным текстовым узлам следующим образом :

 //*[@class="ParamText"]/span[text()[contains(.,"STODOLINK")]]
  

Или, если "STODOLINK" не обязательно находится непосредственно внутри span (может быть вложен в другой элемент в span ), тогда вы можете просто использовать . вместо text() :

 //*[@class="ParamText"]/span[contains(.,"STODOLINK")]
  

Комментарии:

1. Спасибо, могу я спросить, что здесь означает «.». Я предполагаю, что «любой символ», как в регулярном выражении?

2. Это ссылка на сам элемент. Кроме того, ‘..’ — это ссылка на родительский элемент; Они работают как в системах * nix (Linux, Mac и т. Д.) Пути к файлам, Где ‘.’ — текущий каталог, а ‘..’ — родительский каталог.

Ответ №2:

В моем терминале (предполагая, что мой пример идентичен вашему файлу) ваш код работает:

Ввод

 import scrapy
example='<div class="ParamText"><span>STODOLINK</span></div>'
scrapy.Selector(text=example).xpath('//*[@class="ParamText"]/span[contains(text(),"STODOLINK")]').extract()
  

Вывод:

 ['<span>STODOLINK</span>']
  

Можете ли вы уточнить, что может быть по-другому?

Ответ №3:

Я использую Scrapy с BeautifulSoup4.0. IMO, Soup легко читать и понимать. Это вариант, если вам не нужно использовать HtmlXPathSelector . Ниже приведен пример поиска всех ссылок. Вы можете заменить это на ‘span’. Надеюсь, это поможет!

 import scrapy
from bs4 import BeautifulSoup
import Item

def parse(self, response):

    soup = BeautifulSoup(response.body,'html.parser')
    print 'Current url: %s' % response.url
    item = Item()
    for link in soup.find_all('a'):
        if link.get('href') is not None:
            url = response.urljoin(link.get('href'))
            item['url'] = url
            yield scrapy.Request(url,callback=self.parse)
            yield item