无缝调用Java生态:用Jsoup轻松解析网页

大家是不是好奇用Groovy写爬虫到底靠不靠谱?简单说,这玩意儿就像给Java插上了翅膀——既能直接用所有Java的牛逼库,又能用更简洁的代码快速搞事。比如用几行代码就能扒网页数据,处理JSON像吃糖一样简单,还能和Redis这些中间件无缝配合。特别适合急需验证想法或者团队里Java老哥多的场景,下面咱就上手整段真实能跑的代码瞧瞧!

下面是一个实用的Groovy爬虫代码,用于爬取图书信息网站并提取数据。这个示例展示了Groovy在爬虫开发中的简洁性和强大功能。

#!/usr/bin/envgroovy

// 导入必要的库

@Grab('org.jsoup:jsoup:1.15.3')

@Grab('org.apache.httpcomponents:httpclient:4.5.13')

@Grab('com.fasterxml.jackson.core:jackson-databind:2.14.2')

importorg.jsoup.Jsoup

importorg.jsoup.nodes.Document

importorg.jsoup.nodes.Element

importorg.jsoup.select.Elements

importorg.apache.http.impl.client.HttpClients

importorg.apache.http.client.methods.HttpGet

importorg.apache.http.client.config.RequestConfig

importorg.apache.http.util.EntityUtils

importcom.fasterxml.jackson.databind.ObjectMapper

importcom.fasterxml.jackson.databind.SerializationFeature

/**

* 图书信息类

*/

classBook{

Stringtitle

Stringauthor

BigDecimalprice

Stringdescription

Integerrating

Stringurl


StringtoString() {

"《${title}》- ${author} - 价格: ${price}元 - 评分: ${rating}星"

   }

}

/**

* 网页爬虫类

*/

classBookScraper{

// HTTP客户端配置

privatedefhttpClient

privatedefconfig

privatedefobjectMapper


BookScraper() {

// 配置HTTP客户端(设置超时和代理等)

config=RequestConfig.custom()

.setConnectTimeout(5000)

.setSocketTimeout(5000)

.build()


httpClient=HttpClients.custom()

.setDefaultRequestConfig(config)

.build()


objectMapper=newObjectMapper()

objectMapper.enable(SerializationFeature.INDENT_OUTPUT)

   }


/**

* 获取网页内容

*/

StringfetchPage(Stringurl) {

try{

println"正在抓取: $url"

defhttpGet=newHttpGet(url)

// 设置请求头,模拟浏览器

httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")

httpGet.setHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")


defresponse=httpClient.execute(httpGet)

defentity=response.getEntity()

defcontent=EntityUtils.toString(entity)

EntityUtils.consume(entity)


returncontent

}catch(Exceptione) {

println"抓取网页时出错: ${e.message}"

returnnull

       }

   }


/**

* 解析图书列表页

*/

List<Book>parseBookList(Stringhtml,StringbaseUrl) {

defbooks=[]

try{

Documentdoc=Jsoup.parse(html)

ElementsbookElements=doc.select(".product_pod")// 假设每本书都在这个CSS类中


bookElements.each{Elementelement->

try{

Bookbook=newBook()


// 提取标题

book.title=element.select("h3 a").attr("title")

if(!book.title) {

book.title=element.select("h3 a").text()

                   }


// 提取作者

book.author=element.select(".author").text()?:"未知作者"


// 提取价格

defpriceText=element.select(".price_color").text()

book.price=priceText?newBigDecimal(priceText.replaceAll("[^\\d.]","")) :0.0


// 提取评分(假设评分用CSS类表示,如star-rating-Five)

defratingClass=element.select(".star-rating").attr("class")

defratingMatch=ratingClass=~/star-rating-(\w+)/

if(ratingMatch) {

defratingMap=[One:1,Two:2,Three:3,Four:4,Five:5]

book.rating=ratingMap[ratingMatch[0][1]]?:0

                   }


// 提取详情页链接

defrelativeUrl=element.select("h3 a").attr("href")

book.url=baseUrl+relativeUrl


// 获取图书详情

fetchBookDetails(book)


books<<book

println"已解析: ${book.title}"

}catch(Exceptione) {

println"解析单本书时出错: ${e.message}"

               }

           }

}catch(Exceptione) {

println"解析图书列表时出错: ${e.message}"

       }


returnbooks

   }


/**

* 获取图书详细信息

*/

voidfetchBookDetails(Bookbook) {

try{

defhtml=fetchPage(book.url)

if(html) {

Documentdoc=Jsoup.parse(html)


// 提取描述

defdescriptionElement=doc.select("#product_description + p")

if(descriptionElement) {

book.description=descriptionElement.text()

               }

           }

}catch(Exceptione) {

println"获取图书详情时出错: ${e.message}"

       }

   }


/**

* 保存结果到JSON文件

*/

voidsaveToJson(List<Book>books,Stringfilename) {

try{

objectMapper.writeValue(newFile(filename),books)

println"结果已保存到: ${filename}"

}catch(Exceptione) {

println"保存结果时出错: ${e.message}"

       }

   }


/**

* 关闭HTTP客户端

*/

voidclose() {

httpClient.close()

   }

}

/**

* 主程序

*/

defmain() {

// 初始化爬虫

defscraper=newBookScraper()


try{

// 要爬取的网站URL(这里以虚构的图书网站为例)

defbaseUrl="https://books.example.com"

defstartUrl="${baseUrl}/catalogue/page-1.html"


// 获取网页内容

defhtml=scraper.fetchPage(startUrl)


if(html) {

// 解析图书列表

defbooks=scraper.parseBookList(html,baseUrl)


// 打印结果

println"\n爬取结果:"

books.eachWithIndex{book,index->

println"${index+1}. ${book}"

if(book.description) {

println"   描述: ${book.description.length()>100?book.description.substring(0,100)+'...':book.description}"

               }

println()

           }


// 保存结果到JSON文件

scraper.saveToJson(books,"books.json")


println"共爬取 ${books.size()} 本书籍"

}else{

println"未能获取网页内容"

       }

}finally{

// 确保关闭HTTP客户端

scraper.close()

   }

}

// 运行主程序

main()

代码说明

这个Groovy爬虫示例具有以下特点:

1、完整的爬虫功能

发送HTTP请求并处理响应

解析HTML内容提取所需数据

处理异常和错误情况

保存结果到JSON文件

2、使用Groovy的优势

简洁的语法和强大的集合操作

直接使用Java生态库(Jsoup、HttpClient、Jackson)

灵活的闭包和DSL风格代码

无需编译,可直接运行

3、实用功能

设置超时和请求头模拟浏览器

错误处理和日志输出

数据清洗和转换

结构化数据存储

运行方法

1、确保已安装Groovy

2、将代码保存为book_scraper.groovy

3、运行命令:groovy book_scraper.groovy

扩展建议

1、添加代理支持以避免IP被封

2、实现分页爬取功能

3、添加并发处理以提高爬取效率

4、集成数据库存储代替文件存储

5、添加定时任务支持定期爬取

这个示例展示了Groovy在爬虫开发中的简洁性和强大功能,特别适合需要快速开发和与Java生态系统集成的项目。

看出来了吧?Groovy搞爬虫真是又狠又灵活!代码写得比Java清爽十倍,底层还能调用所有Java生态的硬核工具库。无论是快速抓数据还是集成到现有Java系统里都特别顺手。不过记得爬数据要讲武德,控制频率加异常处理,毕竟咱不是暴力爬虫。用这招去折腾数据吧,绝对爽到飞起!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容