Python,XPath:查找所有指向图像的链接

5

我正在使用Python中的lxml来解析一些HTML,我想提取所有指向图片的链接。目前我的做法是:

//a[contains(@href,'.jpg') or contains(@href,'.jpeg') or ... (etc)]

这种方法存在一些问题:

  • 在所有情况下(包括“jpg”和“JPG”)都要列出所有可能的图像扩展名,这不够优美。
  • 在奇怪的情况下,href 可能会在字符串中间而不是在末尾包含 .jpg。

我想使用正则表达式,但失败了:

//a[regx:match(@href,'.*\.(?:png|jpg|jpeg)')]

这总是返回我所有的链接...

有人知道正确、优雅的方法来做这件事吗?或者我的正则表达式方法有什么问题吗?


好问题,+1。请看我的答案,其中包含一个解决方案,用于解决您的问题之一——查找仅以给定字符串结尾的@href。 - Dimitre Novatchev
除了其他描述子字符串的答案之外,您还可以使用translate函数进行粗略的大小写转换。translate(@href, "EGIJFNP", "egijfnp")(所有png、jpeg、gif中的字符)。 - yonran
@yonran 我不确定这是否是一个好主意,因为它将改变整个URL,而不仅仅是扩展名,我不希望发生这种情况。 - Nicu Surdu
5个回答

2
使用XPath返回所有<a>元素,并使用Python列表推导式过滤匹配您的正则表达式的元素。

也许是你的语法有问题。快速谷歌搜索建议使用 fn:matches 而不是 regx:match - Marcelo Cantos

2

替代方案:

a[contains(@href,'.jpg')]

用途:

a[substring(@href, string-length(@href)-3)='.jpg']

(对于其他可能的结尾采用相同的表达式模式。)
上述表达式是XPath 1.0等效于以下XPath 2.0表达式:
a[ends-with(@href, '.jpg')]

2

lxml支持EXSLT命名空间中的正则表达式:

from lxml import html

# download & parse web page
doc = html.parse('http://apod.nasa.gov/apod/astropix.html')

# find the first <a href that ends with .png or .jpg or .jpeg ignoring case
ns = {'re': "http://exslt.org/regular-expressions"}
img_url = doc.xpath(r"//a[re:test(@href, '\.(?:png|jpg|jpeg)', 'i')]/@href",
                    namespaces=ns, smart_strings=False)[0]
print(img_url)

1

因为没有保证链接中一定有文件扩展名,或者文件扩展名与内容不匹配(例如返回错误 HTML 的 .jpg URL),这限制了您的选择。

收集网站上所有图像的唯一正确方法是获取每个链接,然后使用 HTTP HEAD 请求查询它以查找服务器发送的 Content-type。如果内容类型为 image/(anything),则是图像,否则不是。

对常见文件扩展名的URL进行爬取可能会获得99.9%的图像。这并不优雅,但大多数HTML也不是优雅的。我建议在这种情况下满足于99.9%。额外的0.1%不值得。


0

使用:

//a[@href[contains('|png|jpg|jpeg|',
                   concat('|',
                          substring-after(substring(.,string-legth()-4),'.'),
                          '|')]]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接