栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

详解Java豆瓣电影爬虫——小爬虫成长记(附源码)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

详解Java豆瓣电影爬虫——小爬虫成长记(附源码)

以前也用过爬虫,比如使用nutch爬取指定种子,基于爬到的数据做搜索,还大致看过一些源码。当然,nutch对于爬虫考虑的是十分全面和细致的。每当看到屏幕上唰唰过去的爬取到的网页信息以及处理信息的时候,总感觉这很黑科技。正好这次借助梳理Spring MVC的机会,想自己弄个小爬虫,简单没关系,有些小bug也无所谓,我需要的只是一个能针对某个种子网站能爬取我想要的信息就可以了。有Exception就去解决,可能是一些API使用不当,也可能是遇到了http请求状态异常,又或是数据库读写有问题,就是在这个报exception和解决exception的过程中,JewelCrawler(儿子的小名)已经可以能够独立的爬取数据,并且还有一项基于Word2Vec算法做个情感分析的小技能。

后面可能还会有未知的Exception等着解决,也有一些性能需要优化,比如和数据库的交互,数据的读写等等。但是目测年内没有太多精力放这上面了,所以今天做一个简单的总结,而且前两篇主要侧重的是功能和结果,这篇来说说JewelCrawler是如何诞生的,并将代码放到Github上(源码地址在文章最后),有兴趣的可以关注下(仅供交流学习,请勿他用,考虑下douban君。多一点真诚,少一点伤害)

 环境介绍

开发工具:Intellij idea 14

数据库: Mysql 5.5 + 数据库管理工具Navicat(可用来连接查询数据库)

语言:Java

Jar包管理:Maven

版本管理:Git 

目录结构

其中

  com.ansj.vec是Word2Vec算法的Java版本实现

  com.jackie.crawler.doubanmovie是爬虫实现模块,其中又包括

有些包是空的,因为这些模块还没有用上,其中

  •     constants包是存放常量类
  •     crawl包存放爬虫入口程序
  •     entity包映射数据库表的实体类
  •     test包存放测试类
  •     utils包存放工具类

 resource模块存放的是配置文件和资源文件,比如

  •     beans.xml:Spring上下文的配置文件
  •     seed.properties:种子文件
  •     stopwords.dic:停用词库
  •     comment12031715.txt:爬取的短评数据
  •     tokenizerResult.txt:使用IKAnalyzer分词后的结果文件
  •     vector.mod:基于Word2Vec算法训练的模型数据

test模块是测试模块,用于编写UT.

 数据库配置

1. 添加依赖的包

JewelCrawler使用的maven管理,所以只需要在pom.xml中添加相应的依赖就可以了



  org.springframework

  spring-jdbc

  4.1.1.RELEASE





  commons-pool

  commons-pool

  1.6





  commons-dbcp

  commons-dbcp

  1.4





  mysql

  mysql-connector-java

  5.1.38





  mysql

  mysql-connector-java

  5.1.38

 

2. 声明数据源bean

我们需要在beans.xml中声明数据源的bean

 



  

  

  

  

 

注意: 这里是绑定了外部配置文件jdbc.properties,具体数据源的参数从该文件读取。

如果遇到问题“SQL [insert into user(id) values(?)]; Field 'name' doesn't  have a default value;”解决方法是设置表的相应字段为自增长字段。

解析页面遇到的问题

对于爬到的网页数据需要解析dom结构,拿到自己想要的数据,期间遇到如下错误

org.htmlparser.Node不识别

解决方法:添加jar包依赖



  org.htmlparser

  htmlparser

  1.6

 

org.apache.http.HttpEntity不识别

解决方法:添加jar包依赖



  org.apache.httpcomponents

  httpclient

  4.5.2

 

当然这是期间遇到的问题,最后用的是Jsoup做的页面解析。

 maven仓库下载速度慢

之前使用的是默认的maven中央仓库,下载jar包的速度很慢,不知道是我的网络问题还是其他原因,后来在网上找到了阿里云的maven仓库,更新后,相比之前简直是秒下,吐血推荐。



  

   alimaven

   aliyun maven

   http://maven.aliyun.com/nexus/content/groups/public/

   central    

  

 

找到maven的settings.xml文件,添加这个镜像即可。

读取resource模块下文件的一种方法

比如读取seed.properties文件

