使用 Swift 汤从任何网站抓取产品价格

Scrape product price from any Website using Swift Soup

在我的应用程序中,我想抓取任何产品的价格(用户输入想要的 URL)。

我现在搜索了很多,发现有几个 Webscrapers,我想我现在会使用 SwiftSoup。但是,我找不到一个教程来教授如何 scrape 用于 "dynamic" tags 的元素。例如,网站上产品的 price 每个网站看起来都不一样:

示例 1:

<div class="price">82 EUR</div>

示例 2:

<span class="gl-price__value">€ 139,95</span>

示例 3:

<span id="priceblock_ourprice" class="a-size-medium a-color-price priceBlockBuyingPriceString">79,99&nbsp;€</span>

我知道我可以 scrape 这样的元素:

let html: String = "<a id=1 href='?foo=bar&mid&lt=true'>One</a> <a id=2 href='?foo=bar&lt;qux&lg=1'>Two</a>";
let els: Elements = try SwiftSoup.parse(html).select("a");
for element: Element in els.array(){
    print(try element.attr("href"))
}

但是动态 scrape 的最佳方式是什么?在这上面找不到任何东西,所以我很高兴得到每一个帮助:)

更新

如果我知道确切的 'class-name' :

我设法得到正确的 'price'
let url = "https://www.adidas.de/adistar-trikot/CV7089.html"
    let className = "gl-price__value"


    do {
        let html: String = getHTMLfromURL(url: url)
        let doc: Document = try SwiftSoup.parse(html)

        let price: Element = try doc.getElementsByClass(className).first()!
        let priceText : String = try price.text()

        result.text = priceText

    } catch Exception.Error(let type, let message) {
        print(message)
    } catch {
        print("error")
    }

但是,我想让这个工作,所以上面的所有 3 个示例都可以工作。现在我正在努力获得包含所有三个示例的正确 'regex'...有人有想法吗?

我不认为有一种方法可以抓取几乎任何东西 "dynamically"。您无法检测人们在向您展示价格时可以写下 html 的所有可能方式。

您可以做的是训练机器学习模型来检测价格大多数时候,但我认为这不会那么容易。但这可能超出了这个问题的范围。

您可以尝试的另一种方法是简单地查看大多数网站并添加几个 "generic" 算法来抓取他们的网站。如果一个不起作用,您只需尝试另一个,直到您成功或放弃。这样,避免对 class 名称和其他内容进行硬编码,您至少会抓取所有与通用抓取器中的结构相似的网站。

一种方法(但我相信你可以想到其他更好的方法)我将采用 "generic" 抓取算法的实现方法是拥有 class 的正则表达式列表匹配价格并尝试全部尝试,然后尝试验证您在 html 文本中获得的结果(例如,文本中是否有任何数字?它是否包含 €、$、..?等符号。 ). 我会从 .*price.* 和其他类似的正则表达式开始,你可以通过查看大多数站点简单地找到。

你肯定会在一些你没有想到的网站上招致。然后您可以向自己发送该信息(当您在客户端上检测到您无法在网站上找到价格时),并且您可以自己查看该网站并在您的列表中添加更多正则表达式(可能需要更新服务器端并在每次更新时下载到您的客户端上)如果这解决了问题,或者添加另一个抓取算法或使您以前的算法更通用并且也可以使用该用例(但这需要新的应用程序版本)。

如果这个答案不是很具体,我很抱歉,但你的问题太广泛了,几乎不可能更具体。

PS:不确定这是否是最好的方法(也许某些解析器更适合这种方法)但是我可以很快想到的一个正则表达式匹配你的所有 3 个示例,其中 <[^>]*class=".*price.*"[^>]*>([^<]*)< . 可能有更聪明的东西,但使用此正则表达式,您将自动获取第一个捕获组中 html 元素内的文本。比你只需要清理它(删除不需要的字符等)并可能验证它。