سؤال

لنفترض أن لدي هذا النوع من HTML الذي أحتاج منه لتحديد "Text2" باستخدام LXML / ElementTree:

<div>text1<span>childtext1</span>text2<span>childtext2</span>text3</div>

إذا كان لدي بالفعل عنصر DIV كـ MyDiv ، فإن MyDiv.Text يعيد فقط "Text1".

يبدو استخدام itertext () مشكلة أو مرهقة في أحسن الأحوال لأنه يمشي الشجرة بأكملها تحت Div.

هل هناك أي طريقة بسيطة/أنيقة لاستخراج جزء من النص غير الأول من عنصر؟

هل كانت مفيدة؟

المحلول

حسنًا ، يوفر LXML.etree دعم XPATH الكامل ، والذي يتيح لك معالجة عناصر النص:

>>> import lxml.etree
>>> fragment = '<div>text1<span>childtext1</span>text2<span>childtext2</span>text3</div>'
>>> div = lxml.etree.fromstring(fragment)
>>> div.xpath('./text()')
['text1', 'text2', 'text3']

نصائح أخرى

سيكون مثل هذا النص في tail سمات أطفال العنصر الخاص بك. إذا كان عنصرك في elem ومن بعد:

elem[0].tail

سوف يعطيك نص الذيل للطفل الأول داخل العنصر ، في حالتك "text2" أنت تبحث عن.

كما قال Llasram ، أي نص ليس في text ستكون السمة في tail سمات العقد الفرعية.

على سبيل المثال ، إليك أبسط طريقة للاستخراج الكل من قطع النص (أولاً وغيرها) في العقدة:

html = '<div>text1<span>childtext1</span>text2<span>childtext2</span>text3</div>'

import lxml.html    # ...or lxml.etree as appropriate
div = lxml.html.fromstring(html)

texts = [div.text] + [child.tail for child in div]
# Result: texts == ['text1', 'text2', 'text3']
# ...and you are guaranteed that div[x].tail == texts[x+1]
# (which can be useful if you need to access or modify the DOM)

إذا كنت تفضل التضحية بهذه العلاقة من أجل منع texts من احتواء سلاسل فارغة ، يمكنك استخدام هذا بدلاً من ذلك:

texts = [div.text] + [child.tail for child in div if child.tail]

لم أختبر هذا مع elementtree القديم البسيط ، لكن يجب أن يعمل مع ذلك أيضًا. (شيء لم يحدث لي إلا بمجرد أن رأيت محلول LXML الخاص بشين هولواي) أنا أفضل فقط LXML لأنه يحصل على دعم أفضل لـ HTML IDEOSYNCRACIS lxml.html.clean

يستخدم node.text_content() للحصول على كل النص أسفل العقدة كسلسلة واحدة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top