@Test

  public void testFile(){

    File seedFile = new File(this.getClass().getResource("/seed.properties").getPath());

    System.out.print("===========" + seedFile.length() + "===========" );

  }

有关正则表达式

使用regrex正则表达式的时候,如果匹配上了定义的Pattern,则需要先调用matcher的find方法然后才能使用group方法找到子串。直接调用group方法是没有办法找到你想要的结果的。

  我看了下上面Matcher类的源码 

package java.util.regex;

import java.util.Objects;

public final class Matcher implements MatchResult {

  

  Pattern parentPattern;

 

  

  int[] groups;

 

  

  int from, to;

 

  

  int lookbehindTo;

 

  

  CharSequence text;

 

  

  static final int ENDANCHOR = 1;

  static final int NOANCHOR = 0;

  int acceptMode = NOANCHOR;

 

  

  int first = -1, last = 0;

 

  

  int oldLast = -1;

 

  

  int lastAppendPosition = 0;

 

  

  int[] locals;

 

  

  boolean hitEnd;

 

  

  boolean requireEnd;

 

  

  boolean transparentBounds = false;

 

  

  boolean anchoringBounds = true;

 

  

  Matcher() {

  }

 



Matcher(Pattern parent, CharSequence text) {

  this.parentPattern = parent;

  this.text = text;

 

  // Allocate state storage

  int parentGroupCount = Math.max(parent.capturingGroupCount, 10);

  groups = new int[parentGroupCount * 2];

  locals = new int[parent.localCount];

 

  // Put fields into initial states

  reset();

}

....



public String group() {

  return group(0);

}



public String group(int group) {

  if (first < 0)

    throw new IllegalStateException("No match found");

  if (group < 0 || group > groupCount())

    throw new IndexOutOfBoundsException("No group " + group);

  if ((groups[group*2] == -1) || (groups[group*2+1] == -1))

    return null;

  return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();

}



public boolean find() {

  int nextSearchIndex = last;

  if (nextSearchIndex == first)

    nextSearchIndex++;

 

  // If next search starts before region, start it at region

  if (nextSearchIndex < from)

    nextSearchIndex = from;

 

  // If next search starts beyond region then it fails

  if (nextSearchIndex > to) {

    for (int i = 0; i < groups.length; i++)

      groups[i] = -1;

    return false;

  }

  return search(nextSearchIndex);

}

 



boolean search(int from) {

  this.hitEnd = false;

  this.requireEnd = false;

  from    = from < 0 ? 0 : from;

  this.first = from;

  this.oldLast = oldLast < 0 ? from : oldLast;

  for (int i = 0; i < groups.length; i++)

    groups[i] = -1;

  acceptMode = NOANCHOR;

  boolean result = parentPattern.root.match(this, from, text);

  if (!result)

    this.first = -1;

  this.oldLast = this.last;

  return result;

}

...

} 

原因是这样的:这里如果不先调用find方法,直接调用group,可以发现group方法调用group(int group),该方法的方法体中有if first<0,显然这里这个条件是成立的,因为first的初始值就是-1,所以这里会抛异常。但是如果调用find方法,可以发现,最终会调用search(nextSearchIndex),注意这里的nextSearchIndex已被last赋值,而last的值为0,再跳转到search方法中

boolean search(int from) {

  this.hitEnd = false;

  this.requireEnd = false;

  from    = from < 0 ? 0 : from;

  this.first = from;

  this.oldLast = oldLast < 0 ? from : oldLast;

  for (int i = 0; i < groups.length; i++)

    groups[i] = -1;

  acceptMode = NOANCHOR;

  boolean result = parentPattern.root.match(this, from, text);

  if (!result)

    this.first = -1;

  this.oldLast = this.last;

  return result;

} 

这个nextSearchIndex传给了from,而from在方法体中被赋值给了first,所以,调用了find方法之后,这个的first就不在是-1,也就不是抛异常了。

源码已经上传至百度网盘:http://pan.baidu.com/s/1dFwtvNz

以上说的问题比较碎,都是在遇到问题和解决问题的时候的一些总结。在具体操作的时候还会遇到其他问题,有问题或者建议的话欢迎提出来^^。

最后放几张截止目前爬取的数据

Record表

其中存储的是79032条,爬取过的网页有48471条

movie表

目前爬取了2964部影视作品

comments表

爬取了29711条记录

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/148452.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号