动态ajax页面为什么会再同一个页面有多个分页,就是因为当你点击其他页的时候服务器返回一串json串,js执行json参数达到改变页面效果。下面说说如何抓取json串。
1:爬取信息要对源页有所了解,首先打开虎牙直播,谷歌F12选取network。点xhr。里面可能会有多个json文件,点击第三页。
发现点击第三页后会出现一个新的json串。点击看下
会发现服务器返回的数据就是这个页面所显示的。你想要的数据都在里面。可以通过这个数据爬取有用的信息。查看服务器的请求
最下面一行的Query String Parameters就是需要的请求,这样我们模拟请求就可以获取信息。
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class test2 {
public static void main(String[] args) throws IOException
{
String url="https://www.huya.com/";
Connection connect = Jsoup.connect(url).timeout(20000);
Map<String, String> header = new HashMap<String, String>();
header.put("m", "LiveList");
header.put("do", "getLiveListByPage");
header.put("tagAll", "0");
header.put("page", "3");
connect.data(header);
Document doc=connect.get();
System.out.println(doc.text());
}
}
却发现输出的是
这个就是前面xhr中的response文件。并且这是一个json串,要想转换json变成我们想要的东西。就要使用阿里的fastjson解析工具,导入fastjson包就可以使用。对于fastjson的简单使用,可以先简单对单个数据摸索。尝试看看。就可以获得想要的数据。json串的解析和获取信息需要自己慢慢摸索。贴上最终的代码:
import java.io.IOException;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
/*
* 直接抓所有直播
*/
public class 抓取所有直播 {
public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException {
int id=1;
/*
* 连接数据库
*/
java.sql.Connection con;
Class.forName("com.mysql.jdbc.Driver");
System.out.println("数据库驱动加载成功");
con = DriverManager.getConnection("jdbc:mysql:"
+ "//127.0.0.1:3306/db?useSSL=true", "root", "123456");
System.out.println("数据库连接成功");
/*
* 模拟请求 注意,请求的页面不同
*/
String url="https://www.huya.com/";
Connection connect = Jsoup.connect(url).timeout(20000);
Map<String, String> header = new HashMap<String, String>();
header.put("m", "LiveList");
header.put("do", "getLiveListByPage");
header.put("tagAll", "0");
int page=0;//页数
//获取页面数操作 首先要用jsoup解析当前页面,看看有多少页,
Document exam=Jsoup.connect("https://www.huya.com/l").get();//请求链接所有直播
Elements links = exam.getElementsByClass("list-page");//可以遍历到人数和主播昵称
page=Integer.parseInt(links.attr("data-pages")) ;
System.out.println(page);
for(int i=0;i<page;i++) {
header.put("page", 1+i+"");
Connection data = connect.data(header);
Document doc= data.get(); //获取json字符串
// System.out.println(doc.text());
try {
JSONObject jsonObj = JSON.parseObject(doc.text()); //将json字符串转成中文 获得主要的json串
//System.out.println(jsonObj);
JSONObject jsonOb=JSON.parseObject(jsonObj.getString("data"));//获取data选项的json内容
// System.out.println(jsonOb);
JSONArray jarr=jsonOb.getJSONArray("datas");//获取datas内容的jsonarray可以看作是多组jsonobjiect组成
for(Object jar:jarr)
{
JSONObject js=JSON.parseObject( jar.toString());//获取更具体的json值
/*
* 写入数据库
*/
int renshu=Integer.parseInt((String) js.get("totalCount"));
String type=js.get("gameFullName").toString();
String sql2="insert into satuday(name,href,number,type)value(?,?,?,?)";//插入mysql姓名 链接 观看人数 分类
PreparedStatement pstmt = con.prepareStatement(sql2);
pstmt.setString(1, (String) js.get("nick")); //可以查看json数据preview里面的选项做参考
pstmt.setString(2, "https://www.huya.com/"+js.get("profileRoom"));
pstmt.setInt(3, renshu);
pstmt.setString(4,type );
pstmt.execute();
System.out.println(js.get("gameFullName")+""+id+++" "+i+"");
}
}
catch(Exception e) {System.out.println(e.getMessage());}
}
con.close();
}
}
有一点比较重要的是解析json时一定要使用try catch别用再主函数抛出异常,因为各种原因可能服务器会返回错误的一个或者json串,而多组数据如果不用try catch的话会异常终止,使用后会直接跳过去,这种情况虽然少但是还是会发生。所以大不了就跳过一页中间数据。这样,数据就存在数据库里了。
初学者。可能代码有很多不好的地方。多多见谅