【问题标题】:lxml python load html string without header and body and add element around targeted elementslxml python加载没有标题和正文的html字符串并在目标元素周围添加元素
【发布时间】:2013-12-18 01:01:42
【问题描述】:

我正在尝试使用 lxml 从字符串中读取 html,然后尝试查找所有 img 标签,更新图像 src 的属性并在找到的每个图像周围添加超链接

这样,

<img src="old-value" />

会这样

<a href=""><img src="new-value" /></a>

我面临的问题是两个,首先是使用 etree.HTML 加载 html 字符串,由于某种原因,它正在向 html 本身添加 html 标记和 body 标记。有没有办法加载它而不自动导致这种情况发生?

另一个问题无法解决,如何在图像标签周围添加超链接元素,我尝试了以下但它会在 img 标签内添加超链接元素

tree = etree.HTML(self.content)
imgs = tree.xpath('.//img')
thm = "new-value"
for img in imgs:
     img.set('src', thm)
     a = etree.Element('a', href="#")
     img.insert(0, a)

谁能给点建议?

更新:

我刚刚尝试了@Alko 提供的方法并且效果很好,但是它正在使用的内容类型存在问题。

img 标签位于 p 标签内,如下例所示

<html><body><p><img src="/public_media/cache/66/ed/66edd1c01e3027ba18bef9244ca8e8b4.jpg?id=31"/>jshjksh skjhs jksh skjhsj ksh jkshs kjhs kjsh sjkhs khs ksh skh skh skjh skjh skjh ksjh ksh skhs kjsh skjh skhs khs kjsh skjh skjhs kshk sjh skjhs kjsh skjh skjh ksj ksjh jsk hskjh s</p><p>jshjksh skjhs jksh skjhsj ksh jkshs kjhs kjsh sjkhs khs ksh skh skh skjh&#13;
 skjh skjh ksjh ksh skhs kjsh skjh skhs khs kjsh skjh skjhs kshk sjh &#13;
skjhs kjsh skjh skjh ksj ksjh jsk hskjh s</p></body></html>

当我运行给定的解决方案时发生了什么,在段落结尾之后添加了结束标记。

【问题讨论】:

  • 很高兴您现在开始使用LXML。您能否接受您从中获得此想法/知识的答案 - 因为它解决了您替换 src 值的问题:stackoverflow.com/questions/20595735/…
  • 我刚刚做了,谢谢乔恩 :).. 感谢您的意见

标签: python lxml


【解决方案1】:

您可以在插入之前使用addprevious:

imgs = tree.xpath('.//img')
thm = "new-value"
for img in imgs:
    img.set('src', thm)
    a = etree.Element('a', href="#")
    img.addprevious(a)
    a.insert(0, img)

这将导致

>>> etree.tostring(tree)
'<html><body><a href="#"><img src="new-value"/></a></body></html>'

另外,lxml.html.fragment_fromstring 可能很有用,但您必须提供更多样化的示例,因为在您的单独图像元素的情况下,您的 xpath 不会找到它。

请看以下演示:

>>> import lxml.html
>>> img = lxml.html.fragment_fromstring('<img src="old-value" />')
>>> thm = "new-value"
>>> img.set('src', thm)
>>> a = etree.Element('a', href="#")
>>> a.insert(0, img)
>>> lxml.html.etree.tostring(a)
'<a href="#"><img src="new-value"/></a>'

更新

对于img标签有尾的情况,可以重新分配给创建的a标签:

>>> s = '<html><body><p><img src="old_value"/>some text</p></body></html>'
>>> tree = etree.HTML(s)
>>> imgs = tree.xpath('.//img')
>>> thm = "new-value"
>>> for img in imgs:
...     img.set('src', thm)
...     a = etree.Element('a', href="#")
...     img.addprevious(a)
...     a.insert(0, img)
...     a.tail = img.tail
...     img.tail = ''
...
>>> etree.tostring(tree)
'<html><body><p><a href="#"><img src="new-value"/></a>some text</p></body></html>'

【讨论】:

  • 感谢您的快速响应,addprevious 确实有效.. 但它不会在图像后添加结束标签?对我来说,我得到 就是这样,在 img 之后没有关闭
  • @MoJ.Mughrabi 您必须添加上一个 并 插入新的 (&lt;a&gt;) 元素,请参阅我的答案中的示例
  • 我刚刚更新了问题,问题出在html本身,图像标签位于p标签内,导致使用插入时a被放置在段落之后
  • @MoJ.Mughrabi 此文本实际上是 img 元素的一部分,即 img.tail。你可以使用a.tail = img.tail; img.tail= ''
【解决方案2】:
holder = etree.Element('div', {'id': 'links'})
for img in imgs:
   a_tag = etree.SubElement( holder, {'href':'#'} )
   img_tag = etree.SubElement( a_tag, {'src': 'new_value'} ) 

etree.toString(holder)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2021-09-09
    相关资源
    最近更新 更多