博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java爬虫(二)
阅读量:5232 次
发布时间:2019-06-14

本文共 9909 字,大约阅读时间需要 33 分钟。

  

  上一篇简单的实现了获取url返回的内容,在这一篇就要第返回的内容进行提取,并将结果保存到html中。而且这个爬虫是的java语言实现,其逻辑大致相同。

 

一 、 需求:

  抓取主页面:百度百科Python词条   https://baike.baidu.com/item/Python/407313

 

  

分析上面的源码格式,便于提取:

  • 关键词分析:位于class为lemmaWgt-lemmaTitle-title的dd元素的第一个h1标签内

 

  •  简介分析(位于class为lemma-summary的div的text内容)

 

   

  • 其他相关联的标签的分析(是a标签,且href以/item/开头)

 

 

 

 

二、抓取过程流程图:

 

 

 

三、代码实现:

1.SpiderManager.java 

  构造函数中创建Url管理器,html加载器,html解析器,html输出器

  craw()方法中是爬虫的主要业务逻辑。

package cn.qlq.craw.JsoupBaike;import java.io.IOException;import java.util.List;import java.util.Map;/** * 爬虫的入口 * @author liqiang * */public class SpiderManager {    private UrlManager urlManager;    private HtmlLoader htmlLoader;    private HtmlOutputer htmlOutputer;    private HtmlParser htmlParser;        public SpiderManager() {        super();        this.urlManager =new  UrlManager();        this.htmlLoader =new  HtmlLoader();        this.htmlOutputer =new HtmlOutputer();        this.htmlParser =new  HtmlParser();    }            /**     * 爬虫的主要逻辑     * @param url    需要爬的网站地址     */    public void craw(String url){        if(url == null || "".equals(url)){            return;        }        int count = 0;//记录爬取了几个页面        urlManager.addNewUrl(url);        while (urlManager.hasNewUrl()){            try {                String newUrl = urlManager.getNewUrl();//获取需要爬取的网站url                String htmlContent = htmlLoader.loadUrl(newUrl);//爬取网站内容                Map
datas = htmlParser.parseHtml(newUrl,htmlContent);//提取到爬到的网页中需要的信息 urlManager.addNewUrls((List
) datas.get("urls"));//将提取到的url信息保存到urlManager htmlOutputer.collectData(datas);//将提取到的数据收集起来 if(count == 10){ break; } count++; } catch (Exception e) { System.out.println("发生异常"+e.getMessage()); } } try { htmlOutputer.outputDatas(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public UrlManager getUrlManager() { return urlManager; } public void setUrlManager(UrlManager urlManager) { this.urlManager = urlManager; } public HtmlLoader getHtmlLoader() { return htmlLoader; } public void setHtmlLoader(HtmlLoader htmlLoader) { this.htmlLoader = htmlLoader; } public HtmlOutputer getHtmlOutputer() { return htmlOutputer; } public void setHtmlOutputer(HtmlOutputer htmlOutputer) { this.htmlOutputer = htmlOutputer; } public HtmlParser getHtmlParser() { return htmlParser; } public void setHtmlParser(HtmlParser htmlParser) { this.htmlParser = htmlParser; }}

 

 

2.UrlManager.java

  维护两个list,一个用于存放未被爬取的url地址

        一个用于存储已经爬取的url地址,并且两者不能有重复元素

package cn.qlq.craw.JsoupBaike;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;/** * url管理器 * @author liqiang * */@SuppressWarnings("all")public class UrlManager {    /**     * 存放未被访问的url的list     */    private List
new_urls; /** * 存放已经访问过的url的list */ private List
old_urls; public UrlManager() { this.new_urls = new LinkedList
(); this.old_urls = new LinkedList
(); } /** * 添加一个url到list中 * @param url */ public void addNewUrl(String url) { if(url == null || "".equals(url)){ return; } if(!new_urls.contains(url) && !old_urls.contains(url) ){ new_urls.add(url); } } /** * 判断是否有新的url * @return */ public boolean hasNewUrl() { return new_urls.size()>0; } /** * 弹出一个新的url * @return */ public String getNewUrl() { if(new_urls.size() == 0){ return null; } String newUrl = new_urls.get(0);//从未访问的集合中获取一个数据 new_urls.remove(0);//移除第一个元素 old_urls.add(newUrl);//将移除的数据添加到旧的已经访问过的集合中 return newUrl; } /** * 批量添加url * @param urls 需要添加的url集合 */ public void addNewUrls(List
urls) { if(urls == null || urls.size()==0){ return; } for(String url:urls){ this.addNewUrl(url); } } public List
getNew_urls() { return new_urls; } public void setNew_urls(List
new_urls) { this.new_urls = new_urls; } public List
getOld_urls() { return old_urls; } public void setOld_urls(List
old_urls) { this.old_urls = old_urls; } }

 

 

 

3.HtmlLoader.java

  主要就是利用JSoup去读取url的内容

