java爬虫-------爬取携程景点及门票数据

1.爬虫

    1. 网络爬虫简介

   他的主要工作就是 跟据指定的url地址 去发送请求,获得响应, 然后解析响应 , 一方面从响应中查找出想要查找的数据,另一方面从响应中解析出新的URL路径,然后继续访问,继续解析;继续查找需要的数据和继续解析出新的URL路径  .

这就是网络爬虫主要干的工作.  下面是流程图:

    1. 爬虫准备

通过上面的流程图 能大概了解到 网络爬虫 干了哪些活  ,根据这些 也就能设计出一个简单的网络爬虫出来.

 

一个简单的爬虫 必需的功能:  

 

1: 发送请求和获取响应的功能 ;

 

2: 解析响应的功能 ;

 

3: 对 过滤出的数据 进行存储 的功能 ;

 

4: 对解析出来的URL路径 处理的功能 ;

2.java爬虫

2.1实现java爬虫的三种简易方式

  1. 通过urlconnection抓取信息:

步骤:
1.获取url
2.获取http请求
3.获取状态码
4.根据状态吗返回信息。

代码:
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class ConnectionUtil {

    public static String Connect(String address){
        HttpURLConnection conn = null;
        URL url = null;
        InputStream in = null;
        BufferedReader reader = null;
        StringBuffer stringBuffer = null;
        try {
            //1.新建url对象,表示要访问的网页
            url = new URL(address);
            //2.建立http连接,返回连接对象urlconnection
            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setDoInput(true);
            conn.connect();

            //3.获取相应的http状态码,
            int code=conn.getResponseCode();
            if(code!=200){
                return null;
            }
            //4.如果获取成功,从URLconnection对象获取输入流来获取请求网页的源代码
            in = conn.getInputStream();
            reader = new BufferedReader(new InputStreamReader(in));
            stringBuffer = new StringBuffer();
            String line = null;
            while((line = reader.readLine()) != null){
                stringBuffer.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            conn.disconnect();
            try {
                in.close();
                reader.close();
            } catch (Exception e) {
                System.out.println("获取不到网页源码:"+e);
                e.printStackTrace();
            }
        }

        return stringBuffer.toString();
    }
}

 

  1. 通过httpclient抓取信息:

引入pom依赖

<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>

 

步骤
1.创建一个客户端,类似打开一个浏览器
2./创建一个get方法,类似在浏览器中输入一个地址,path则为URL的值
3.获得响应的状态码
4.得到返回的类容
5.释放资源

代码:

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * Created by Administrator on 2018/8/7.
 */
public class HttpClient3 {

    public static String doGet(String url) {
        // 输入流
        InputStream is = null;
        BufferedReader br = null;
        String result = null;
        // 创建httpClient实例
        HttpClient httpClient = new HttpClient();
        // 设置http连接主机服务超时时间:15000毫秒
        // 先获取连接管理器对象,再获取参数对象,再进行参数的赋值
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000);
        // 创建一个Get方法实例对象
        GetMethod getMethod = new GetMethod(url);
        // 设置get请求超时为60000毫秒
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000);
        // 设置请求重试机制,默认重试次数:3次,参数设置为true,重试机制可用,false相反
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, true));
        try {
            // 执行Get方法
            int statusCode = httpClient.executeMethod(getMethod);
            // 判断返回码
            if (statusCode != HttpStatus.SC_OK) {
                // 如果状态码返回的不是ok,说明失败了,打印错误信息
                System.err.println("Method faild: " + getMethod.getStatusLine());
            } else {
                // 通过getMethod实例,获取远程的一个输入流
                is = getMethod.getResponseBodyAsStream();
                // 包装输入流
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));

                StringBuffer sbf = new StringBuffer();
                // 读取封装的输入流
                String temp = null;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp).append("\r\n");
                }

                result = sbf.toString();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 释放连接
            getMethod.releaseConnection();
        }
        return result;
    }
    
    
    public static void main(String[] args){
        String s=doGet("http://www.baidu.com");
    }
}

 

3.通过jsoup获取网页信息:

引入jsoup jar包或maven依赖

<dependency>
   <!-- jsoup HTML parser library @ https://jsoup.org/ -->
   <groupId>org.jsoup</groupId>
   <artifactId>jsoup</artifactId>
   <version>1.11.3</version>
</dependency>

 

import java.io.File;
import java.io.IOException;


import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * Created by Administrator on 2018/7/31.
 */
public class spider {
    public static void main(String[] args) throws IOException {
        String url = "http://www.baidu.com";
        Document document = Jsoup.connect(url).timeout(3000).get();


//通过Document的select方法获取属性结点集合
        Elements elements = document.select("a[href]");
//得到节点的第一个对象
        Element element = elements.get(0);
        System.out.println(element);

    }

}

 

3.java爬虫案例

3.1爬取百度上的所有链接

1.使用正则表达式进行信息提取

首先建立urlconnection连接获取网页返回的数据,然后使用正则表达式提取所有的 http链接地址

快速学习正则https://www.jb51.net/tools/zhengze.html

 

