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

时间:2010-12-01 21:06:44

标签: python xpath lxml

我在Python中使用lxml来解析一些HTML,我想提取所有链接到图像。我现在这样做的方式是:

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

这种方法存在一些问题:

  • 你必须在所有情况下列出所有可能的图片扩展名(“jpg”和“JPG”),这不是很优雅
  • 在奇怪的情况下,href可能在中间某处包含.jpg,而不是在字符串的末尾

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

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

这一直让我回复了所有链接......

有没有人知道正确,优雅的方式来做这个或我的正则表达式方法有什么问题?

5 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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 :(得分: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)

答案 3 :(得分:1)

因为无法保证链接完全具有文件扩展名,或者文件扩展名甚至与内容(例如返回错误HTML的.jpg网址)相匹配,这限制了您的选项。

从站点收集所有图像的唯一正确方法是获取每个链接,并使用HTTP HEAD请求查询它,以找出服务器为其发送的内容类型。如果内容类型是图像/(任何),那么它就是图像,否则就不是。

抓取常见文件扩展名的网址可能会让你获得99.9%的图片。它并不优雅,但大多数HTML都不是。我建议很高兴在这种情况下满足99.9%。额外的0.1%是不值得的。

答案 4 :(得分:0)

使用:

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