Java爬取校内论坛新帖

为了保持消息灵通,博主没事会上上校内论坛看看新帖,作为爬虫爱好者,博主萌生了写个爬虫自动下载的想法。

嗯,这次就选Java。

第三方库准备

  • Jsoup

Jsoup是一款比较好的Java版HTML解析器。可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

  • mysql-connector-java

mysql-connector-java是java JDBC的MySQL驱动,可以提供方便统一的接口来操纵MySQL数据库

爬虫步骤

  • 目标分析
  • 爬取网页
  • 解析网页
  • 存储数据

目标分析

博主爬取的是浙大的cc98论坛,需要内网才能上,新帖会在其中一个版面内出现,界面大概是这样:

分析一下之后,发现100条新帖一共有5页,内容呈现在一张表格上。

再用Firefox分析一下页面,发现是一个class="tableborder1"的table下有20行记录,每一行有4个td,爬虫只要获取这四个td数据就可以了。

爬取网页

由于这个网站是要用用户名和密码登录的,博主一开始都在使用POST方法,后来用Firefox抓包分析之后,才发现可以使用带cookies的GET方法登录。

private void getDoc(String url, String page)
{
try
{
//获取网页
this.doc = Jsoup.connect(url)
.cookie("aspsky", "***")
.cookie("BoardList","BoardID=Show")
.cookie("owaenabled","True")
.cookie("autoplay","True")
.cookie("ASPSESSIONIDSSCBSSCR","***")
.data(" stype","3")
.data("page",page) //Page就是1-5页
.get();
}
catch (IOException e)
{
e.printStackTrace();
throw new RuntimeException();
}
}

这里使用到的Jsoup很强大,其实还可以添加header之类的作修饰,但博主发现只要加了cookies之后就能成功访问了。

解析网页

根据目标分析的结果,我们可以开始解析HTML文档,同样地,Jsoup允许使用JQuery方法来解析,十分方便

private void parse()
{
//采用JQuery CSS选择
Elements rows = doc.select(".tableborder1 tr");
//去掉表头行
rows.remove(0); for(Element row : rows)
{
String theme = row.select("td:eq(0) a:eq(1)").text().trim();
String url = "http://www.cc98.org/"
+ row.select("td:eq(0) a:eq(1)").attr("href");
String part = row.select("td:eq(1) a").text().trim();
String author = row.select("td:eq(2) a").text().trim();
if(author.length()==0)
{
author = "匿名";
}
String rawTime = row.select("td:eq(3)").text().
replace("\n","")
.replace("\t","");
try
{
Date publishTime = sdf.parse(rawTime);
System.out.println(publishTime+" "+theme);
System.out.println("---------------------------------------------------------");
storage.store(theme,publishTime,part,author,url);
}
catch (ParseException e)
{
e.printStackTrace();
}
}
}

存储数据

为了方便日后的分析(博主还打算偶尔分析一下各个版面的活跃情况),我们要把数据存储到硬盘上,这里选用了jdbc连接MySQL

    public void store(String theme, Date publishTime,
String part, String author,
String url)
{
try
{
String sql = "INSERT INTO news (theme," +
"publishTime,part,author,url)VALUES(?,?,?,?,?)"; //使用预处理的方法
PreparedStatement ps = null; ps = conn.prepareStatement(sql); //依次填入参数
ps.setString(1,theme);
java.sql.Time time = new java.sql.Time(publishTime.getTime());
//这里使用数据库的时间戳
ps.setTimestamp(2,new Timestamp(publishTime.getTime()));
ps.setString(3,part);
ps.setString(4,author);
ps.setString(5,url); ps.executeUpdate();
}
catch (SQLException e)
{
//主要是重复的异常,在MySQL中已经有约束unique
// e.printStackTrace();
}
}

我们可以通过MySQL可视化工具查看结果,由于MySQLworkbench不太好用,博主使用了DBeaver,结果如下:

结果非常令人满意。

完整代码

Spider.java

