作为一名网站的作者,我理解你对于半小时写一个网络爬虫框架的需求。这里给出详细攻略:
步骤一:准备工作
在开始编写爬虫框架之前,需要准备好以下工具:
1. 开发环境:JDK、IDEA(或其他你喜欢的IDE)
2. 技术框架:Jsoup、HttpClient
步骤二:建立基础框架
- 新建Java项目,创建类WebCrawler。
- 在WebCrawler类中添加以下变量:
private CloseableHttpClient httpClient;
private CookieStore cookieStore;
private RequestConfig config;
public WebCrawler() {
// 初始化httpClient, cookieStore, config
}
在构造函数中实现httpClient, cookieStore, config的初始化。
- 添加get方法:
public Document get(String url) throws IOException {
HttpGet httpGet = new HttpGet(url);
// 设置请求头
httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3");
// 发起请求
CloseableHttpResponse response = httpClient.execute(httpGet);
// 解析响应
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
Document doc = Jsoup.parse(content, "utf-8", url);
// 关闭response, content
response.close();
content.close();
return doc;
}
该方法发起get请求,并返回Document对象。
步骤三:爬行流程
- 新建类CrawlResult。
- 在WebCrawler类中添加crawl方法:
public CrawlResult crawl(CrawlTask task) {
CrawlResult result = new CrawlResult(task);
String url = task.getUrl();
// 调用get方法获取Document对象
try {
Document doc = get(url);
// 解析doc,提取所需内容
// 将内容加入result
} catch (IOException e) {
result.setSuccess(false);
}
return result;
}
该方法接收CrawlTask对象,通过get方法获取Document对象,并解析Document对象提取所需内容,生成CrawlResult对象并返回。
- 新建类ListPageParser,实现parseListPage和hasNextPage方法,用于解析分页列表,提取url和判断是否还有下一页。
public class ListPageParser {
public List<String> parseListPage(Document doc) {
// 解析列表页面,提取所有详情页url
// 返回url列表
}
public boolean hasNextPage(Document doc) {
// 判断是否还有下一页
// 返回true或false
}
}
- 新建类DetailPageParser,实现parseDetailPage方法,用于解析详情页,提取所需内容。
public class DetailPageParser {
public void parseDetailPage(Document doc, CrawlResult result) {
// 解析详情页面,提取所需内容,加入result
}
}
- 在WebCrawler类中添加crawlListPage和crawlDetailPage方法:
public List<String> crawlListPage(String listUrl) {
List<String> urls = new ArrayList<>();
String url = listUrl;
// 判断是否有下一页,有则循环
while (url != null) {
try {
Document doc = get(url);
List<String> pageUrls = new ListPageParser().parseListPage(doc);
urls.addAll(pageUrls);
url = new ListPageParser().hasNextPage(doc);
} catch (IOException e) {
url = null;
}
}
return urls;
}
public CrawlResult crawlDetailPage(String detailUrl) {
CrawlTask task = new CrawlTask(detailUrl);
return crawl(task);
}
- 在WebCrawler类中添加crawlSite方法,用于爬取整个站点:
public void crawlSite(String listUrl) {
List<String> detailUrls = crawlListPage(listUrl);
for (String detailUrl : detailUrls) {
crawlDetailPage(detailUrl);
}
}
步骤四:示例使用
以爬取CSDN博客文章为例。
- 新建类CSDNBlogCrawler,继承WebCrawler类。在CSDNBlogCrawler类中实现get方法:
public Document get(String url) throws IOException {
Document doc = super.get(url);
// 去掉广告内容,调整页面样式
doc.select("div.blog_ad").remove();
doc.select("div.article_manage").remove();
doc.select("div.comt_tit.bbs").remove();
return doc;
}
- 在CSDNBlogCrawler类中添加parseListPage和parseDetailPage方法:
public class CSDNBlogCrawler extends WebCrawler {
private class CSDNListPageParser extends ListPageParser {
@Override
public List<String> parseListPage(Document doc) {
Elements elements = doc.select("div.list_item");
List<String> urls = new ArrayList<>();
for (Element element : elements) {
Element a = element.selectFirst("a[href]");
String url = a.attr("href");
urls.add(url);
}
return urls;
}
@Override
public boolean hasNextPage(Document doc) {
Element nextPage = doc.selectFirst("a.page_nav.next_page");
if (nextPage != null) {
return nextPage.attr("href");
}
return null;
}
}
private class CSDNDetailPageParser extends DetailPageParser {
@Override
public void parseDetailPage(Document doc, CrawlResult result) {
String title = doc.selectFirst("h1.blog_title").text();
String content = doc.selectFirst("div.blog_content").html();
result.addField("title", title);
result.addField("content", content);
}
}
public List<String> crawlBlogListPage(String blogUrl) {
return crawlListPage(blogUrl);
}
public CrawlResult crawlBlogDetailPage(String blogDetailUrl) {
return crawlDetailPage(blogDetailUrl);
}
}
- 在CSDNBlogCrawler类中使用crawlSite方法爬取CSDN博客文章信息:
public static void main(String[] args) {
String blogUrl = "https://blog.csdn.net";
String listUrl = blogUrl + "/nav/web";
CSDNBlogCrawler csdnBlogCrawler = new CSDNBlogCrawler();
List<String> blogDetailUrls = csdnBlogCrawler.crawlBlogListPage(listUrl);
for (String blogDetailUrl : blogDetailUrls) {
CrawlResult result = csdnBlogCrawler.crawlBlogDetailPage(blogDetailUrl);
System.out.println(result);
}
}
至此,一个半小时实现Java手撸网络爬虫框架(附完整源码)的攻略就结束了。
示例1
场景:爬取博客网站中某个作者发布的所有文章。
- 找到作者博客主页的地址。
- 调用crawlSite方法,传入作者博客主页地址,即可获取该作者发布的所有文章。
public static void main(String[] args) {
String blogUrl = "http://www.xxx.com";
String listUrl = blogUrl + "/blog";
WebCrawler webCrawler = new WebCrawler();
webCrawler.crawlSite(listUrl);
}
示例2
场景:爬取一个电商网站商品的基本信息,包括价格、名称、评价星级等。
- 找到商品列表页的地址。
- 调用crawlListPage方法,传入商品列表页地址,获取该页面所有商品详情页地址。
- 循环调用crawlDetailPage方法,传入每个商品详情页地址,获取该商品的基本信息。
public static void main(String[] args) {
String baseUrl = "http://www.xxx.com";
String listUrl = baseUrl + "/products";
WebCrawler webCrawler = new WebCrawler();
List<String> productDetailUrls = webCrawler.crawlListPage(listUrl);
for (String productDetailUrl : productDetailUrls) {
CrawlResult result = webCrawler.crawlDetailPage(productDetailUrl);
System.out.println(result);
}
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:半小时实现Java手撸网络爬虫框架(附完整源码) - Python技术站