Python BeautifulSoup экстракта тэкст паміж элементам

Я спрабую атрымаць «ГЭТА ТЭКСТ» з наступнага HTML:

<html>
<body>
<table>
   <td class="MYCLASS">
      <!-- a comment -->
      Text
      
something

THIS IS MY TEXT
something else


</td> </table> </body> </html>

Я паспрабаваў гэта так:

soup = BeautifulSoup(html)

for hit in soup.findAll(attrs={'class' : 'MYCLASS'}):
    print hit.text

Але я атрымліваю ўвесь тэкст паміж усімі укладзенымі тэгамі плюс каментаром.

Можа хто-небудзь дапамагчы мне, каб проста атрымаць «ГЭТА ТЭКСТ» з-за гэтага?

24

7 адказы

Даведайцеся больш аб тым, як арыентавацца праз дрэва разбору ў BeautifulSoup </а >. Разбіраем дрэва мае тэгі і NavigableStrings (як ГЭТА ТЭКСТ). прыклад

from BeautifulSoup import BeautifulSoup 
doc = ['<html><head><title>Page title</title></head>',
       '<body>
This is paragraph one.', '
This is paragraph two.', '</html>'] soup = BeautifulSoup(''.join(doc)) print soup.prettify() # <html> # <head> # <title> # Page title # </title> # </head> # <body> #
# This is paragraph # # one # # . #
#

# This is paragraph # # two # # . #

# </body> # </html>

Для перамяшчэння ўніз па дрэве сінтаксічнага аналізу ў вас ёсць змесціва і радок .

  •   <�Р> змест з'яўляецца спарадкаваны спіс тэгаў і аб'ектаў NavigableString   ўтрымліваецца ў межах элемента старонкі </р>
  •   <�Р>, калі тэг мае толькі адзін даччыны вузел, а даччыны вузел з'яўляецца радком,   даччыны вузел становіцца даступным, як tag.string, а таксама   tag.contents [0] </р>

Для вышэй, гэта значыць вы можаце атрымаць

soup.b.string
# u'one'
soup.b.contents[0]
# u'one'

Для некалькіх даччыных вузлоў, вы можаце мець, напрыклад,

pTag = soup.p
pTag.contents
# [u'This is paragraph ', one, u'.']

so here you may play with contents and get contents at the index you want.

Вы таксама можаце перабіраць тэг, гэта ярлык. Напрыклад,

for i in soup.body:
    print i
# 
This is paragraph one.
#

This is paragraph two.

26
дададзена
так што тут вы можаце гуляць з утрыманнем і атрымаць змесціва на індэкс вы хочаце.
дададзена аўтар octoback, крыніца
адказ на пытанне
дададзена аўтар octoback, крыніца
<�Код> hit.string гэта None і hit.contents [0] гэта і '\ п' , таму калi ласка, падайце адказ для прыкладу ад пытання.
дададзена аўтар Cristian Ciupitu, крыніца
12
дададзена
Што азначае лік 6 азначае?
дададзена аўтар User, крыніца
@ Ɥɔǝnqɹǝƃloɥ Нажаль, няма. Магчыма выкарыстоўваць адказы іншых людзей
дададзена аўтар TerryA, крыніца
@User З .contents вяртае спіс, мы атрымліваем 7-й элемент са спісу (г.зн. 6-й індэкса), які з'яўляецца тэкстам
дададзена аўтар TerryA, крыніца
Дзякуй, але тэкст не заўсёды на тым жа месцы. Ці будзе гэта працаваць у любым выпадку?
дададзена аўтар ɥɔǝnq ɹǝƃloɥ, крыніца

Выкарыстоўвайце .children замест гэтага:

from bs4 import NavigableString, Comment
print ''.join(unicode(child) for child in hit.children 
    if isinstance(child, NavigableString) and not isinstance(child, Comment))

Так, гэта крыху танца.

выхад:

>>> for hit in soup.findAll(attrs={'class' : 'MYCLASS'}):
...     print ''.join(unicode(child) for child in hit.children 
...         if isinstance(child, NavigableString) and not isinstance(child, Comment))
... 




      THIS IS MY TEXT
10
дададзена
@CristianCiupitu: Вядома, вы маеце рацыю, не звяртаючы ўвагі тут. Абнаўленне.
дададзена аўтар Martijn Pieters, крыніца
Гэта адзінае рашэнне, якое не залежыць ад тэксту, знаходзячыся ў паслядоўнасці або пазіцыйным суадносінах для канкрэтнага сябра, а хутчэй цягне ўвесь тэкст з названага тэга/элемента, ігнаруючы тэкст (ці іншае змесціва) даччыныя тэгі/элементаў. Дзякуй! Гэта нязручна, але гэта працуе і вырашае маю праблему (я не ОП, але была падобная неабходнасць).
дададзена аўтар geewiz, крыніца
Гэта будзе вяртаць і '\ на каментар \ NTEXT \ Nsomething \ N гэта мой TEXT \ п нешта яшчэ \ N' або u'a commentTextsomethingTHIS МОЯ TEXTsomething яшчэ ', які больш тэксту, чым патрабуецца.
дададзена аўтар Cristian Ciupitu, крыніца

з вашым уласным аб'ектам супу:

soup.p.next_sibling.strip()
  1. you grab the

    directly with soup.p *(this hinges on it being the first

    in the parse tree)

  2. then use next_sibling on the tag object that soup.p returns since the desired text is nested at the same level of the parse tree as the
  3. .strip() is just a Python str method to remove leading and trailing whitespace

* У адваротным выпадку проста знайсці элемента выкарыстоўваючы ваш выбар фільтр (ы)

ў інтэрпрэтатару гэта выглядае прыкладна так:

In [4]: soup.p
Out[4]: 
something

In [5]: type(soup.p) Out[5]: bs4.element.Tag In [6]: soup.p.next_sibling Out[6]: u'\n THIS IS MY TEXT\n ' In [7]: type(soup.p.next_sibling) Out[7]: bs4.element.NavigableString In [8]: soup.p.next_sibling.strip() Out[8]: u'THIS IS MY TEXT' In [9]: type(soup.p.next_sibling.strip()) Out[9]: unicode
9
дададзена
Не маглі б вы дадаць трохі больш тлумачальны тэкст аб тым, што гэта адказ на гэтае пытанне?
дададзена аўтар Andy Jones, крыніца
рад! (Глядзі вышэй)
дададзена аўтар Gregory Kremler, крыніца

Short answer: soup.findAll('p')[0].next

Рэальны адказ: Вы павінны інварыянтная кропка адліку, з якой вы можаце дабрацца да вашай мэты.

Вы згадваеце ў сваім камэнтары да адказу Haidro, што тэкст, які вы хочаце, не заўсёды ў тым жа месцы. Знайсці сэнс, у якім ён знаходзіцца ў тым жа месцы адносна некаторага элемента. Затым высветліць, як зрабіць BeautifulSoup перамяшчацца па дрэве сінтаксічнага разбору наступны гэтага інварыянтнай шляху.

Напрыклад, у HTML вы дае ў зыходным паведамленні, мэтавая радок з'яўляецца адразу пасля першага элемента абзаца, і гэты пункт не з'яўляецца пустым. Так як FindAll ( 'р') будзе знайсці элементы абзаца, soup.find ( 'р') [0] будзе першы абзац элемента.

Вы маглі б у гэтым выпадку выкарыстанне soup.find ( «р») , але soup.findAll ( «р») [п] больш агульны характар, паколькі можа быць ваш фактычны сцэнар мае патрэбу пяты абзац ці нешта падобнае.

<�Код> Наступны атрыбут поля будзе наступным разабраны элемент дрэва, у тым ліку дзяцей. Так soup.findAll ( 'р') [0] .next ўтрымлівае тэкст абзаца, а soup.findAll ( 'р') [0] .next.next </код > верне вашу мэта ў HTML пры ўмове.

6
дададзена
soup = BeautifulSoup(html)
for hit in soup.findAll(attrs={'class' : 'MYCLASS'}):
  hit = hit.text.strip()
  print hit

Гэта будзе друкаваць: ГЭТА ТЭКСТ Паспрабуйце гэта ..

0
дададзена

BeautifulSoup дакументацыя прыведзены прыклад аб выдаленні аб'ектаў з дакумента з выкарыстаннем экстракта метад. У наступным прыкладзе мэта складаецца ў тым, каб выдаліць усе каментары з дакумента:

<�Моцны> Выдаленне элементаў

<�Р> Калі ў вас ёсць спасылка на элемент, вы можаце капіяваць яго з   дрэва з метадам экстракта. Гэты код выдаляе ўсе каментары   з дакумента:
from BeautifulSoup import BeautifulSoup, Comment
soup = BeautifulSoup("""1<!--The loneliest number-->
                    2<!--Can be as bad as one-->3""") comments = soup.findAll(text=lambda text:isinstance(text, Comment)) [comment.extract() for comment in comments] print soup # 1 # 23
0
дададзена