package com.company;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class Spider
{
private Document doc;
//定义时间格式
private SimpleDateFormat sdf = new SimpleDateFormat( "  yyyy/MM/dd  HH:mm " );
Storage storage = new Storage(); private void getDoc(String url, String page)
{
try
{
//获取网页
this.doc = Jsoup.connect(url)
.cookie("aspsky", "***")
.cookie("BoardList","BoardID=Show")
.cookie("owaenabled","True")
.cookie("autoplay","True")
.cookie("ASPSESSIONIDSSCBSSCR","***")
.data(" stype","3")
.data("page",page)
.get();
}
catch (IOException e)
{
e.printStackTrace();
throw new RuntimeException();
}
} private void parse()
{
//采用JQuery CSS选择
Elements rows = doc.select(".tableborder1 tr");
//去掉表头行
rows.remove(0); for(Element row : rows)
{
String theme = row.select("td:eq(0) a:eq(1)").text().trim();
String url = "http://www.cc98.org/"
+ row.select("td:eq(0) a:eq(1)").attr("href");
String part = row.select("td:eq(1) a").text().trim();
String author = row.select("td:eq(2) a").text().trim();
if(author.length()==0)
{
author = "匿名";
}
String rawTime = row.select("td:eq(3)").text().
replace("\n","")
.replace("\t","");
try
{
Date publishTime = sdf.parse(rawTime);
System.out.println(publishTime+" "+theme);
System.out.println("---------------------------------------------------------");
storage.store(theme,publishTime,part,author,url);
}
catch (ParseException e)
{
e.printStackTrace();
}
}
} public void run(String url)
{
for (Integer i = 1; i<=5; i++)
{
getDoc(url, i.toString());
parse();
}
storage.close();
} public static void main(String[] args)
{
Spider spider = new Spider();
spider.run("http://www.cc98.org/queryresult.asp?stype=3");
}
}

Storage.java

package com.company;