import java.io.BufferedReader;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class WebSpider {
    public static void main(String[] args) {
        URL url = null;
        URLConnection urlconn = null;
        BufferedReader br = null;
       // PrintWriter pw = null;

        try {
            //通过url建立与网页的连接
            url = new URL("http://www.baidu.com/");
            urlconn = url.openConnection();
            //pw = new PrintWriter(new FileWriter("f:/url(baidu).txt"), true);//这里我把爬到的链接存储在了F盘底下的一个叫做url(baidu)的doc文件中
            //通过链接取得网页返回的数据
            br = new BufferedReader(new InputStreamReader(urlconn.getInputStream()));
            String buf = null;
            StringBuffer stringBuffer = new StringBuffer();
            while ((buf = br.readLine()) != null) {
                stringBuffer.append(buf);
            }
            System.out.println("获取成功!"+stringBuffer);
            //编写获取http链接的正则表达式
            String regex = "http://[\\w+\\.?/?]+\\.[A-Za-z]+";
            Pattern p = Pattern.compile(regex);
            //匹配返回的结果
            Matcher m=p.matcher(stringBuffer.toString());
            while(m.find()){//查找匹配的链接
                String a=m.group();
                System.out.println("====爬取的链接"+a);
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
           // pw.close();
        }
    }
}

 

 

 

 

 

 

2.使用jsoup解析遍历

Jsonp学习地址:html:http://www.open-open.com/jsoup/dom-navigation.htm

//使用http的get方式获取返回的网页信息
HttpClient h=new JavaHttpClient();
String s = h.doGet("http://www.baidu.com",null).getResponseString();
//System.out.println("======"+s);
Document root_document = Jsoup.parse(s);//将html的字符串解析成一个html文档
//获取所有a标签元素
Elements e=root_document.getElementsByTag("a");
//循环获取a标签的href属性
for(int i=0;i<e.size();i++){
    Element href=e.get(i);//得到每一个a标签
    String link=href.attr("href");//获取href属性
    System.out.println("====获取到的链接:"+link);
}

3.2爬取携程上的景点信息

1.首先进去携程页面,我需要爬取的是杭州的景点信息如图,点击搜索杭州,会看到以下的景点信息。

2.查看网页信息,使用谷歌的浏览器debug模式,也就是f12 我们先观察网页的布局检查元素寻找需要爬取到的信息。

3.通过查看发现所需要的数据都在<div id="searchResultContainer" class="searchresult_left"> 这个div中

我们获取一下这个div,使用jsonp的dom操作获取,获取之后在获取景点列表,可以看到列表景点的样式为searchresult_product04(在执行过程中发现样式除了04外还有searchresult_product05 所以我合并了两个集合)

HttpClient h=new JavaHttpClient();
String s = h.doGet(strurl,null).getResponseString();//自己写的一个http链接
Document root_document = Jsoup.parse(s);
//获取需要数据的div
Element e= root_document.getElementById("searchResultContainer");
//得到网页上的景点列表(包含两个样式集合)
Elements yy = e.getElementsByClass("searchresult_product04");
Elements yy2 = e.getElementsByClass("searchresult_product05");
yy.addAll(yy2);
System.out.println("-------------------------------------"+yy.size());

4.对获得的景点列表进行遍历获取每一个景点信息

使用jsoup的选择器进行信息抽取(使用方法可以利用谷歌的selectort)定位标题所在地方,鼠标右键copy->copy selector

得到#searchResultContainer > div:nth-child(1) > div > div.search_ticket_title > h2 > a

使用jsoup的select选择器 因为我们已经获取到了这个searchResultContainer div对象,所以直接用searchResultContainer 获取的对象像下级进行获取

Element nameStr=Info.selectFirst("div > div.search_ticket_title > h2 > a");

 

for(int i=0;i<yy.size();i++){
    //得到每一条景点信息
    Element Info=yy.get(i);
    //分析网页得到景点的标题(使用选择器语法来查找元素)
    Element nameStr=Info.selectFirst("div > div.search_ticket_title > h2 > a");
    String name=nameStr.html();//得到标题的信息
    String link=nameStr.attr("href");//得到标题的链接(可以存库对详情信息获取)
    Element gradeStr=Info.selectFirst(" div > div.search_ticket_title > h2 > span > span.rate");//得到景点等级
    String  grade=gradeStr.html();
    Element addressStr=Info.selectFirst("div > div.search_ticket_title > div.adress");//得到景点地址
    String address=addressStr.html();
    Element scoreStr=Info.selectFirst("div > div.search_ticket_assess > span.grades > em");//得到评分
    String score=null;
    if(scoreStr!=null){
        score=scoreStr.html();
    }
    Element judenumber=Info.selectFirst("div > div.search_ticket_assess > span.grades");//得到评论人数
    String judenum="";
    if(judenumber!=null){
        judenum=judenumber.text();//----分(3580人点评)
        //使用正则表达式抽取评论人数
        Pattern p=Pattern.compile("\\(.*人点评\\)");
        Matcher m=p.matcher(judenum);
        if(m.find()){
            judenum=m.group();
        }
    }
    Element specialStr=Info.selectFirst("div > div.search_ticket_title > div.exercise");//得到特色
    String special=specialStr.html();
    grade=("").equals(grade)?null:grade;
    //获取的地址是这样的 ----》地址:浙江省湖州市安吉县递铺镇天使大道1号  所以需要进行截取操作
    address=("").equals(address)?null:address.substring(address.indexOf(":")+1);
    special=("").equals(special)?null:special.substring(special.indexOf(":")+1);
    judenum=("").equals(judenumber)?null:Utils.getNum(judenum);
    System.out.println("==="+name);

    //组装成对象
    Object[] o=new Object[8];
    o[0]=name;
    o[1]=address;
    o[2]=score;
    o[3]=judenum;
    o[4]="杭州";
    o[5]=grade;
    o[6]=special;
    o[7]=link;
    insertqueue2.add(o);//加入队列进行入库
}

 

5.组装的对象进行入库操作

 

 

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值