【问题标题】:Python, XPath: Find all links to imagesPython、XPath:查找所有图片链接
【发布时间】:2015-01-24 00:45:45
【问题描述】:

我在 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。
  • 除了描述子字符串的其他答案外,您还可以使用 translate 函数进行粗略的大小写转换。 translate(@href, "EGIJFNP", "egijfnp") (png、jpeg、gif 中的所有字符)。
  • @yonran 我不知道这是不是个好主意,因为它还会改变 URL 的其余部分,不仅是扩展名,而且我不希望这样

标签: python xpath lxml


【解决方案1】:

代替

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

使用

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

(以及其他可能的结尾的相同表达模式)。

以上表达式是 XPath 1.0 等价于以下 XPath 2.0 表达式

a[ends-with(@href, '.jpg')]

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 也许这是你的语法。一个快速的谷歌建议fn:matches而不是regx:match
    【解决方案3】:

    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)
    

    【讨论】:

      【解决方案4】:

      因为根本无法保证链接具有文件扩展名,或者文件扩展名甚至与限制您选择的内容(例如,.jpg URL 返回错误 HTML)匹配。

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

      抓取常见文件扩展名的 URL 可能会得到 99.9% 的图像。它并不优雅,但大多数 HTML 也不是。在这种情况下,我建议乐于接受 99.9%。额外的 0.1% 是不值得的。

      【讨论】:

        【解决方案5】:

        用途:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-03-17
          • 2021-05-02
          • 1970-01-01
          • 1970-01-01
          • 2020-07-21
          • 2016-01-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多