import java.sql.*;
import java.util.Date; public class Storage {
//数据库连接字符串,cc98为数据库名
private static final String URL="jdbc:mysql://localhost:3306/cc98?characterEncoding=utf8&useSSL=false";
//登录名
private static final String NAME="***";
//密码
private static final String PASSWORD="***"; private Connection conn = null;
public Storage()
{
//加载jdbc驱动
try
{
Class.forName("com.mysql.jdbc.Driver");
}
catch (ClassNotFoundException e)
{
System.out.println("未能成功加载驱动程序,请检查是否导入驱动程序!");
e.printStackTrace();
}
try
{
conn = DriverManager.getConnection(URL, NAME, PASSWORD);
// System.out.println("获取数据库连接成功!");
}
catch (SQLException e)
{
// System.out.println("获取数据库连接失败!");
e.printStackTrace();
}
} public void close()
{
//关闭数据库
if(conn!=null)
{
try
{
conn.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
public void store(String theme, Date publishTime,
String part, String author,
String url)
{
try
{
String sql = "INSERT INTO news (theme," +
"publishTime,part,author,url)VALUES(?,?,?,?,?)";
//使用预处理的方法
PreparedStatement ps = null; ps = conn.prepareStatement(sql); //依次填入参数
ps.setString(1,theme);
java.sql.Time time = new java.sql.Time(publishTime.getTime());
//这里使用数据库的时间戳
ps.setTimestamp(2,new Timestamp(publishTime.getTime()));
ps.setString(3,part);
ps.setString(4,author);
ps.setString(5,url); ps.executeUpdate();
}
catch (SQLException e)
{
//主要是重复的异常,在MySQL中已经有约束unique
// e.printStackTrace();
}
}
}

小结

这个项目其实涉及的知识点还挺多的,博主也刚学java,很多细节也没有很好吃透,如JDBC、Jsoup都值得好好学习一下。欢迎大家批评指正。

另,祝大家中秋国庆双节快乐~

Java爬取校内论坛新帖的更多相关文章

  1. Java爬取先知论坛文章

    Java爬取先知论坛文章 0x00 前言 上篇文章写了部分爬虫代码,这里给出一个完整的爬取先知论坛文章代码. 0x01 代码实现 pom.xml加入依赖: <dependencies> & ...

  2. 【Python】爬取理想论坛单帖爬虫

    代码: # 单帖爬虫,用于爬取理想论坛帖子得到发帖人,发帖时间和回帖时间,url例子见main函数 from bs4 import BeautifulSoup import requests impo ...

  3. Java爬取B站弹幕 —— Python云图Wordcloud生成弹幕词云

    一 . Java爬取B站弹幕 弹幕的存储位置 如何通过B站视频AV号找到弹幕对应的xml文件号 首先爬取视频网页,将对应视频网页源码获得 就可以找到该视频的av号aid=8678034 还有弹幕序号, ...

  4. MinerHtmlThread.java 爬取页面线程

    MinerHtmlThread.java 爬取页面线程 package com.iteye.injavawetrust.miner; import org.apache.commons.logging ...

  5. MinerConfig.java 爬取配置类

    MinerConfig.java 爬取配置类 package com.iteye.injavawetrust.miner; import java.util.List; /** * 爬取配置类 * @ ...

  6. Java爬取网络博客文章

    前言 近期本人在某云上购买了个人域名,本想着以后购买与服务器搭建自己的个人网站,由于需要筹备的太多,暂时先搁置了,想着先借用GitHub Pages搭建一个静态的站,搭建的过程其实也曲折,主要是域名地 ...

  7. java爬取网页内容 简单例子(2)——附jsoup的select用法详解

    [背景] 在上一篇博文java爬取网页内容 简单例子(1)——使用正则表达式 里面,介绍了如何使用正则表达式去解析网页的内容,虽然该正则表达式比较通用,但繁琐,代码量多,现实中想要想出一条简单的正则表 ...

  8. java爬取并下载酷狗TOP500歌曲

    是这样的,之前买车送的垃圾记录仪不能用了,这两天狠心买了好点的记录仪,带导航.音乐.蓝牙.4G等功能,寻思,既然有这些功能就利用起来,用4G听歌有点奢侈,就准备去酷狗下点歌听,居然都是需要办会员才能下 ...

  9. Java爬取并下载酷狗音乐

    本文方法及代码仅供学习,仅供学习. 案例: 下载酷狗TOP500歌曲,代码用到的代码库包含:Jsoup.HttpClient.fastJson等. 正文: 1.分析是否可以获取到TOP500歌单 打开 ...

随机推荐

  1. java去除html代码中含有的html、js、css标签,获取文字内容

    https://blog.csdn.net/u010882234/article/details/80585175

  2. Centos6中Docker使用中国官方镜像加速

    vi /etc/sysconfig/docker 增加如下内容: other_args="--registry-mirror=https://registry.docker-cn.com&q ...

  3. tp3.2上传图片生成缩略图

    //引入 use think\Image; /* * $name为表单上传的name值 * $filePath为为保存在入口文件夹public下面uploads/下面的文件夹名称,没有的话会自动创建 ...

  4. JSP基础知识➣Cookie和Session(五)

    JSP Cookie 处理 Cookie是存储在客户机的文本文件,它们保存了大量轨迹信息.在servlet技术基础上,JSP显然能够提供对HTTP cookie的支持.JSP脚本通过request对象 ...

  5. noip2012

    题解: 闲着无聊做了一遍noip2012 我觉得出题出的好奇怪啊... 为什么两道倍增两道二分答案??? 两天第一题: 第一天第一题傻逼普及组题没什么好说的了 第二天第一题你会扩欧就秒了 两天第二题: ...

  6. springboot创建错误

    1.Unknown system variable 'query_cache_size' 解决:https://www.cnblogs.com/nicknailo/articles/9074804.h ...

  7. Python select解析

    一.首先列一下,sellect.poll.epoll三者的区别 1.select a.select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监控多个文件描述符的数组,当 ...

  8. 008 RestFul API 拦截器

    一:任务 1.任务 过滤器Filter 拦截器Interceptor 切片Aspect 二:过滤器 1.新建包 2.自定义过滤器程序 加了注解,这个过滤器在springboot中就起作用了 packa ...

  9. 20165235 祁瑛 2018-4 《Java程序设计》第八周学习总结

    20165235 祁瑛 2018-4 <Java程序设计>第八周学习总结 教材学习内容总结 操作系统与进程 程序是一段静态的代码,它是应用软件执行的蓝本.进程是程序的一次动态执行过程,它对 ...

  10. day 68 django 之api操作 | jQueryset集合与对象

    我们的orm里面分为: jQueryset集合, 还有对象, 我们的jqueryset集合里面可以有多个对象,这句话的意思就是我们的对象是最小的单位,不可以再拆分了,我们的jQueryset集合就相当 ...