java爬虫,爬取当当网数据

时间:2022-01-18 07:50:07

   背景:女票快毕业了(没错!我是有女票的!!!),写论文,主题是儿童性教育,查看儿童性教育绘本数据死活找不到,没办法,就去当当网查询下数据,但是数据怎么弄下来呢,首先想到用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>

目录结构如下:

java爬虫,爬取当当网数据

连接的数据库是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;
} }

最后表里数据如下:

java爬虫,爬取当当网数据

注意:建表的时候注意字段类型,orcale的var(255)不够我的这个数据标题用,开始报错,后来改了字段类型,还有注意ID的自增和入库时间的自动添加,个人数据库较差,百度一番才弄好

java爬虫,爬取当当网数据的更多相关文章

  1. 【转】java爬虫,爬取当当网数据

     背景:女票快毕业了(没错!我是有女票的!!!),写论文,主题是儿童性教育,查看儿童性教育绘本数据死活找不到,没办法,就去当当网查询下数据,但是数据怎么弄下来呢,首先想到用Python,但是不会!!百 ...

  2. python爬虫爬取赶集网数据

    一.创建项目 scrapy startproject putu 二.创建spider文件 scrapy genspider  patubole patubole.com   三.利用chrome浏览器 ...

  3. 网络爬虫之定向爬虫:爬取当当网2015年图书销售排行榜信息(Crawler)

    做了个爬虫,爬取当当网--2015年图书销售排行榜 TOP500 爬取的基本思想是:通过浏览网页,列出你所想要获取的信息,然后通过浏览网页的源码和检查(这里用的是chrome)来获相关信息的节点,最后 ...

  4. Scrapy爬虫(5)爬取当当网图书畅销榜

      本次将会使用Scrapy来爬取当当网的图书畅销榜,其网页截图如下:   我们的爬虫将会把每本书的排名,书名,作者,出版社,价格以及评论数爬取出来,并保存为csv格式的文件.项目的具体创建就不再多讲 ...

  5. python爬虫06 &vert; 你的第一个爬虫,爬取当当网 Top 500 本五星好评书籍

    来啦,老弟 我们已经知道怎么使用 Requests 进行各种请求骚操作 也知道了对服务器返回的数据如何使用 正则表达式 来过滤我们想要的内容 ... 那么接下来 我们就使用 requests 和 re ...

  6. python爬取当当网的书籍信息并保存到csv文件

    python爬取当当网的书籍信息并保存到csv文件 依赖的库: requests #用来获取页面内容 BeautifulSoup #opython3不能安装BeautifulSoup,但可以安装Bea ...

  7. Python爬虫爬取全书网小说,程序源码&plus;程序详细分析

    Python爬虫爬取全书网小说教程 第一步:打开谷歌浏览器,搜索全书网,然后再点击你想下载的小说,进入图一页面后点击F12选择Network,如果没有内容按F5刷新一下 点击Network之后出现如下 ...

  8. Java实现爬取京东手机数据

    Java实现爬取京东手机数据 最近看了某马的Java爬虫视频,看完后自己上手操作了下,基本达到了爬数据的要求,HTML页面源码也刚好复习了下,之前发布两篇关于简单爬虫的文章,也刚好用得上.项目没什么太 ...

  9. scrapy项目3:爬取当当网中机器学习的数据及价格(spider类)

    1.网页解析 当当网中,人工智能数据的首页url如下为http://category.dangdang.com/cp01.54.12.00.00.00.html 点击下方的链接,一次观察各个页面的ur ...

随机推荐

  1. NodeJS 最快速搭建一个HttpServer

    最快速搭建一个HttpServer 在目录里放一个index.html cd D:\Web\InternalWeb start http-server -i -p 8081

  2. &lbrack;转&rsqb;CSS3 Media Query实现响应布局

    讲到响应式布局, 相信大家都有一定的了解,响应式布局是今年很流行的一个设计理念,随着移动互联网的盛行,为解决如今各式各样的浏览器分辨率以及不同移动设备的显示效果, 设计师提出了响应式布局的设计方案.今 ...

  3. Eclipse cpp 开发 include路径

  4. Codevs 1230 STL万岁。。 。

    题目描述 Description 给出n个正整数,然后有m个询问,每个询问一个整数,询问该整数是否在n个正整数中出现过. 输入描述 Input Description 第一行两个整数 n 和m. 第二 ...

  5. 如何在十分钟内插入1亿条记录到Oracle数据库?

    这里提供一种方法,使用 APPEND 提示,使得十分钟内插入上亿数据成为可能. -- Create table create table TMP_TEST_CHAS_LEE ( f01 VARCHAR ...

  6. 判断手机连接的是fdd还是tdd的办法

    判断手机连接的是fdd还是tdd的办法http://bbs.ydss.cn/thread-550035-1-1.html移动4G一般都是tdd,联通则可能有tdd,还有可能是fdd,判断手机连接的是t ...

  7. HDU 1172 猜数字(DFS)

    猜数字 Time Limit:10000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status ...

  8. MySQL批量修改数据库的字符集

    #走过,试过的路 UPDATE information_schema.`SCHEMATA` SET DEFAULT_COLLATION_NAME='utf8_general_ci' WHERE DEF ...

  9. C&num;特性和反射

    C#特性和反射 .NET编译器的任务之一就是为所有定义和引用的类型生成元数据描述.除了程序集中标准的元数据外,.NET平台还支持特定(attribute)把更多的元数据嵌入到程序集中. .NET特性扩 ...

  10. thinkphp 的两种建构模式 第一种一个单入口里面定义两个模块,前台和后台,函数控制模块必须function&period;php前台加载前台模块的汉书配置文件,后台加载后台模块的汉书配置文件,公共文件共用。第二种架构模式两个单入口文件,分别生成两个应用定义define。。。函数可以定义配置文件。。。。

    thinkphp 的两种建构模式  第一种一个单入口里面定义两个模块,前台和后台,函数控制模块必须function.php前台加载前台模块的汉书配置文件,后台加载后台模块的汉书配置文件,公共文件共用. ...