前言:
最近几个月因为接触了一些活动外团的的工作,对网页数据的获取比较频繁,所以开始接触了Spider的一些编写,之前也接触过Python这门语言,但是用它来写爬虫,虽然编写速度快,执行效率高,但是个人对Java语言学习的多一点,因此用Java语言来编写了一个spider。
思考:
一开始的spider是通过爬取网页源代码来获得我们所需要的数据,而比较原始的网站,它的一个前端数据显示是静态的,所有很简单的可以通过右击查看源代码就可以看到当前页面的内容了,如图:
编写的一个spider把这个能看到的源代码拿下来封装到HtmlPage这个类中然后再转换成Document
而这时候已经拿到了需要的源代码,那么就要通过css选择器来筛选出我们需要的信息了。
代码:
核心方法,传入对应参数可以获取到对应的网页源码
public static Document getHtmlDocument(String url,boolean JavaScriptEnabled) {
final WebClient webClient = new WebClient(BrowserVersion.CHROME);//新建一个模拟谷歌浏览器客户端对象
webClient.getOptions().setThrowExceptionOnScriptError(false);//JS执行出错的时是否抛出异常
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//HTTP的状态非200时是否抛出异常
webClient.getOptions().setActiveXNative(false);
webClient.getOptions().setCssEnabled(false);//是否启用CSS
webClient.getOptions().setJavaScriptEnabled(JavaScriptEnabled); //是否启用JS
webClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置支持AJAX
HtmlPage page = null;
try {
page = webClient.getPage(url);//尝试加载网页
} catch (Exception e) {
//e.printStackTrace();
} finally {
webClient.close();
}
webClient.waitForBackgroundJavaScript(30000);
String pageXml = page.asXml();//直接将加载完成的页面转换成xml格式的字符串
Document document = Jsoup.parse(pageXml);
return document;
}
这开发的的一个spider,可以获取对应帖子的用户名,楼层,回帖内容,以及回帖中包含的图片,因为某些问题就把代码都丢一块去了,别太在意关键代码如下:
public void crawler(String url,String bodyFormat,boolean isImg) {
//建立一个存储整体数据的list
List<List<String>> dataList = new ArrayList<>();
//存放用户名
String names ="";
//进行爬取并接收数据
Document document = HtmlUtil.getHtmlDocument(url, false);
/**
* 获取每个用户昵称所附带的链接,通过此链接能够进一步获取到真实的用户名
*/
List<String> linkList = PageParserTool.getLinks(
"https://tieba.baidu.com",
document.select("a[class~=p_author_name (.*?)]"),"a","href");
/**
* 获取帖子中用户回复的内容
*/
List<Element> bodyList = document.select("div[id~=post_content_(-?\\d*)(\\.\\d+)?]");
/**
*获取用户等级数据
*/
List<Element> LVList = document.select("div[class~=d_badge_title (.*?)]");
/**
* 获取本页面的所有楼层数
*/
List<Element> floorList = document.select("span[class=tail-info]");
/**该list用于保存最后一个遍历的楼层的数组下标*/
List<Integer> sum = new ArrayList<Integer>();
sum.add(0, 0);
/**
* * 进行数据遍历
*/
for (int i = 0; i < bodyList.size(); i++) {
/**
* 通过 linkList 列表保存的地址获取当前回复内容所属的真实用户名
*/
Document doc = HtmlUtil.getHtmlDocument(linkList.get(i), false);
Elements elements = doc.select("span[class=user_name]");
//建立一个信息存贮列表,存储用户名,内容以及楼层信息
List<String> data = new ArrayList<>();
//建立楼层模糊匹配
Pattern pattern = Pattern.compile("楼");
/**
* 进行楼层匹配查询,获取当前内容所属楼层
*/
for (int a = sum.get(0) + 1; a < floorList.size(); a++) {
//判断该内容是否为楼层数据
Matcher matcher = pattern.matcher(String.valueOf(floorList.get(a)));
if (matcher.find()) {
sum.set(0, a);
String str = PageParserTool.StripHT(String.valueOf(floorList.get(a))).trim();
data.add(str);
break;
}
}
if (elements != null) {
/**
* 输出用户名
*/
String str;
try {
str = PageParserTool.StripHT(String.valueOf(elements.get(0)));//提取纯文本文件
} catch (Exception e) {
data.add(3,"无法找到给用户,请到对应楼层查看具体问题");
str = "**用户不存在**";
}
//字符截断,获得用户名
names = StringUtils.substringBefore((str), "吧龄").substring(5).trim();
System.out.println(names);
data.add(names);
//开启图片收集
if(isImg){
List<String> imgUrl = PageParserTool.getLinks("",
bodyList.get(i).select("img[class=BDE_Image ]"),
"img","src");//(.*?)
if(imgUrl != null){
ImgUtils.Download(imgUrl,names+".jpg");
}
}
}
/**保存回帖内容*/
String body = PageParserTool.StripHT(String.valueOf(bodyList.get(i))).trim();
data.add(body);
if(isImg){
//添加图片路径,用于写入图片
data.add("F:\\COData\\res\\"+names+".jpg");
}
//添加数据
dataList.add(data);
}
//写进excel表格中
ExcelOperationUtil.addExcel("TBdata.xlsx", dataList,isImg);
}
当我们把数据都获取处理完毕后,就可以存放到自己需要放置的文件了,这里导出为excel文件。
尾言:
在这里一个一个关于爬取某吧的数据的spider就可以是讲述完毕了,可能写的不是很好,有错迎告之!
行路赏景,与君共勉!