Hickory项目实战:构建一个简易网页爬虫与数据提取工具

【免费下载链接】hickory HTML as data 【免费下载链接】hickory 项目地址: https://gitcode.com/gh_mirrors/hic/hickory

Hickory是一个强大的HTML解析与处理库,能将HTML文档转换为Clojure数据结构,支持解析、转换和生成HTML。本教程将带你使用Hickory构建一个高效的网页爬虫与数据提取工具,无需复杂代码即可轻松处理网页数据。

快速了解Hickory核心功能

Hickory作为HTML处理工具,主要提供三大核心能力:

  • HTML解析:将原始HTML字符串转换为结构化数据
  • 数据转换:支持Hiccup向量格式与Hickory DOM映射格式互转
  • 数据提取:通过CSS风格选择器快速定位和提取目标数据

Hickory的设计理念是"HTML as data",将网页内容转化为易于操作的Clojure数据结构,这使得数据处理变得直观而高效。

环境准备:从零开始搭建开发环境

安装Hickory依赖

在项目的project.clj中添加Hickory依赖:

[org.clj-commons/hickory "0.7.3"]

如果你使用Clojure CLI工具,在deps.edn中添加:

org.clj-commons/hickory {:mvn/version "0.7.3"}

项目结构概览

典型的Hickory项目结构如下:

src/
  clj/                  ; Clojure代码
    hickory/
      core.clj          ; 核心解析功能
  cljc/                 ; 跨平台代码
    hickory/
      convert.cljc      ; 格式转换功能
      select.cljc       ; 选择器功能
      render.cljc       ; HTML渲染功能
test/                   ; 测试代码

核心功能解析:HTML解析与数据转换

解析HTML文档

使用hickory.core/parse函数解析完整HTML文档:

