@Hadi
初来乍到 多多点赞
前言
之前闲来无事逛了逛csdn看了点博文发现有些博主文章还是挺有趣的,看了几篇类似的网页爬虫的应用觉得写得挺好,于是在寻找目标之后对新浪微博动起了邪念~😄
一、目标需求分析
1. 对目标网页的分析
所有的爬虫起始步骤都一样,首先都是先对目标的网页结构进行分析,然后确定自己使用的方法或者框架是否适用,再进行下一步。有对流程的把控才会有相应的效率。
分享下我的经验,先看网页源码,如果找到目标的内容的话就是静态爬虫这种是最简单的抓取,非常基础的内容。然后如果源码找不到相应的内容的话,一般就是动态加载的网页,这就属于动态爬虫的范畴,这时候就要F12XHR或者All去观察相应的请求地址,再进行下一步的操作,然后就是设置请求头 调delay 放Session 等一系列的应对反爬机制的操作再进一步测试调试观察。所以思路清晰很重要!!
今天的主角很明显就是一个静态网页,很简单不用框架直接抓取就行。😐
2. 整体需求分析
在网页分析过后开始要对整体流程的做一个需求分析,因为原本我想使用scrapy框架来应对动态页面或者一些反爬机制,但既然现在不需要的话我直接就用java写吧,因为之前搭的小web是ssm架构的,所以直接选用java去做整个流程会比较快,直接扔进去就好了。其实用什么语言去写需求不重要,你可以用php 你可以用python,主要是看需求怎么去完成比较顺手,以及实现后的预想性能效果如何,找到最优解就可以了,我是比较随心的,我直接用java,图表的话这里直接用echarts简单粗暴,没听说过的直接去百度echarts就好了用法很简单,网页定位这里的话我一般会用xpath,因为正则很繁琐本人也不是很熟练,所以就是xpath定位爬取静态资源=>整理数据且json格式化=>echarts+ajax异步加载实现动态图表
二、效果展示
1. 网址
可以直接到本人网站看效果
服务器这里我调的是3秒请求一次,为什么这么慢咧因为刚开始是1秒share给人看后请求太密集就被新浪安全中心狙击了hhhhhhhhhhhhh
2.刷不出来的看图吧
三、来人把代码端上来
(我这里的话直接用servlet做的简易web有点懒😊)
代码如下:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dom4j.io.SAXReader;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.jsoup.Jsoup;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Servlet implementation class getjson
*/
@WebServlet("/getdata")
public class getdata extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public getdata() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
// TODO Auto-generated method stub
try {
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("UTF-8");
SAXReader reader = new SAXReader();
String html = Jsoup.connect("https://s.weibo.com/top/summary?Refer=top_hot&topnav=1&wvr=6").get().html().replace("&", "&");
InputStream htmlinp=new ByteArrayInputStream(html.getBytes("UTF-8"));
String textxpath="//td[@class='td-02']/a";
String countxpath="//td[@class='td-02']/span";
Document doc = reader.read(htmlinp);
List<Element> textlist = doc.selectNodes(textxpath);
List<Element> countlist = doc.selectNodes(countxpath);
textlist.remove(0);
ArrayList tl=new ArrayList();
ArrayList cl=new ArrayList();
//遍历热搜文字节点
for (Element ele : textlist) {
tl.add(ele.getText());
//System.out.println("热搜" + ":" + ele.getText());
}
//遍历点击量节点
for (Element ele : countlist) {
cl.add(ele.getText());
//System.out.println("点击量"+ ":" + ele.getText());
}
Map<String, ArrayList> map = new HashMap<String,ArrayList>();
map.put("text", tl);
map.put("count", cl);
ObjectMapper oj=new ObjectMapper();
String jsonresult=oj.writeValueAsString(map);
System.out.println(jsonresult);
PrintWriter out = response.getWriter();
out.print(jsonresult);
out.flush();
out.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
2.前端(echarts+ajax)
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>新浪微博实时热搜数据</title>
</head>
<script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.min.js"></script>
<body>
<h1 align="center">ProducedBy@Hadi2021</h1>
<div id="main" style="width: 1550px;height:600px;"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
myChart.setOption({
title: {
text: '实时热搜监测',
subtext: 'From weibo.sina'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '8%',
bottom: '5%',
containLabel: true
},
xAxis: {
type: 'value',
boundaryGap: [0, 0.01]
},
yAxis: {
type: 'category',
data: []
},
series: [
{
name: '',
type: 'bar',
data: ['热搜词']
}
]
});
myChart.showLoading(); //数据加载完之前先显示一段简单的loading动画
function sendRequest(){
$.ajax({
type : "post",
async : true, //异步请求(同步请求将会锁住浏览器,用户其他操作必须等待请求完成才可以执行)
url : "getdata", //请求发送到TestServlet处
data : {},
dataType : "json", //返回数据形式为json
success : function(result) {
myChart.hideLoading(); //隐藏加载动画
myChart.setOption({ //加载数据图表
yAxis: {
data: result.text
},
series: [{
// 根据名字对应到相应的系列
name: '实时搜索量',
data: result.count
}]
});
},
error : function(errorMsg) {
//请求失败时执行该函数
alert("图表请求数据失败!");
myChart.hideLoading();
}
})}
$(function () { //加载页面的时候就会调用定时刷新
setInterval("sendRequest()", 1000); //每隔1秒刷新点击量
});
</script>
</body>
</html>
这里的实时更新其实就是setInterval方法里的定时调用函数罢了。定时调用ajax请求servlet中的返回值。
写在最后
这是我第一篇文章,虽然不知道有没有人看,但这也花了我一个早上的摸鱼时间,我是Hadi,希望看我文章的人都能给我点个赞让我也有继续更下去的动力,分享一些有趣的东西和自己的小经验 好了我干饭去了~!!!!