Углубление с помощью узла xpath()

Я пытаюсь найти окружающий текст всех гиперссылок в абзацах на страницах Википедии, и то, как я это делаю, включает использование xpath tree.xpath("//p/node()"). С большинством ссылок все работает нормально, и я могу найти большинство вещей, которые <Element a at $mem_location$>. Однако, если гиперссылка выделена курсивом (см. пример ниже), xpath node() видит ее только как <Element i at $mem_location> и не смотрит глубже.

Это приводит к тому, что мой код пропускает гиперссылки и нарушает индексацию остальной части страницы.

Ex:

<p>The closely related term, <a href="/wiki/title="Mange">mange</a>,
is commonly used with <a href="/wiki/Domestic_animal" title="Domestic animal" class="mw-redirect">domestic animals</a> 
(pets) and also livestock and wild mammals, whenever hair-loss is involved. 

<i><a href="/wiki/Sarcoptes" title="Sarcoptes">Sarcoptes</a></i> 
and <i><a href="/wiki/Demodex" title="Demodex">Demodex</a></i> 
species are involved in mange, both of these genera are also involved in human skin diseases (by 
convention only, not called mange). <i>Sarcoptes</i> in humans is especially 
severe symptomatically, and causes the condition known as 
<a href="/wiki/Scabies" title="Scabies">scabies</a>.</p>

node() правильно захватывает "чесотку", "домашнее животное" и "чесотку", но в значительной степени пропускает "саркопты" и "демодекс" и портит индексацию, так как я отфильтровываю узлы, которые являются <Element a at $mem_location$>, а не <Element i at $mem_location$>.

Есть ли способ заглянуть глубже с node()? Я не мог найти ничего в документации об этом.

Редактировать: сейчас мой xpath равен "//p/node()", но он захватывает только самый внешний слой элемента. В большинстве случаев это <a>, и это здорово, но если он заключен в слой <i>, он захватывает только его. Я спрашиваю, есть ли способ проверить глубже, чтобы найти <a> внутри оболочки <i>.

Соответствующий код приведен ниже: tree = etree.HTML(read)

titles = list(tree.xpath('//p//a[contains(@href,\"/wiki/\")]/@title')) #extracts the titles of all hyperlinks in section paragraphs
hyperlinks = list(tree.xpath('//p//a[contains(@href,\"/wiki/\")]/text()'))
b = list(tree.xpath("//p/b/text()")) #extracts all bolded words in section paragraphs
t = list(tree.xpath("//p/node()"))

b_count = 0
a_count = 0
test = []
for items in t:
print items
items = str(items)
if "<Element b" in str(items):
  test.append(b[b_count])
  b_count += 1
  continue
if "<Element a" in str(items):
  test.append((hyperlinks[a_count],titles[a_count]))
  a_count +=1
  continue

if "<Element " not in items:
  pattern = re.compile('(\t(.*?)\n)')
  look = pattern.search(str(items))

  if look != None: #if there is a match
    test.append(look.group().partition("\t")[2].partition("\n")[0])

  period_pattern = re.compile("(\t(.*?)\.)")
  look_period = period_pattern.search(str(items))
  if look_period != None:
    test.append(look_period.group().partition("\t")[2])

person Try431    schedule 18.06.2015    source источник
comment
Какой код вы используете до сих пор?   -  person Anand S Kumar    schedule 18.06.2015
comment
В переменной t вам нужны все элементы b и a? что именно вы хотите в переменной t?   -  person Anand S Kumar    schedule 18.06.2015
comment
t содержит все элементы, проанализированные xpath, поэтому это список всего, что есть в абзаце. Ниже print t[:15] [<Element b at 0x7f59228cf248>, ' is an ', <Element a at 0x7f5922947368>, ' with ', <Element a at 0x7f59229473b0>, '.', <Element sup at 0x7f59228cf2d8>, '\n', 'There are several complications with the terminology:\n', 'Acariasis is a term for a ', <Element a at 0x7f5922947440>, ', caused by mites, sometimes with a papillae (', <Element a at 0x7f59228cf3b0>, '), and usually accompanied by severe ', <Element a at 0x7f5922947488>]   -  person Try431    schedule 18.06.2015


Ответы (1)


Я не могу придумать прямой xpath, который может помочь, но вы всегда можете просмотреть содержимое и отфильтровать такие элементы:

for i,x in enumerate(t):
    if x.tag == i:
        aNodes = x.find('a')
        if aNodes is not None and len(aNodes) > 0:
            del t[i]
            for j, y in enumerate(x.findall('/nodes()')): #doing x.findall to take in text elements as well as a elements.
                t.insert(i+j,y)

Это также обработает несколько a внутри одного i, например <i><a>something</a><a>blah</a></i>

person Anand S Kumar    schedule 18.06.2015