美文网首页
gecco 的学习和练习

gecco 的学习和练习

作者: 客观开发者 | 来源:发表于2021-05-07 17:31 被阅读0次

    1,学习gecco
    源码地址:https://gitee.com/xtuhcy/gecco
    2,运行源码。
    导入到idea 里面。
    运行第一个demo 在text 里面可以找到

    @Gecco(pipelines="consolePipeline")
    public class CommonCrawler implements HtmlBean {
    
        private static final long serialVersionUID = -8870768223740844229L;
    
        @Request
        private HttpRequest request;
        
        @Text(own=false)
        @HtmlField(cssPath="body")
        private String body;
    
        public HttpRequest getRequest() {
            return request;
        }
    
        public void setRequest(HttpRequest request) {
            this.request = request;
        }
    
        public String getBody() {
            return body;
        }
    
        public void setBody(String body) {
            this.body = body;
        }
        
        public static void main(String[] args) {
            GeccoEngine.create()
            .classpath("com.geccocrawler.gecco.demo")
            .start("https://www.baidu.com/")
            .interval(2000)
            .start();
        }
    }
    

    代码说明
    接口HtmlBean说明该爬虫是一个解析html页面的爬虫(gecco还支持json格式的解析)
    注解@Gecco告知该爬虫匹配的url格式(matchUrl)和内容抽取后的bean处理类(pipelines处理类采用管道过滤器模式,可以定义多个处理类)。
    注解@RequestParameter可以注入url中的请求参数,如@RequestParameter("user")表示匹配url中的{user}
    注解@HtmlField表示抽取html中的元素,cssPath采用类似jquery的css selector选取元素
    注解@Text表示获取@HtmlField抽取出来的元素的text内容
    注解@Html表示获取@HtmlField抽取出来的元素的html内容(如果不指定默认为@Html)
    GeccoEngine表示爬虫引擎,通过create()初始化,通过start()/run()运行。可以配置一些启动参数如:扫描@Gecco注解的包名classpath;开始抓取的url地址star;抓取线程数thread;抓取完一个页面后的间隔时间interval(ms)等

    2021-05-08_17-20-17.png
    根据文档,可以进行自己demo 测试了。
    也可以先看文档
    reamde.MD其实够好了。
    http://www.geccocrawler.com/author/gecco/
    看着困了。还是写吧。
    代码在 源码里面添加的和测试的
    Snipaste_2021-05-08_17-25-59.png

    主要是爬明星的基本信息。。是循环进行的。
    主方法

    package com.geccocrawler.gecco.demo.mingxing;
    
    import com.geccocrawler.gecco.GeccoEngine;
    import com.geccocrawler.gecco.annotation.*;
    import com.geccocrawler.gecco.request.HttpGetRequest;
    import com.geccocrawler.gecco.request.HttpRequest;
    import com.geccocrawler.gecco.spider.HtmlBean;
    
    import java.util.List;
    
    //@Gecco(matchUrl = "http://ku.ent.sina.com.cn/star/search&page_no={page}", pipelines = {"consolePipeline", "starIndexPagePipeline"})
    @Gecco(matchUrl = "http://ent.sina.com.cn/ku/star_search_index.d.html?page={page}", pipelines = {"consolePipeline", "starIndexPagePipeline"})
    //matchUrl是爬取相匹配的url路径,然后将获取到的HtmlBean输出到相应的管道(pipelines)进行处理。这里的管道是可以自定义的。
    public class StarIndexPage implements HtmlBean {
    
        private static final long serialVersionUID = 1225018257932399804L;
    
        @Request
        private HttpRequest request;
    
        //url中的page参数
        @RequestParameter
        private String page;
    
    
        //首页中的明星板块的集合,li的集合
        @HtmlField(cssPath = "#dataListInner > ul >li")
        private List<StarDetail> lsStarDetail;
    //@HtmlField(cssPath = "#dataListInner > ul >li")是用来抓取网页中的相应网页数据,csspath是jQuery的形式。
    //cssPath获取小技巧:用Chrome浏览器打开需要抓取的网页,按F12进入发者模式。然后在浏览器右侧选中该元素,鼠标右键选择Copy–Copy selector,即可获得该元素的cssPath
    
        //当前的页码,如果当前的是有很多页码的话,可以通过获取当前页码还有总页码,为继续抓取下一页做准备
    //@Text是指抓取网页中的文本部分。@Html是指抓取Html代码。@Href是用来抓取元素的连接 @Ajax是指获取Ajax得到的内容。
        @Text
        @HtmlField(cssPath = "#dataListInner > div > ul > li.curr a")
        private int currPageNum;
    
        //相应的Getter和Setter方法...省略
    
        @Text
        @HtmlField(cssPath = "#dataListInner > div > ul > li")
        private String pageNum;
    
        public String getPageNum() {
            return pageNum;
        }
    
        public void setPageNum(String pageNum) {
            this.pageNum = pageNum;
        }
    
        public static long getSerialVersionUID() {
            return serialVersionUID;
        }
    
        public HttpRequest getRequest() {
            return request;
        }
    
        public void setRequest(HttpRequest request) {
            this.request = request;
        }
    
        public String getPage() {
            return page;
        }
    
        public void setPage(String page) {
            this.page = page;
        }
    
        public List<StarDetail> getLsStarDetail() {
            return lsStarDetail;
        }
    
        public void setLsStarDetail(List<StarDetail> lsStarDetail) {
            this.lsStarDetail = lsStarDetail;
        }
    
        public int getCurrPageNum() {
            return currPageNum;
        }
    
        public void setCurrPageNum(int currPageNum) {
            this.currPageNum = currPageNum;
        }
        /*
        * https://segmentfault.com/a/1190000010086659
        * 案例。。可以用
        * */
        public static void main(String[] args) {
    //        String url = "http://ku.ent.sina.com.cn/star/search&page_no=1"; //想要爬取的网站的首页地址
            String url = "http://ent.sina.com.cn/ku/star_search_index.d.html?page=1"; //想要爬取的网站的首页地址
            HttpGetRequest start = new HttpGetRequest(url); //获取网站请求
            start.setCharset("UTF-8");
            GeccoEngine.create() //创建搜索引擎
                    .classpath("com.geccocrawler.gecco.demo.mingxing") //要搜索的包名,会自动搜索该包下,含@Gecco注解的文件。
                    .start(start)
                    .thread(5)//开启多少个线程抓取
                    .interval(2000) //隔多长时间抓取1次
                    .run();
        }
    
    }
    

    @Gecco 来 找url 和 爬虫的参数
    下面的放就是上面指定的方法
    也是 数据存储的地方

    package com.geccocrawler.gecco.demo.mingxing;
    
    import com.geccocrawler.gecco.annotation.PipelineName;
    import com.geccocrawler.gecco.pipeline.Pipeline;
    import com.geccocrawler.gecco.request.HttpRequest;
    import com.geccocrawler.gecco.scheduler.SchedulerContext;
    import org.apache.commons.lang3.StringUtils;
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.List;
    import java.util.Map;
    
    @PipelineName("starIndexPagePipeline")
    //@pipelineName 标签指定了pipline的名字。并且pipeline这个类需要实现Pipleline<T>。
    public class StarIndexPagePipeline implements Pipeline<StarIndexPage> {
    
        @Override
        public void process(StarIndexPage starIndexPage) {
    
            List<StarDetail> lsStarDetail = starIndexPage.getLsStarDetail();
    
            StringBuilder inputText = new StringBuilder();
    
            for (StarDetail starDetail : lsStarDetail) {
                String professionHtml = starDetail.getProfessionHtml();
                String starNameHtml = starDetail.getStarNameHtml();
                Document docName = Jsoup.parse(starNameHtml);
                String starName = docName.getElementsByTag("a").attr("title").trim();
    
                String starSex = starDetail.getStarSex().trim();
                Document doc = Jsoup.parse(professionHtml);
                String profession = "未知"; //有不含a标签的,不含a标签的都是未知的
                if (professionHtml.indexOf("<a") != -1) {
                    profession = doc.getElementsByTag("a").text();
                }
                String nationality = starDetail.getNationality().trim();
                String birthday = starDetail.getBirthday().trim();
                String constellation = starDetail.getConstellation().trim();
                String height = starDetail.getHeight().trim();
                inputText.append(starName + "\t" +
                        starSex + "\t" +
                        profession + "\t" +
                        nationality + "\t" +
                        birthday + "\t" +
                        constellation + "\t" +
                        height + "\t" +
                        System.getProperty("line.separator"));
            }
            //写入文件
            writeFile(inputText.toString());
    
            //爬取下一页
            HttpRequest currRequest = starIndexPage.getRequest();
    
    //        int currPageNum = starIndexPage.getCurrPageNum();
    //        String pageNum = starIndexPage.getPageNum();
    
            Map<String, String> parameters = currRequest.getParameters();
            String page = parameters.get("page");
            int i = Integer.parseInt(page);
            /*
            System.out.println("----------已爬取第" + currPageNum + "页----------");
            pageNum = pageNum.replace("第", "");
            pageNum = pageNum.replace("页", "");
            int i1 = Integer.parseInt(pageNum);
            System.out.println("----------已爬取第" + pageNum + "页----------");
            System.out.println("----------已爬取第" + i1 + "页----------");*/
            System.out.println("----------已爬取第" + i + "页----------");
    
            searchNext(i, currRequest);
        }
    
        //写入文档的方法
        public void writeFile(String inputText) {
            try {
    
                File f1 = new File("D:\\明星数据.txt");
                if (!f1.exists()) {
                    f1.createNewFile();
                }
                FileWriter fw1 = new FileWriter("D:\\明星数据.txt", true);
                PrintWriter pw = new PrintWriter(fw1, true);
                pw.println("姓名" + "\t" + "性别" + "\t" + "职业" + "\t" + "国籍" + "\t" + "生日" + "\t" + "星座" + "\t" + "身高");
                pw.print(inputText);
                pw.flush();
                pw.close();
                /*if (new File("D:\\明星数据.txt").exists()) {
                    FileWriter fw1 = new FileWriter("D:\\明星数据.txt", true);
                    PrintWriter pw = new PrintWriter(fw1);
                    pw.print(inputText);
                    pw.flush();
                    pw.close();
    
                } else {
    
                }*/
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
        public void searchNext(int currPageNum, HttpRequest currRequest) {
            //总页数只有2178
            if (currPageNum < 2179) {
    //            System.out.println("----------第" + currPageNum + "页----------");
                int nextPageNum = currPageNum + 1;
    //            System.out.println("----------第" + nextPageNum + "页----------");
                String currUrl = currRequest.getUrl();
                String nextUrl = StringUtils.replaceOnce(currUrl, "page=" + currPageNum, "page=" + nextPageNum);
                SchedulerContext.into(currRequest.subRequest(nextUrl));
            } else {
                System.out.println("---------------爬取完毕------------------");
            }
    
        }
    }
    
    

    主要是第几页没有能对。以及页面获取属性。@Text @HtmlField的理解使用
    这就就搞定了。总页数是根据网站里面二判断的。
    还有明星的实体

    package com.geccocrawler.gecco.demo.mingxing;
    
    import com.geccocrawler.gecco.annotation.Html;
    import com.geccocrawler.gecco.annotation.HtmlField;
    import com.geccocrawler.gecco.annotation.Text;
    import com.geccocrawler.gecco.spider.HtmlBean;
    
    public class StarDetail implements HtmlBean {
    
        /*//明星的照片
        @Image("src")
        @HtmlField(cssPath = "a > img")
        prie String PhotoString;*/
    
        //明星的名字
        @Html
        @HtmlField(cssPath ="div > div > h4")
        private String  starNameHtml;
    
        //明星的性别
        @Text
        @HtmlField(cssPath = "div > p:nth-child(2)")
        private  String starSex;
    
        //明星的职业
        @Html
        @HtmlField(cssPath = "div > p:nth-child(3)")
        private String professionHtml;
    
        //明星的国籍
        @Text
        @HtmlField(cssPath = " div > p:nth-child(4)")
        private String  nationality;
    
        //明星的出生日期
        @Text
        @HtmlField(cssPath = "div > p.special")
        private String birthday;
    
        //明星的星座
        @Text
        @HtmlField(cssPath = "div > p:nth-child(6)>a")
        private String constellation;
    
        //明星的身高
        @Text
        @HtmlField(cssPath = "div > p:nth-child(7)")
        private String height;
    
        public String getStarNameHtml() {
            return starNameHtml;
        }
    
        public void setStarNameHtml(String starNameHtml) {
            this.starNameHtml = starNameHtml;
        }
    
        public String getStarSex() {
            return starSex;
        }
    
        public void setStarSex(String starSex) {
            this.starSex = starSex;
        }
    
        public String getProfessionHtml() {
            return professionHtml;
        }
    
        public void setProfessionHtml(String professionHtml) {
            this.professionHtml = professionHtml;
        }
    
        public String getNationality() {
            return nationality;
        }
    
        public void setNationality(String nationality) {
            this.nationality = nationality;
        }
    
        public String getBirthday() {
            return birthday;
        }
    
        public void setBirthday(String birthday) {
            this.birthday = birthday;
        }
    
        public String getConstellation() {
            return constellation;
        }
    
        public void setConstellation(String constellation) {
            this.constellation = constellation;
        }
    
        public String getHeight() {
            return height;
        }
    
        public void setHeight(String height) {
            this.height = height;
        }
    }
    

    最后就保存在d盘明星数据.txt中,就循环进行的。

    相关文章

      网友评论

          本文标题:gecco 的学习和练习

          本文链接:https://www.haomeiwen.com/subject/mmoudltx.html