(use 'hickory.core)
(def html-content "<html><body><h1>Hello Hickory</h1><p>HTML parsing made easy</p></body></html>")
(def parsed-doc (parse html-content))

对于HTML片段,使用parse-fragment函数:

(def fragment (parse-fragment "<div class='article'><p>First paragraph</p><p>Second paragraph</p></div>"))

数据格式转换

Hickory支持两种主要数据格式:

  1. Hiccup格式:紧凑的向量表示法,适合编写HTML
(as-hiccup parsed-doc)
; 返回: ([html {} [head {}] [body {} [h1 {} "Hello Hickory"] [p {} "HTML parsing made easy"]]])
  1. Hickory格式:详细的映射结构,适合数据处理
(as-hickory parsed-doc)
; 返回: {:type :document, :content [{:type :element, :tag :html, ...}]}

Hickory格式的节点结构包含以下关键字:

  • :type:节点类型(:comment, :document, :element等)
  • :tag:元素标签(仅元素节点)
  • :attrs:属性映射(仅元素节点)
  • :content:子节点向量

实战开发:构建网页数据提取工具

基本爬虫框架搭建

结合HTTP客户端和Hickory,构建一个简单的网页爬虫:

(use 'hickory.core)
(require '[clj-http.client :as client])
(require '[hickory.select :as s])

(defn fetch-and-parse [url]
  (-> (client/get url) 
      :body 
      parse 
      as-hickory))

使用选择器提取数据

Hickory的选择器功能(hickory.select命名空间)提供了强大的数据提取能力:

常用选择器函数
  • tag:按标签选择元素
  • id:按ID选择元素
  • class:按类名选择元素
  • attr:按属性选择元素
  • child:选择直接子元素
  • descendant:选择后代元素
提取示例:获取网页标题
(defn extract-title [htree]
  (-> (s/select (s/descendant (s/tag :head) (s/tag :title)) htree)
      first 
      :content 
      first))

; 使用方法
(def site-htree (fetch-and-parse "https://example.com"))
(extract-title site-htree)  ; 返回网页标题文本
提取示例:获取所有链接
(defn extract-links [htree]
  (map #(get-in % [:attrs :href]) 
       (s/select (s/tag :a) htree)))

; 获取所有链接
(extract-links site-htree)

高级数据提取:组合选择器

通过组合多个选择器,可以精确定位目标数据:

; 选择class为"article"的div中的所有p标签
(def article-paragraphs 
  (s/select (s/descendant (s/class :article) (s/tag :p)) site-htree))

; 提取带特定属性的图片
(def product-images
  (s/select (s/and (s/tag :img) (s/attr :data-product-id)) site-htree))

数据处理与转换:从HTML到结构化数据

处理提取结果

将提取的原始数据转换为结构化格式:

(defn extract-articles [htree]
  (map (fn [article]
         {:title (-> (s/select (s/tag :h2) article) first :content first)
          :content (->> (s/select (s/tag :p) article)
                        (map :content)
                        (map first)
                        (clojure.string/join " "))
          :date (-> (s/select (s/class :date) article) first :content first)})
       (s/select (s/class :article) htree)))

使用Zipper修改HTML结构

Hickory提供Zipper功能,可以方便地修改HTML结构:

(require '[hickory.zip :as hzip])
(require '[clojure.zip :as zip])

(defn add-css-class [htree selector class]
  (let [zip (hzip/hickory-zip htree)]
    (-> (zip/root 
          (loop [loc zip]
            (if (zip/end? loc)
              loc
              (if (s/select? selector loc)
                (recur (zip/edit loc #(update % :attrs assoc :class (str (:class (:attrs %)) " " class)))
                (recur (zip/next loc)))))))))

完整案例:构建一个简单的产品信息爬虫

下面是一个完整的示例,从电子商务网站提取产品信息:

(ns product-scraper
  (:require [hickory.core :as hickory]
            [hickory.select :as s]
            [clj-http.client :as client]
            [clojure.string :as str]))

(defn fetch-page [url]
  (-> (client/get url {:headers {"User-Agent" "Mozilla/5.0"}})
      :body
      hickory/parse
      hickory/as-hickory))

(defn extract-products [htree]
  (map (fn [product]
         {:name (-> (s/select (s/descendant (s/class :product-name) (s/tag :a)) product)
                    first :content first str/trim)
          :price (-> (s/select (s/class :product-price) product)
                     first :content first str/trim)
          :image (-> (s/select (s/tag :img) product)
                     first :attrs :src)
          :rating (-> (s/select (s/class :rating) product)
                      first :attrs :data-rating)})
       (s/select (s/class :product-item) htree)))

(defn -main [& args]
  (let [url (first args)
        htree (fetch-page url)
        products (extract-products htree)]
    (doseq [product products]
      (println (str/join "\t" [(:name product) (:price product) (:rating product)])))))

最佳实践与性能优化

选择合适的数据格式

  • Hiccup格式:适合生成HTML或简单的结构转换
  • Hickory格式:适合复杂的数据提取和分析

优化选择器性能

  • 避免过深的嵌套选择器
  • 优先使用ID和标签选择器,后使用类选择器
  • 对大型文档,考虑分块处理

处理动态内容

对于JavaScript渲染的内容,可以结合Headless浏览器:

; 使用PhantomJS或Selenium获取动态内容
(defn fetch-dynamic-page [url]
  ; 实现略,需集成外部工具
  )

总结与扩展学习

通过本教程,你已经掌握了使用Hickory构建网页爬虫和数据提取工具的基本技能。Hickory的强大之处在于将HTML转换为易于处理的数据结构,让复杂的网页数据提取变得简单直观。

进一步学习资源

项目扩展方向

  • 添加异步请求支持
  • 实现数据持久化存储
  • 构建可视化数据展示界面
  • 开发定时爬取任务

Hickory为网页数据处理提供了强大而灵活的工具集,无论是简单的数据提取还是复杂的HTML转换,都能轻松应对。开始你的Hickory之旅,探索网页数据的无限可能吧!

【免费下载链接】hickory HTML as data 【免费下载链接】hickory 项目地址: https://gitcode.com/gh_mirrors/hic/hickory

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