package cn.qlq.craw.JsoupBaike;import java.io.IOException;import org.jsoup.Jsoup;/** * 读取url的内容 * @author liqiang * */public class HtmlLoader {    public String loadUrl(String newUrl) {        try {            return Jsoup.connect(newUrl).post().toString();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return "";    }}

 

 

 

4.HtmlParser.java

  主要就是提取页面的主要内容(a标签,标题和简介)

package cn.qlq.craw.JsoupBaike;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.jsoup.nodes.Element;import org.jsoup.select.Elements;/** * 解析器 * @author liqiang * */public class HtmlParser {    /**     * 提取网站信息     *      * @param newUrl     * @param htmlContent     * @return map中应该包含该网页上提取到的url地址(set集合)和关键字     */    public Map
parseHtml(String newUrl, String htmlContent) { // 0.将返回的htmlContent转换成DOM树 // Document document = Jsoup.parse(htmlContent); // 1.获取到所有的a标签,且a标签的href属性包含/item List
urls = this.getUrls(newUrl, htmlContent); // 2.获取指定的标题和介绍 Map
titleAndSummary = this.getTitleAndSummary(newUrl, htmlContent); // 创建一个map,将提取到的urls和标题和简介装到map中返回去 Map
result = new HashMap
(); result.put("urls", urls); result.put("titleAndSummary", titleAndSummary); return result; } /** * 获取标题和简介 * * @param newUrl * 传下来的访问的url * @param htmlContent * 传下来的获取到的html内容 * @return */ private Map
getTitleAndSummary(String newUrl, String htmlContent) { Document document = Jsoup.parse(htmlContent);// 转换成DOM文档 // 1.获取标题 // first查找下面的第一个h1元素,get(index)可以获取指定位置的标签 Element title_ele = document.select("dd.lemmaWgt-lemmaTitle-title").select("h1").first(); String title_text = title_ele.text(); // 2.获取简介 Element summary_ele = document.select("div.lemma-summary").first(); String summary_text = summary_ele.text(); //将3.数据加入map返回 Map
titleAndSummary = new HashMap
(); titleAndSummary.put("title", title_text); titleAndSummary.put("summary", summary_text); titleAndSummary.put("url", newUrl); return titleAndSummary; } /** * 获取到所有的a标签,且a标签的href属性包含/item * * @param newUrl * @param htmlContent * @return */ private List
getUrls(String newUrl, String htmlContent) { Document document = Jsoup.parse(htmlContent);// 转换成DOM文档 Elements elements = document.select("a[href^='/item']");// 查找以/item开头的元素的标签 List
urls = new ArrayList
(); for (Element ele : elements) { String url = newUrl.substring(0, newUrl.indexOf("/item")) + ele.attr("href"); urls.add(url); } return urls; }}

 

 

5.HtmlOutputer.java

  主要作用有两个:一个是保存每次提取的信息

         一个是最后爬虫完毕将提取的信息输出到html中。 

package cn.qlq.craw.JsoupBaike;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileWriter;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Map;/** * 输出器 *  * @author liqiang * */public class HtmlOutputer {    private List
> collected_datas; public HtmlOutputer() { this.collected_datas = new ArrayList
>(); } /** * 收集数据 * * @param datas */ public void collectData(Map
datas) { collected_datas.add(datas);// 将数据 添加到集合中 } /** * 最后处理所有的数据,写出到html或者保存数据库 * * @throws IOException */ public void outputDatas() throws IOException { if (collected_datas != null && collected_datas.size() > 0) { File file = new File("C:\\Users\\liqiang\\Desktop\\实习\\python\\JavaCraw\\out.html"); // 如果文件不存在就创建文件 if (!file.exists()) { file.createNewFile(); } // 构造FileWriter用于向文件中输出信息(此构造方法可以接收file参数,也可以接收fileName参数) FileWriter fileWriter = new FileWriter(file); // 开始写入数据 fileWriter.write(""); fileWriter.write(""); fileWriter.write("
爬取结果"); fileWriter .write("
"); fileWriter.write(""); fileWriter.write(""); fileWriter.write("
datas : collected_datas) { @SuppressWarnings("unchecked") Map
data = (Map
) datas.get("titleAndSummary"); String url = (String) data.get("url"); String title = (String) data.get("title"); String summary = (String) data.get("summary"); fileWriter.write("
"); for (Map
"); fileWriter.write("
"); fileWriter.write("
"); fileWriter.write("
"); fileWriter.write("
"); } fileWriter.write("
" + url + " " + title + " " + summary + "
"); fileWriter.write(""); fileWriter.write(""); // 关闭文件流 fileWriter.close(); } }}

 

 

 

 

 

至此代码编写基本完成,下面进行测试:

 

 

package cn.qlq.craw.JsoupBaike;import java.io.FileWriter;public class MainClass {    public static void main(String[] args) {        String url = "https://baike.baidu.com/item/Python/407313";        SpiderManager sm = new SpiderManager();        sm.craw(url);    }}

 

结果:(会生成out.html)

 

 

 

 

 Jsoup中文API网址:

 python同样功能的爬虫实现:

 

转载于:https://www.cnblogs.com/qlqwjy/p/8877928.html

你可能感兴趣的文章