一、介绍
WebMagic是一款基于Java的开源网络爬虫框架,能够快速、灵活、高效地实现网络数据的爬取和抽取。WebMagic支持多线程、分布式、自动重试等特性,而且使用起来也非常方便。
二、优点
1. 快速:使用了NIO框架,能够高效地进行网络通信,提高爬虫效率。
2. 灵活:支持自定义爬取规则,能够适应不同的网站结构和数据格式。
3. 高效:采用了异步非阻塞的方式,同时支持多线程和分布式部署,提高爬虫的效率和稳定性。
4. 易用:提供了简单易懂的API,开发者能够快速上手。
三、四大组件
1. Downloader(页面下载组件):负责下载网页,可选择不同的下载器。
2. PageProcessor(页面处理组件):对下载的页面进行处理,包括解析页面,提取有用的数据等。
3. Pipeline(结果输出组件):负责对 PageProcessor 处理出的结果进行处理,可以将结果存储在文件、数据库、搜索引擎等地方。
4. Scheduler(URL管理器):用于管理待抓取的 URL 队列,保证数据的准确性和抓取效率,还支持使用Redis等分布式存储来实现分布式抓取。
四、使用场景
1. 数据采集:能够帮助企业或个人快速、高效地获取网络上的数据,用于数据挖掘、业务分析等领域。
2. 站点监测:能够监测特定网站的变化,如新闻、价格、商品等,帮助企业及时了解市场动态。
3. 网络抓取:WebMagic可以模拟人类浏览器从网站抓取页面和内容,在网站的每个层次上收集信息和数据,从而构建完整的产品目录和分类。
五、注意事项
1. 避免反爬虫机制:一些网站会设置反爬虫机制,需要通过模拟浏览器行为、使用代理等方式进行规避。
2. 控制爬取速度:过快的爬取速度会给网站带来负担,同时也容易被网站封禁IP。
六、补充内容
1. 多语言支持:WebMagic有Python和Scala等语言的版本,能够适应不同开发者的需求。
2. 爬虫任务调度:WebMagic能够与Quartz等任务调度框架结合使用,实现定时爬取数据的功能。
3. WebMagic支持多线程:能够利用多核CPU提高爬虫效率。
4. WebMagic支持多种功能:Cookie、代理等功能,能够模拟登录、避免反爬等操作。
5. WebMagic支持多种格式的数据存储:如MySQL、Redis、Elasticsearch等,方便后续数据处理。
6. 处理异常情况:WebMagic能够处理一些异常情况,如页面404、解析错误等,提高爬虫的健壮性。
七、实际场景
1. 案例一
(1) 场景
爬取一个简单的页面。
(2) 代码
pom.xml
<!--web magic-->
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-core</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-extension</artifactId>
<version>0.8.0</version>
</dependency>
WebMagicCase1.java
/**
* 简单的WebMagic爬取页面案例
*
* @author wxy
* @since 2023-05-30
*/
public class WebMagicCase1 {
public static void main(String[] args) {
String[] urls = new String[]{
"https://blog.csdn.net/qq_45871274/article/details/129162237"
};
new MyTask().execute(urls);
}
}
MyTask.java
import us.codecraft.webmagic.Spider;
/**
* 爬取任务
*
* @author wxy
* @since 2023-05-30
*/
public class MyTask {
public void execute(String... url) {
Spider spider = Spider
// 指定页面解析器
.create(new MyProcessor())
// 指定爬取结果的处理器
.addPipeline(new MyPipeline())
.addUrl(url)
// 创建3个线程
.thread(3);
//异步爬取
spider.start();
}
}
PageProcessor.java
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;
import java.util.ArrayList;
import java.util.List;
/**
* 页面解析
*
* @author wxy
* @since 2023-05-30
*/
public class MyProcessor implements PageProcessor {
@Override
public void process(Page page) {
String pageStrHtml = page.getHtml().get();
Document pageHtmlDocument = Jsoup.parse(pageStrHtml);
List<String> contentList = new ArrayList<>();
// 获取文章标题
Elements title = pageHtmlDocument
.select("h1[id=articleContentId]");
// 写入标题文本内容
page.putField("title", title.text());
// 获取文章内容
Elements contents = pageHtmlDocument
.select("div[id=content_views]");
for (Element content : contents) {
for (Element element : content.children()) {
// 写入每一个标签中的文本内容
contentList.add(element.text());
}
// 写入文章全部文本内容
page.putField("contents", contentList);
}
}
@Override
public Site getSite() {
//在爬取页面时对http请求的一些设置 例如编码、HTTP头、超时时间、重试策略 等、代理等
return Site.me()
// 重试次数
.setRetryTimes(3)
// 间隔时间
.setSleepTime(100)
// 设置超时时间
.setTimeOut(10000);
}
}
MyPipeline.java
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;
import java.util.List;
/**
* 爬取结果的处理
*
* @author wxy
* @since 2023-05-30
*/
public class MyPipeline implements Pipeline {
@Override
public void process(ResultItems resultItems, Task task) {
// 打印文章标题文本内容(在这里解析并保存至数据库)
System.out.println("文章标题: ");
System.out.println(resultItems.get("title").toString());
// 打印文章内容文本内容
List<String> contents = resultItems.get("contents");
System.out.println("文章内容: ");
for (String content : contents) {
System.out.println(content);
}
}
}
最后将爬取的文章标题和内容输出: