【转】java爬虫,爬取当当网数据
背景:女票快毕业了(没错!我是有女票的!!!),写论文,主题是儿童性教育,查看儿童性教育绘本数据死活找不到,没办法,就去当当网查询下数据,但是数据怎么弄下来呢,首先想到用Python,但是不会!!百度一番,最终决定还是用java大法爬虫,毕竟java熟悉点,话不多说,开工!:
实现:
首先搭建框架,创建一个maven项目,使用框架是springboot和mybatis,开发工具是idea,pom.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.com.boco</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.45</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>
目录结构如下:
连接的数据库是oracle本地的数据库,配置文件如下
注意:application.yml文件中
spring:
profiles:
active:dev
指定的就是application_dev.yml文件,就是配置文件用的这个,在实际开发中,可以通过这种方式配置几份配置环境,这样发布的时候切换active属性就行,不用修改配置文件了
application_dev.yml配置文件:
server:
port: 8084 spring:
datasource:
username: system
password: 123456
url: jdbc:oracle:thin:@localhost
driver-class-name: oracle.jdbc.driver.OracleDriver mybatis:
mapper-locations: classpath*:mapping/*.xml
type-aliases-package: cn.com.boco.demo.entity #showSql
logging:
level:
com:
example:
mapper : debug
application.yml文件:
spring:
profiles:
active: dev
启动类如下,加上MapperScan注解,扫描dao层的接口:
@MapperScan("cn.com.boco.demo.mapper")
@SpringBootApplication
public class DemoApplication { public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
} }
dao层接口:
@Repository
public interface BookMapper { void insertBatch(List<DangBook> list); }
xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.com.boco.demo.mapper.BookMapper"> <insert id="insertBatch" parameterType="java.util.List">
INSERT ALL
<foreach collection="list" item="item" index="index" separator=" ">
into dangdang_message (title,img,author,publish,detail,price,parentUrl,inputTime) values
(#{item.title,jdbcType=VARCHAR},
#{item.img,jdbcType=VARCHAR},
#{item.author,jdbcType=VARCHAR},
#{item.publish,jdbcType=VARCHAR},
#{item.detail,jdbcType=VARCHAR},
#{item.price,jdbcType=DOUBLE},
#{item.parentUrl,jdbcType=VARCHAR},
#{item.inputTime,jdbcType=DATE}) </foreach>
select 1 from dual
</insert> </mapper>
两个实体类:
public class BaseModel { private int id;
private Date inputTime; public Date getInputTime() {
return inputTime;
} public void setInputTime(Date inputTime) {
this.inputTime = inputTime;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
}
}
@Alias("dangBook")
public class DangBook extends BaseModel { //标题
private String title;
//图片地址
private String img;
//作者
private String author;
//出版社
private String publish;
//详细说明
private String detail;
//价格
private float price;
//父链接,即请求链接
private String parentUrl; public String getParentUrl() {
return parentUrl;
} public void setParentUrl(String parentUrl) {
this.parentUrl = parentUrl;
} public String getAuthor() {
return author;
} public void setAuthor(String author) {
this.author = author;
} public String getPublish() {
return publish;
} public void setPublish(String publish) {
this.publish = publish;
} public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public String getImg() {
return img;
} public void setImg(String img) {
this.img = img;
} public String getDetail() {
return detail;
} public void setDetail(String detail) {
this.detail = detail;
} public float getPrice() {
return price;
} public void setPrice(float price) {
this.price = price;
} }
service层:
@Service
public class BookService { @Autowired
private BookMapper bookMapper; public void insertBatch(List<DangBook> list){
bookMapper.insertBatch(list);
} }
controll层代码:
@RestController
@RequestMapping("/book")
public class DangdangBookController { @Autowired
private BookService bookService; private static Logger logger = LoggerFactory.getLogger(DemoApplication.class);
//url解码之后
private static final String URL = "http://search.dangdang.com/?key=性教育绘本&act=input&att=1000006:226&page_index=";
//url解码之前
private static final String URL2 = "http://search.dangdang.com/?key=%D0%D4%BD%CC%D3%FD%BB%E6%B1%BE&act=input&att=1000006%3A226&page_index=";
@RequestMapping("/parse")
public JSONObject parse(){
JSONObject jsonObject = new JSONObject();
for(int i =1;i<=10;i++){
List<DangBook> dangBooks = ParseUtils.dingParse(URL+i);
if(dangBooks != null && dangBooks.size() >0){ logger.info("解析完数据,准备入库");
bookService.insertBatch(dangBooks);
logger.info("入库完成,入库数据条数"+ dangBooks.size());
jsonObject.put("code",1);
jsonObject.put("result","success");
}else{
jsonObject.put("code",0);
jsonObject.put("result","fail");
} }
return jsonObject;
} }
本来是前端传入地址解析的,但是发现参数丢失了,用url编码也不行,最后放到后台了
ParseUtils和HttpGetUtils工具类:
public class HttpGetUtils { private static Logger logger = LoggerFactory.getLogger(HttpGetUtils.class); public static String getUrlContent(String url) {
if (url == null) {
logger.info("url地址为空");
return null;
}
logger.info("url为:" + url);
logger.info("开始解析");
String contentLine = null;
//最新版httpclient.jar已经舍弃new DefaultHttpClient()
//但是还是可以用的
HttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResponse = getResp(httpClient, url);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
try {
contentLine = EntityUtils.toString(httpResponse.getEntity(), "utf-8");
} catch (IOException e) {
e.printStackTrace();
}
}
logger.info("解析结束");
return contentLine;
} /**
* 根据url 获取response对象
*/
public static HttpResponse getResp(HttpClient httpClient, String url) {
logger.info("开始获取response对象");
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
try {
httpResponse = httpClient.execute(httpGet);
} catch (IOException e) {
e.printStackTrace();
}
logger.info("获取对象结束");
return httpResponse;
} }
public class ParseUtils { private static Logger logger = LoggerFactory.getLogger(ParseUtils.class); public static List<DangBook> dingParse(String url) {
List<DangBook> list = new ArrayList<>();
Date date = new Date();
if (url == null) {
logger.info("url为空,数据获取结束");
return null;
} logger.info("开始获取数据");
String content = HttpGetUtils.getUrlContent(url);
if (content != null)
logger.info("得到解析数据");
else {
logger.info("解析数据为空,数据获取结束");
return null;
} Document document = Jsoup.parse(content);
//遍历当当图书列表
for(int i =1;i<=60;i++){
Elements elements = document.select("ul[class=bigimg]").select("li[class=line"+i+"]");
for (Element e : elements) {
String title = e.select("p[class=name]").select("a").text();
logger.info("书名:" + title);
String img = e.select("a[class=pic]").select("img").attr("data-original");
logger.info("图片地址:" + img);
String authorAndPublish = e.select("p[class=search_book_author]").select("span").select("a").text();
String []a = authorAndPublish.split(" ");
String author = a[0];
logger.info("作者:" + author);
String publish = a[a.length - 1];
logger.info("出版社:" + publish);
// String publish =e.select("p[class=name]").select("a").text();
String detail = e.select("p[class=detail]").text();
logger.info("图书介绍:" + detail);
String priceS = e.select("p[class=price]").select("span[class=search_now_price]").text();
float price = 0.0f;
if(priceS.length()>1 && priceS != null){
price = Float.parseFloat(priceS.substring(1, priceS.length() - 1));
}
logger.info("价格:" + price);
logger.info("-------------------------------------------------------------------------");
DangBook dangBook = new DangBook();
dangBook.setTitle(title);
dangBook.setImg(img);
dangBook.setAuthor(author);
dangBook.setPublish(publish);
dangBook.setDetail(detail);
dangBook.setPrice(price);
dangBook.setParentUrl(url);
dangBook.setInputTime(date);
list.add(dangBook);
}
}
return list;
} }
最后表里数据如下:
注意:建表的时候注意字段类型,orcale的var(255)不够我的这个数据标题用,开始报错,后来改了字段类型,还有注意ID的自增和入库时间的自动添加,个人数据库较差,百度一番才弄好
【转】java爬虫,爬取当当网数据的更多相关文章
- java爬虫,爬取当当网数据
背景:女票快毕业了(没错!我是有女票的!!!),写论文,主题是儿童性教育,查看儿童性教育绘本数据死活找不到,没办法,就去当当网查询下数据,但是数据怎么弄下来呢,首先想到用Python,但是不会!!百 ...
- python爬虫爬取赶集网数据
一.创建项目 scrapy startproject putu 二.创建spider文件 scrapy genspider patubole patubole.com 三.利用chrome浏览器 ...
- 网络爬虫之定向爬虫:爬取当当网2015年图书销售排行榜信息(Crawler)
做了个爬虫,爬取当当网--2015年图书销售排行榜 TOP500 爬取的基本思想是:通过浏览网页,列出你所想要获取的信息,然后通过浏览网页的源码和检查(这里用的是chrome)来获相关信息的节点,最后 ...
- Scrapy爬虫(5)爬取当当网图书畅销榜
本次将会使用Scrapy来爬取当当网的图书畅销榜,其网页截图如下: 我们的爬虫将会把每本书的排名,书名,作者,出版社,价格以及评论数爬取出来,并保存为csv格式的文件.项目的具体创建就不再多讲 ...
- python爬虫06 | 你的第一个爬虫,爬取当当网 Top 500 本五星好评书籍
来啦,老弟 我们已经知道怎么使用 Requests 进行各种请求骚操作 也知道了对服务器返回的数据如何使用 正则表达式 来过滤我们想要的内容 ... 那么接下来 我们就使用 requests 和 re ...
- python爬取当当网的书籍信息并保存到csv文件
python爬取当当网的书籍信息并保存到csv文件 依赖的库: requests #用来获取页面内容 BeautifulSoup #opython3不能安装BeautifulSoup,但可以安装Bea ...
- Python爬虫爬取全书网小说,程序源码+程序详细分析
Python爬虫爬取全书网小说教程 第一步:打开谷歌浏览器,搜索全书网,然后再点击你想下载的小说,进入图一页面后点击F12选择Network,如果没有内容按F5刷新一下 点击Network之后出现如下 ...
- Java实现爬取京东手机数据
Java实现爬取京东手机数据 最近看了某马的Java爬虫视频,看完后自己上手操作了下,基本达到了爬数据的要求,HTML页面源码也刚好复习了下,之前发布两篇关于简单爬虫的文章,也刚好用得上.项目没什么太 ...
- scrapy项目3:爬取当当网中机器学习的数据及价格(spider类)
1.网页解析 当当网中,人工智能数据的首页url如下为http://category.dangdang.com/cp01.54.12.00.00.00.html 点击下方的链接,一次观察各个页面的ur ...
随机推荐
- groupid公司名,artifactid模块名,version版本
- MongoDB学习笔记(一、MongoDB入门)
目录: 为什么要使用nosql mongo的简介 应用场景 入门demo 为什么要使用nosql: 随着互联网的发展,用户数量激增,访问量的上涨,传统的关系型数据库的性能也趋于瓶颈. 关系型数据库难以 ...
- 201871010101-陈来弟《面向对象程序设计(java)》第一周学习总结
项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址>http ...
- python的路径问题
## 文件路径出错问题 """ 如何获取与当前文件相关的地址 """ import os # 当前文件的完整路径 print(__file_ ...
- acwing 55. 连续子数组的最大和
地址 https://www.acwing.com/problem/content/50/ 输入一个 非空 整型数组,数组里的数可能为正,也可能为负. 数组中一个或连续的多个整数组成一个子数组. 求 ...
- maven clean插件使用进阶
maven clean插件使用进阶 参考 Maven clean 插件 Maven删除外部文件 查看命令帮助 mvn clean:help mvn clean:help -Ddetail=true - ...
- BZOJ1369/LG4395 「BOI2003」Gem 树形DP
问题描述 LG4395 BZOJ1369 题解 发现对于结点 \(x\) ,其父亲,自己,和所有的孩子权值不同,共 \(3\) 类,从贪心的角度考虑,肯定是填 \(1,2,3\) 这三种. 于是套路树 ...
- 【洛谷4173】残缺的字符串(重拾FFT)
点此看题面 大致题意: 有一个长度为\(n\)的字符串\(A\)和一个长度为\(m\)的字符串\(B\),其中存在一些字符'*'可以与任意字符匹配.求\(B\)中所有满足条件的位置,使得从这一位置开始 ...
- Codeforces Round #599 (Div. 2) B1. Character Swap (Easy Version) 水题
B1. Character Swap (Easy Version) This problem is different from the hard version. In this version U ...
- 云服务AppId或AppKey和AppSecret生成策略
App key和App Secret App key简称API接口验证序号,是用于验证API接入合法性的.接入哪个网站的API接口,就需要这个网站允许才能够接入,如果简单比喻的话:可以理解成是登陆网站 ...