美文网首页
Java爬虫小试牛刀

Java爬虫小试牛刀

作者: codingCat喵 | 来源:发表于2019-02-07 23:47 被阅读0次

    爬虫?相信很多人对这个词都不陌生,简单来说,就是利用工具爬取网页上的数据并加以整理分析。照例向小白科普一下对爬虫的误区、原理以及实现。

    爬虫常见的误区:python=爬虫?

    很多小白会把python与爬虫划等号,实际上,python是一种计算机程序设计语言,它不仅仅可以做爬虫,也可以构建web应用,最近大火的人工智能,也是可以使用python语言来实现的。
    而爬虫,其本质是抓取服务器向浏览器响应的数据(下文原理会详述),不同的计算机程序设计语言如Java,C#都可以实现爬虫。

    小结:python≠爬虫,python的功能远比我们想象中的要强大,爬虫也并非只有python可以实现。

    爬虫原理

    让我们回忆一下我们访问百度时的过程:

    1.在地址栏中输入一个URL:https://www.baidu.com/
    有人肯定会说,我从来没这么干过,我都是用浏览器一打开的导航进百度的。
    其实这么进入百度,只是浏览器替你输入了访问百度的链接。
    2.浏览器刷新了一下,百度的搜索框出现在我们眼前。
    当然了,网速卡顿刷新不出来的情况不考虑。

    这期间,浏览器与服务器之间发生了什么?

    1.浏览器向服务器发送URL,即请求地址。
    2.服务器接到浏览器发来的网络请求,开始向浏览器响应数据。
    3.浏览器接到服务器发来的数据,进行解析,并展示出来。
    有兴趣的可以清除一下浏览器缓存,使用Fn+F12组合键打开浏览器控制台,选择NetWork菜单,页面刷新时可以看到具体的响应过程

    爬虫的实现机制

    1.既然浏览器可以向服务器发送请求地址,我们也可以用程序向服务器发起请求。
    2.既然浏览器可以接到服务器发来的数据,我们就可以模仿浏览器解析的过程,通过筛选,拿到我们想要的数据。
    小结:通过我们自己编写的程序,无需重复动手整理我们想要的数据,这一切交给我们的爬虫程序来搞定。

    Java爬虫的具体案例

    目标:爬取山西农业大学新闻网首页中院部动态模块展示的最新新闻,并将新闻内容以文件的形式保存到本地。


    爬取资源1
    爬取资源2
    (一)需求分析

    1.解析新闻网主页,抓取到院部动态模块的内容
    2.模拟跳转,进入每一条新闻页面,抓取新闻具体内容
    3.将新闻具体内容保存在文件中

    (二)代码实现

    1.使用maven工具,在pom.xml中导入我们爬虫所依赖的jar包

      <dependencies>
            <!-- httpclient:用于向浏览器发送请求 -->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.5.3</version>
            </dependency>
            <!-- jsoup:用于解析浏览器发来的数据 -->
            <dependency>
                <groupId>org.jsoup</groupId>
                <artifactId>jsoup</artifactId>
                <version>1.8.3</version>
            </dependency>
            <!-- log4j:用于生成日志 -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.16</version>
            </dependency>
            <!-- junit:用于单元测试 -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
            </dependency>
        </dependencies>
    

    2.制作一个简易的用于发送请求的类

    package com.sxau.example;
    
    import java.io.IOException;
    
    import org.apache.http.HttpHost;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.conn.params.ConnRouteParams;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.params.CoreConnectionPNames;
    import org.apache.http.util.EntityUtils;
    
    public class MyClient {
        public String getContent(String url) throws ClientProtocolException, IOException {
            // 创建httpclient对象
            HttpClient hClient = new DefaultHttpClient();
            // 设置连接超时时间,响应超时时间,以及代理服务器
            hClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000)
                    .setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
                    .setParameter(ConnRouteParams.DEFAULT_PROXY, new HttpHost("117.191.11.71", 8080));
            // 创建get请求对象
            HttpGet hGet = new HttpGet(url);
            // 模拟请求,获得服务器响应的源码
            HttpResponse response = hClient.execute(hGet);
            // 将源码转换为字符串
            String content = EntityUtils.toString(response.getEntity(), "UTF-8");
            // 返回转化后的字符串
            return content;
        }
    }
    
    

    3.制作一个用于解析服务器数据的类

    package com.sxau.example;
    
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.select.Elements;
    
    public class MyJsoup {
        public Elements getTarget(
                String htmlResource,String selectCondition) {
            //解析服务器发来的数据
            Document doc = Jsoup.parse(htmlResource);
            //对解析后的数据通过条件筛选
            Elements elements = doc.select(selectCondition);
            return elements;
        }
    }
    
    

    4.制作一个将文件存储至本地的类

    package com.sxau.example;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class MyFileIO {
        public void makeFile(String title,String txtContent) throws IOException {
            //将标题左右多余的空格去掉
            title = title.trim();
            //拿到当前应用所在路径
            String property = System.getProperty("user.dir");
            //设置生成文件的路径与名称
            String filePath = property + "\\src\\main\\webapp\\spidertxt\\" + title + ".txt";
            //生成新文件
            File txt = new File(filePath);
            //将文件输入器定位到刚刚生成的新文件
            FileWriter writer = new FileWriter(txt);
            //将已经匹配的字符串写入文件中
            writer.write(txtContent);
            //刷新并关闭流
            writer.flush();
            writer.close();
        }
    }
    
    

    5.为了提高效率,制作一个线程用于并发处理

    package com.sxau.example;
    
    import java.io.IOException;
    
    import org.apache.http.client.ClientProtocolException;
    import org.jsoup.select.Elements;
    /**
     * 实现Runable接口
     * @author Administrator
     *
     */
    public class MyThread implements Runnable{
        
        private String mainUrl;
        private String singleUrl;
        //提供有参数的构造方法,确保进入页面时url不为空
        public MyThread(String mainUrl, String singleUrl) {
            this.mainUrl = mainUrl;
            this.singleUrl = singleUrl;
        }
        /**
         * 实现接口未实现的run()方法
         * 通过httpclient发送请求并接收数据
         * 观察html页面,使用jsoup中便捷的仿css/js选择器语法得到我们需要的内容
         * 对匹配好的字符串进行优化,并进行本地存储
         */
        @Override
        public void run() {
            // TODO 自动生成的方法存根
            MyClient myClient = new MyClient();
            String url=mainUrl+singleUrl;
            String content;
            try {
                content = myClient.getContent(url);
                String selectCondition1=".arti_title";
                String selectCondition2=".wp_articlecontent";
                MyJsoup jsoup = new MyJsoup();
                Elements elements1 = jsoup.getTarget(content, selectCondition1);
                Elements elements2 = jsoup.getTarget(content, selectCondition2);
                String html1 = elements1.get(0).html();
                String title = html1.replaceAll("<div class=\"arti_title\"></div>", "");
                String html2 = elements2.get(0).html();
                html2 = html2.replaceAll("<p>", "");
                String word = html2.replaceAll("</p>", "");
                MyFileIO fileIO=new MyFileIO();
                fileIO.makeFile(title, word);
            } catch (ClientProtocolException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            } catch (IOException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
            
        }
        
    }
    
    

    6.制作主体程序

    package com.sxau.example;
    
    import java.io.IOException;
    
    import org.apache.http.client.ClientProtocolException;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
    
    public class MySpider {
        public static void main(String[] args) throws ClientProtocolException, IOException {
            MyClient myClient = new MyClient();
            String url="http://news.sxau.edu.cn/";
            String content = myClient.getContent(url);
            String selectCondition="a[href][title~=(|)]";
            MyJsoup jsoup = new MyJsoup();
            Elements elements = jsoup.getTarget(content, selectCondition);
            for (Element element : elements) {
                String attr = element.attr("href");
                new Thread(new MyThread(url, attr)).start();
            }
            System.out.println("文件爬虫成功!");
        }
    }
    
    

    6.运行mian方法,稍等片刻,新鲜出炉的文件已经安静地在文件夹里躺着。

    log4j:WARN No appenders could be found for logger (org.apache.http.impl.conn.BasicClientConnectionManager).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    文件爬虫成功!
    
    最终效果

    至此,一个简单的爬虫功能就实现了。新手上路,有什么问题还请各位看官不吝赐教,互相探讨共同进步。

    相关文章

      网友评论

          本文标题:Java爬虫小试牛刀

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