soup
抓取网页后,需要对网页解析,可以使用字符串处理工具解析页面,也可以使用正则表达式
jsoup 的作用:是一款 Java 的HTML 解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操作方法来取出和操作数据
jsoup的主要功能如下:
1.从一个URL,文件或字符串中解析HTML;
2.使用DOM或CSS选择器来查找、取出数据;
3.可操作HTML元素、属性、文本;
创建练习类
解析URL
第一个参数是访问的url,第二个参数是访问的超时时间
使用标签选择器,获取title标签中的内容
输出结果
读取文件
准备一个简易的HTML文件
获取这个
读取文件,获取字符串,代码及结果
使用dom方式遍历文档
解析文件获取document对象
依据id获取,这个是id的内容,我们获取这个内容
编写代码,显示结果
依据标签获取,我们获取这个标签的内容
代码及结果
依据class获取,获取内容
代码和结果
依据属性,属性内容
代码和结果
接下来从元素中获取数据
首先从元素中获取ID
从元素中获取className
文本
代码及结果
如果内容是两个class
那么代码及结果
从元素中获取属性
代码及结果
获取元素的所有属性
代码及结果
从元素中获取文本内容,这个之前有,代码和结果
soup介绍
Jsoup是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
Jsoup主要功能
注册中心:
以实例来讲解Jsoup使用
步骤:创建项目、pom.xml引入、创建启动类、运行项目。
中文伪代码
需求:我们要爬取Docker技术文章,这个网站页面左边为菜单,右边为内容。
经过分析:菜单里的url,是在css的class:left-navigation下面的a标签下,并且url以/article/index/开始的。
内容:直接在css的class:article_content下面的html。开始写代码了:
pom.xml引入
<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.3</version> </dependency>
创建启动类
注:可能学校的教务系统已经做了升级,当前的程序不知道还能不能成功获取信息,加上已经毕业,我的账户已经被注销,试不了,在这里做下思路跟过程的记录。
在我的毕业设计中”基于SSM框架贺州学院校园二手交易平台设计与实现”我有这样一个设想:使用学校教务系统账号进行贺州学院学生身份认证(通过HttpClient模拟登陆),发布者身份信息真实、平台由学生(可以跟计算机协会合作,由他们进行维护)维护,平台安全可靠,校园身份认证时本校园二手交易平台的一大特色。为了实现这个功能,我对我们学校的教务系统进行了模拟登陆。
我通过HttpClients模拟登陆教务系统,获取学生信息,使用jsoup俗称“大杀器”进行解析响应回来的html 匹配个人信息a标签地址并做携带参数页Referer进行第二次请求,使用jsoup来解析响应回来的htm匹配所有学生信息获取我们想要的学生信息。在存储过程中要进行唯一性认证,一个账号只能认证一次,一个学生教务教务系统账号只能绑定一个平台账号。
目前头像的上传我是这样做的,先把图片下载的用户电脑本地作为临时文件,再调用FtpUtil.upload()方法读取文件上传到我们nginx图片服务器,成功上传后删除用户电脑中的临时文件。(因为上传需要传入一个InputStream但是在写代码过程中发现从响应回来的HttpResponse获取到的数据转为InputStream时文件出现损失导致上传后图片无法正常打开的情况)。而一个重要的技术点就是验证码的问题,在编写代码时发现想使用Tesseract-OCR开源工具,然而,实现起来没那么简单,所以我的做法是把教务系统的验证码直接writeTo到用户的HttpServletResponse获取图片验证码,直接响应回浏览器,让用户自己手动输入再传到后台。
引入jar:(如果想在控制台打印更多连接时的信息,可以使用log4j),或者使用maven引入也行
public class AuthenticationUtil {
private static HttpClient client = HttpClients.createDefault();//实例化httpclient
//static HttpResponse response = null;
private static String rawHtml; //响应回来的数据
/* public static void main(String[] args) throws Exception {
//模拟登陆教务系统,获取学生信息
System.out.println("======模拟登陆教务系统,获取学生信息======");
//获取验证码
int i=getVerifyingCode();
if(i==1){
//提醒用户并输入验证码
System.out.println("验证码图片下载成功! D:/verifyCode.gif,请输入图片验证码:");
String code;
Scanner in = new Scanner(System.in);
code = in.nextLine();
in.close();
Map map = login("xxx","***",code);
if("200".equals(map.get("code"))){
String xm= (String) map.get("xm");//姓名
String xh= (String) map.get("xh");//学号
String lbl_xb= (String) map.get("lbl_xb");//性别
String lbl_csrq= (String) map.get("lbl_csrq");//出生日期
String lbl_sfzh= (String) map.get("lbl_sfzh");//身份证号
String lbl_xy= (String) map.get("lbl_xy");//学院
String lbl_zymc= (String) map.get("lbl_zymc");//专业
String lbl_xzb= (String) map.get("lbl_xzb");//班级
System.out.println(xm);
}else{
System.out.println(map.get("msg"));
}
}else{
System.out.println("验证码图片下载失败...");
}
}*/
/**
* 模拟登陆
* @param login_xh
* @param login_mm
* @param code
* @throws IOException
* @throws ParseException
*/
public static Map<String,String> login(String login_xh,String login_mm,String code) throws Exception {
Map<String,String> map =new HashMap<String,String>();
String __VIEWSTATE="";
HttpGet getVerifyCode = new HttpGet("http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/default2.aspx");
HttpResponse response = client.execute(getVerifyCode);//获取验证码
rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
Document doc = Jsoup.parse(rawHtml);
Elements select_input = doc.select("input");
for (Element a : select_input) {
String name = a.attr("name");
if("__VIEWSTATE".equals(name)){
__VIEWSTATE=a.attr("value");
break;
}
}
//设定post参数
ArrayList<NameValuePair> postData = new ArrayList<NameValuePair>();
postData.add(new BasicNameValuePair("Button1", ""));
postData.add(new BasicNameValuePair("RadioButtonList1", "学生"));//登陆账号类型
postData.add(new BasicNameValuePair("TextBox2", login_mm));//密码
postData.add(new BasicNameValuePair("Textbox1", ""));
postData.add(new BasicNameValuePair("__VIEWSTATE", __VIEWSTATE));
postData.add(new BasicNameValuePair("hidPdrs", ""));
postData.add(new BasicNameValuePair("hidsc", ""));
postData.add(new BasicNameValuePair("lbLanguage", ""));
postData.add(new BasicNameValuePair("txtSecretCode", code));//验证码
postData.add(new BasicNameValuePair("txtUserName", login_xh));//学号
//登录 post请求
HttpPost post = new HttpPost("http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/default2.aspx");//构建post对象
post.setEntity(new UrlEncodedFormEntity(postData));//捆绑参数
post.setHeader("Accept", "text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8");//带上参数页
post.setHeader("Cookie", "safedog-flow-item=");//带上参数页
post.setHeader("Connection", "keep-alive");//带上参数页
post.setHeader("Content-Type", "application/x-www-form-urlencoded");//带上参数页
post.setHeader("Host", "jwxt.hzu.gx.cn");//带上参数页
post.setHeader("Origin", "http://jwxt.hzu.gx.cn");//带上参数页
post.setHeader("Upgrade-Insecure-Requests", "1");//带上参数页
post.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36");//带上参数页
post.setHeader("Referer", "http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/default2.aspx");//带上referer 参数页
response = client.execute(post);//执行登陆行为
//登录成功,发生302重定向
if(302==response.getStatusLine().getStatusCode()){
//把响应结果打印出来
System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));
Header header = response.getFirstHeader("location"); // 跳转的目标地址是在 HTTP-HEAD 中的
String newuri = header.getValue(); // 这就是跳转后的地址,再向这个地址发出新申请,以便得到跳转后的信息是啥。
newuri="http://jwxt.hzu.gx.cn/"+newuri;
// System.out.println(newuri);
//登录成功 get请求
HttpGet get=new HttpGet(newuri);
get.setHeader("Cookie", "safedog-flow-item=");//带上参数页
get.setHeader("Host", "jwxt.hzu.gx.cn");//带上参数页
get.setHeader("Referer", "http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/default2.aspx");//带上referer 参数页
// client.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 2000);
// client.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 2000);
// 超时设置
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();//设置请求和传输超时时间
get.setConfig(requestConfig);
/*
* 第二次身份认证时,程序会卡在这里
*
*/
response = (CloseableHttpResponse) client.execute(get);//执行重定向
//打印输出
// rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
// System.out.println(rawHtml);
String xsgrxxUrl="http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/";//个人信息a标签地址
if(200==response.getStatusLine().getStatusCode()){
//使用jsoup来解析响应回来的html 匹配个人信息a标签地址
rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
Document document = Jsoup.parse(rawHtml);
Elements select_a = document.select("a");
for (Element a : select_a) {
String href = a.attr("href");
if(href.indexOf("xsgrxx.aspx")!=-1){
xsgrxxUrl=xsgrxxUrl+href;
break;
}
}
//查看个人信息 get请求
get=new HttpGet(xsgrxxUrl);
post.setHeader("Cookie", "safedog-flow-item=");//带上参数页
post.setHeader("Host", "jwxt.hzu.gx.cn");//带上参数页
get.setHeader("Referer", newuri);//带上referer 参数页
response = (CloseableHttpResponse) client.execute(get);//执行
}
rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
//打印输出
// System.out.println(rawHtml);
//使用jsoup来解析响应回来的html 匹配所有学生信息
Document document = Jsoup.parse(rawHtml);
Elements select_span = document.select("span");
for (Element span : select_span) {
String id = span.attr("id");
if("xh".equals(id)){//学号
String xh = span.text();
map.put("xh", xh);
// System.out.println("学号:"+xh);
}
if("xm".equals(id)){//姓名
String xm = span.text();
map.put("xm", xm);
// System.out.println("姓名:"+xm);
}
// if("lbl_TELNUMBER".equals(id)){//手机号码
// String lbl_TELNUMBER = span.text();
// System.out.println("手机号码:"+lbl_TELNUMBER);
// }
if("lbl_xb".equals(id)){//性别
String lbl_xb = span.text();
map.put("lbl_xb", lbl_xb);
// System.out.println("性别:"+lbl_xb);
}
if("lbl_csrq".equals(id)){//出生日期
String lbl_csrq = span.text();
map.put("lbl_csrq", lbl_csrq);
// System.out.println("出生日期:"+lbl_csrq);
}
if("lbl_byzx".equals(id)){//毕业中学
String lbl_byzx = span.text();
map.put("lbl_byzx", lbl_byzx);
// System.out.println("毕业中学:"+lbl_byzx);
}
if("lbl_mz".equals(id)){//民族
String lbl_mz = span.text();
map.put("lbl_mz", lbl_mz);
// System.out.println("民族:"+lbl_mz);
}
if("lbl_sfzh".equals(id)){//身份证号
String lbl_sfzh = span.text();
map.put("lbl_sfzh", lbl_sfzh);
// System.out.println("身份证号:"+lbl_sfzh);
}
if("lbl_xy".equals(id)){//学院
String lbl_xy = span.text();
map.put("lbl_xy", lbl_xy);
// System.out.println("学院:"+lbl_xy);
}
if("lbl_zymc".equals(id)){//专业
String lbl_zymc = span.text();
map.put("lbl_zymc", lbl_zymc);
// System.out.println("专业:"+lbl_zymc);
}
if("lbl_xzb".equals(id)){//班级
String lbl_xzb = span.text();
map.put("lbl_xzb", lbl_xzb);
// System.out.println("班级:"+lbl_xzb);
}
if("lbl_lys".equals(id)){//所在省份
String lbl_lys = span.text();
map.put("lbl_lys", lbl_lys);
// System.out.println("所在省份:"+lbl_lys);
}
if("jtdz".equals(id)){//家庭住址
String jtdz = span.text();
map.put("jtdz", jtdz);
// System.out.println("家庭住址:"+jtdz);
}
}
//上传头像到图片服务器上
Elements select_img = document.select("img");
String imagUrl = select_img.attr("src");
getPortrait((String)map.get("xh"),"http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/"+imagUrl, xsgrxxUrl);
//ftp上传到图片服务器
FileInputStream fileInputStream = new FileInputStream(new File("D:/portrait.jpg"));
CpshResult result = FtpUtil.upload((String)map.get("xh")+"_portrait.jpg", fileInputStream);
if(result.getStatus()==200){
map.put("tx", result.getData()+"");
//把文件删掉
File file = new File("D:/portrait.jpg");
file.delete();
}else{
System.out.println("头像上传失败!");
}
//成功
map.put("code", "200");
map.put("msg", "验证成功");
}else if(200==response.getStatusLine().getStatusCode()){//响应状态200,登录失败
//使用jsoup来解析响应回来的html 解析弹窗提示信息
rawHtml = EntityUtils.toString(response.getEntity(), "utf-8");
Document document = Jsoup.parse(rawHtml);
Elements select_script = document.select("script");
String msg="";
for (Element script : select_script) {
String html = script.html();
if(html.indexOf("alert")!=-1){
//只保留中文汉字
msg=html.replaceAll("[^\u4E00-\u9FA5]", "");
break;
}
}
//成功
map.put("code", "400");
map.put("msg", msg);
// System.out.println(msg);
}else if(500==response.getStatusLine().getStatusCode()){//
map.put("code", "500");
map.put("msg", "教务系统响应500...");
}
// client.getConnectionManager().shutdown();
// response.close();
return map;
}
/**
* 获取图片验证码,直接响应回浏览器
* @param client
* @return
*/
public static void getVerifyingCode(HttpServletResponse response1){
try {
HttpGet getVerifyCode = new HttpGet("http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/CheckCode.aspx");//验证码get
HttpResponse response = client.execute(getVerifyCode);//获取验证码
if(200==response.getStatusLine().getStatusCode()){//200响应码
//将响应回来的图片信息writeTo 到 fileOutputStream
response.getEntity().writeTo(response1.getOutputStream());
}
} catch (Exception e) {
e.printStackTrace();
// return 0;
}finally {
}
}
/**
* 获取图片验证码,下载到本地
* @param client
* @return
*/
public static int getVerifyingCode(){
FileOutputStream fileOutputStream = null;
try {
// HttpClient client = HttpClients.createDefault();//实例化httpclient
HttpGet getVerifyCode = new HttpGet("http://jwxt.hzu.gx.cn/(ffxibsu12r31de551s3q4w3o)/CheckCode.aspx");//验证码get
HttpResponse response;
response = client.execute(getVerifyCode);//获取验证码
if(200==response.getStatusLine().getStatusCode()){//200响应码
/*验证码写入文件,保存为verifyCode.jped*/
fileOutputStream = new FileOutputStream(new File("D:/verifyCode.gif"));
//将响应回来的图片信息writeTo 到 fileOutputStream
response.getEntity().writeTo(fileOutputStream);
return 1;
}else{
return 0;
}
} catch (Exception e) {
e.printStackTrace();
return 0;
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 下载头像图片
* @param cilent
* @param imagUrl
* @param referer
* @return
*/
public static void getPortrait(String xh,String imagUrl,String referer){
// HttpClient client = HttpClients.createDefault();//实例化httpclient
FileOutputStream fileOutputStream=null;
try {
// HttpClient client = HttpClients.createDefault();//实例化httpclient
HttpGet portrait = new HttpGet(imagUrl);//get请求 头像照片
//portrait.setHeader("Referer",referer);
HttpResponse response = client.execute(portrait);// 执行
if(200==response.getStatusLine().getStatusCode()){//200响应码
// /*图片写入文件,保存为portrait.jpg*/
File file = new File("D:/portrait.jpg");
file.createNewFile();
fileOutputStream = new FileOutputStream(file);
response.getEntity().writeTo(fileOutputStream);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.flush();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
可以再控制台打印出来,我这里是作为layer弹窗:
作者:huanzi-qch
出处:https://www.cnblogs.com/huanzi-qch
若标题中有“转载”字样,则本文版权归原作者所有。若无转载字样,本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.
*请认真填写需求信息,我们会在24小时内与您取得联系。