本文主要是介绍java爬虫-------爬取携程景点及门票数据,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.爬虫
-
- 网络爬虫简介
他的主要工作就是 跟据指定的url地址 去发送请求,获得响应, 然后解析响应 , 一方面从响应中查找出想要查找的数据,另一方面从响应中解析出新的URL路径,然后继续访问,继续解析;继续查找需要的数据和继续解析出新的URL路径 .
这就是网络爬虫主要干的工作. 下面是流程图:
-
- 爬虫准备
通过上面的流程图 能大概了解到 网络爬虫 干了哪些活 ,根据这些 也就能设计出一个简单的网络爬虫出来.
一个简单的爬虫 必需的功能:
1: 发送请求和获取响应的功能 ;
2: 解析响应的功能 ;
3: 对 过滤出的数据 进行存储 的功能 ;
4: 对解析出来的URL路径 处理的功能 ;
2.java爬虫
2.1实现java爬虫的三种简易方式
- 通过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();
}
}
- 通过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.组装的对象进行入库操作
这篇关于java爬虫-------爬取携程景点及门票数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!