Java实现爬虫
为什么我们要爬取数据
在大数据时代,我们要获取更多数据,就要进行数据的挖掘、分析、筛选,比如当我们做一个项目的时候,需要大量真实的数据的时候,就需要去某些网站进行爬取,有些网站的数据爬取后保存到数据库还不能够直接使用,需要进行清洗、过滤后才能使用,我们知道有些数据是非常真贵的。
分析豆瓣电影网站
我们使用chrome浏览器去访问豆瓣的网站如
https://movie.douban.com/explore#!type=movie&tag=%e7%83%ad%e9%97%a8&sort=recommend&page_limit=20&page_start=0
在chrome浏览器的network中会得到如下的数据
可以看到地址栏上的参数type=movie&tag=热门&sort=recommend&page_limit=20&page_start=0
其中type是电影tag是标签,sort是按照热门进行排序的,page_limit是每页20条数据,page_start是从第几页开始查询。
但是这不是我们想要的,我们需要去找豆瓣电影数据的总入口地址是下面这个
https://movie.douban.com/tag/#/
我们再次的去访问请求终于拿到了豆瓣的电影数据如下图所示
在看下请求头信息
最后我们确认了爬取的入口为:
https://movie.douban.com/j/new_search_subjects?sort=u&range=0,10&tags=&start=0
创建maven项目开始爬取
我们创建一个maven工程,如下图所示
maven工程的依赖,这里只是爬取数据,所以没有必要使用spring,这里使用的数据持久层框架是mybatis 数据库用的是mysql,下面是maven的依赖
<dependencies> <dependency> <groupid>org.json</groupid> <artifactid>json</artifactid> <version>20160810</version> </dependency> <dependency> <groupid>com.alibaba</groupid> <artifactid>fastjson</artifactid> <version>1.2.47</version> </dependency> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <version>5.1.47</version> </dependency> <dependency> <groupid>org.mybatis</groupid> <artifactid>mybatis</artifactid> <version>3.5.1</version> </dependency> <dependency> <groupid>junit</groupid> <artifactid>junit</artifactid> <version>4.12</version> </dependency> </dependencies>
创建好之后,结构如下所示
首先我们在model包中建立实体对象,字段和豆瓣电影的字段一样,就是请求豆瓣电影的json对象里面的字段
movie实体类
public class movie { private string id; //电影的id private string directors;//导演 private string title;//标题 private string cover;//封面 private string rate;//评分 private string casts;//演员 public string getid() { return id; } public void setid(string id) { this.id = id; } public string getdirectors() { return directors; } public void setdirectors(string directors) { this.directors = directors; } public string gettitle() { return title; } public void settitle(string title) { this.title = title; } public string getcover() { return cover; } public void setcover(string cover) { this.cover = cover; } public string getrate() { return rate; } public void setrate(string rate) { this.rate = rate; } public string getcasts() { return casts; } public void setcasts(string casts) { this.casts = casts; } }
这里注意的是导演和演员是多个人我没有直接处理。这里应该是一个数组对象。
创建mapper接口
public interface moviemapper { void insert(movie movie); list<movie> findall(); }
在resources下创建数据连接配置文件jdbc.properties
driver=com.mysql.jdbc.driver url=jdbc:mysql://localhost:3306/huadi username=root password=root
创建mybatis配置文件 mybatis-config.xml
<?xml version="1.0" encoding="utf-8" ?> <!doctype configuration public "-//mybatis.org//dtd config 3.0//en" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="jdbc.properties"></properties> <environments default="development"> <environment id="development"> <transactionmanager type="jdbc"/> <datasource type="pooled"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </datasource> </environment> </environments> <mappers> <mapper resource="moviemapper.xml"/> </mappers> </configuration>
创建mapper.xml映射文件
<!doctype mapper public "-//mybatis.org//dtd mapper 3.0//en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cn.scitc.mapper.moviemapper"> <resultmap id="moviemappermap" type="com.cn.scitc.model.movie"> <id column="id" property="id" jdbctype="varchar"/> <id column="title" property="title" jdbctype="varchar"/> <id column="cover" property="cover" jdbctype="varchar"/> <id column="rate" property="rate" jdbctype="varchar"/> <id column="casts" property="casts" jdbctype="varchar"/> <id column="directors" property="directors" jdbctype="varchar"/> </resultmap> <insert id="insert" keyproperty="id" parametertype="com.cn.scitc.model.movie"> insert into movie(id,title,cover,rate,casts,directors) values (#{id},#{title},#{cover},#{rate},#{casts},#{directors}) </insert> <select id="findall" resultmap="moviemappermap"> select * from movie </select> </mapper>
由于这里没有用任何的第三方爬虫框架,用的是原生java的http协议进行爬取的,所以我写了一个工具类
public class getjson { public jsonobject gethttpjson(string url, int comefrom) throws exception { try { url realurl = new url(url); httpurlconnection connection = (httpurlconnection) realurl.openconnection(); connection.setrequestproperty("accept", "*/*"); connection.setrequestproperty("connection", "keep-alive"); connection.setrequestproperty("user-agent", "mozilla/4.0 (compatible; msie 6.0; windows nt 5.1;sv1)"); // 建立实际的连接 connection.connect(); //请求成功 if (connection.getresponsecode() == 200) { inputstream is = connection.getinputstream(); bytearrayoutputstream baos = new bytearrayoutputstream(); //10mb的缓存 byte[] buffer = new byte[10485760]; int len = 0; while ((len = is.read(buffer)) != -1) { baos.write(buffer, 0, len); } string jsonstring = baos.tostring(); baos.close(); is.close(); //转换成json数据处理 // gethttpjson函数的后面的参数1,表示返回的是json数据,2表示http接口的数据在一个()中的数据 jsonobject jsonarray = getjsonstring(jsonstring, comefrom); return jsonarray; } } catch (malformedurlexception e) { e.printstacktrace(); } catch (ioexception ex) { ex.printstacktrace(); } return null; } public jsonobject getjsonstring(string str, int comefrom) throws exception{ jsonobject jo = null; if(comefrom==1){ return new jsonobject(str); }else if(comefrom==2){ int indexstart = 0; //字符处理 for(int i=0;i<str.length();i++){ if(str.charat(i)=='('){ indexstart = i; break; } } string strnew = ""; //分割字符串 for(int i=indexstart+1;i<str.length()-1;i++){ strnew += str.charat(i); } return new jsonobject(strnew); } return jo; } }
爬取豆瓣电影的启动类
public class main { public static void main(string [] args) { string resource = "mybatis-config.xml"; 定义配置文件路径 inputstream inputstream = null; try { inputstream = resources.getresourceasstream(resource);//读取配置文件 } catch (ioexception e) { e.printstacktrace(); } sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream);//注册mybatis 工厂 sqlsession sqlsession = sqlsessionfactory.opensession();//得到连接对象 moviemapper moviemapper = sqlsession.getmapper(moviemapper.class);//从mybatis中得到dao对象 int start;//每页多少条 int total = 0;//记录数 int end = 9979;//总共9979条数据 for (start = 0; start <= end; start += 20) { try { string address = "https://movie.douban.com/j/new_search_subjects?sort=u&range=0,10&tags=&start=" + start; jsonobject dayline = new getjson().gethttpjson(address, 1); system.out.println("start:" + start); jsonarray json = dayline.getjsonarray("data"); list<movie> list = json.parsearray(json.tostring(), movie.class); if (start <= end){ system.out.println("已经爬取到底了"); sqlsession.close(); } for (movie movie : list) { moviemapper.insert(movie); sqlsession.commit(); } total += list.size(); system.out.println("正在爬取中---共抓取:" + total + "条数据"); } catch (exception e) { e.printstacktrace(); } } } }
最后我们运行将所有的数据插入到数据库中。
项目地址
总结
爬取豆瓣网站非常的轻松,每页任何的难度,需要注意的是就是start是每页多少条我们发现规则当start=0的时候是20条数据是从0到19条,就这样每次加20条直到爬取完。
到此这篇关于java实现爬虫的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。