学校实训作业:Java爬虫(WebMagic框架)的简单操作

项目名称:java爬虫

项目技术选型:Java、Maven、Mysql、WebMagic、Jsp、Servlet

项目实施方式:以认知java爬虫框架WebMagic开发为主,用所学java知识完成指定网站的数据爬取解析,并使用Servlet和Jsp展示到页面

实训环境:一人一机,边讲边练

实训简介:

本次实训的主要目的是增强学生对于WebMagic框架和Servlet的了解,并结合所学的理论知识进行爬虫实战。需要同学掌握包括目前市场上使用广泛的Mysql数据、Java语言、WebMagic框架和Servlet的开发,并了解大中型大数据行业的基本模式知识。

此次实训选择的案例有:

Mysql数据库基本操作

Java基本语法使用

WebMagic框架搭建并开发爬虫项目

通过学习这些内容可大大提升学生对计算机知识的理解,促进专业课程的学习,从而潜移默化的提升学生的就业竞争力。

步骤:

1、下载、安装好Maven,并在Eclipse中配置好Maven的相关设置。

1)、下载、安装Maven

下载地址:http://maven.apache.org/download.cgi,根据自己系统选择合适版本进行下载:

image

解压下载的文件到合适的位置即完成了Maven的安装:

image

2)、设置环境变量

复制Maven的安装路径下bin目录的路径,将其添加到电脑的环境变量中去:

复制bin目录所在的路径:

image

添加环境变量:

image

在cmd下输入:mvn --version  检查Maven是否安装成功,出现以下提示则安装成功:

image

3)、可忽略:修改Maven安装目录 conf下的settings.xml文件(E:\apache-maven-3.5.4\conf\settings.xml),来配置本地仓库的位置和将远程仓库镜像修改成阿里云镜像:

配置本地仓库,在下面加上自己所要创建的本地仓库的地址(根据自身情况设置):

image

Maven仓库默认在国外,使用难免很慢,尤其是下载依赖的时候,速度贼慢,换成国内阿里云镜像后会在速度上有很大的提升:

       <mirror>
      <id>aliyun</id> 
      <name>aliyun Maven</name> 
      <mirrorOf>*</mirrorOf> 
      <url>http://maven.aliyun.com/nexus/content/repositories/central</url> 
    </mirror>
image.png

4)、Eclipse的配置

以下步骤,在每个人的电脑上显示的内容可能会不一样(截图来自不同的项目,请忽略包名、类名等信息,部分截图来自网络,不同截图里的相关信息可能不同),但操作步骤是一样的,只要照着做就行了,在Eclipse上安装maven,打开Eclipse点击window>prferences之后会弹出:

image
image

点击确定之后会出现:

image

点击finish之后:

image

在Eclipse中配置Maven:

打开Eclipse的首选项设置

image

找到Maven的配置项目

image

设置Maven的全局配置文件settings.xml

image

更新配置信息

image

2、在Eclipse中创建Maven项目

1)、开启eclipse,右键new——》other,如下图找到maven project或者直接搜索maven projec:

创建项目:

image

2)、选择Maven Project,请选中Create a simple project(skip archetype selection),之后点击Next :

image

3)、填写Group id和Artifact id, Version默认,Packaging默认为jar,Name,Description选填,其他的可以都不填写:

image

之后点击Finish即可,此时需要等待一段时间下载所需要的文件,创建后的完整项目结构应如下图所示:

image

3、编写Java爬虫项目代码,抓取https://hr.tencent.com/position.php网站的相关信息:

1)、所需要抓取网页内容:职位名称、职位类别、人数、地点、发布时间

image

2)、根据所要抓取的内容(抓取内容包括:职位名称、职位类别、人数、地点、发布时间),可参照下面的SQL语句设计数据库(mysql):

/*
SQLyog Ultimate v12.5.0 (64 bit)
MySQL - 5.5.27 : Database - mysql_java
*********************************************************************
*/

/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`mysql_java` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `mysql_java`;

/*Table structure for table `tencent_position` */

DROP TABLE IF EXISTS `tencent_position`;

CREATE TABLE `tencent_position` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `p_name` varchar(200) NOT NULL,
  `p_link` varchar(200) NOT NULL,
  `p_type` varchar(100) NOT NULL,
  `p_num` varchar(20) NOT NULL,
  `p_location` varchar(20) NOT NULL,
  `p_publish_time` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1125 DEFAULT CHARSET=utf8;

3)、在创建的项目下,首先需要配置好pom.xml,然后分别创建四个类和一个接口(名字自己取):MySQLUtils、TencentPageProcessor、TencentPosition、TencentPositionDao(接口)、TencentPositionDaoImpl

image

配置pom.xml:

pom.xml文件的设置:填写好<dependency..../dependency>后的内容后,一定记得要按Ctrl+S/保存按钮,之后Eclipse会自动从设置好的Maven仓库中下载所需要的文件,可能需要一定的时间:

image

dependency数据来自:http://mvnrepository.com/  分别搜索:webmagic、mysql会显示相关内容

image

点击搜索得到的内容,复制框内的代码到pom.xml的<dependency..../dependency>代码块中:

image

可以在Maven Dependencies库中查看是否下载完成:

image

以下是示例代码,自己编码时,请记得一定要改动代码。

MySQLUtils类代码如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class MySQLUtils {
    
    private static Connection connection;
    
    public static Connection getConnection() throws ClassNotFoundException, SQLException {
        if (connection == null) {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mysql_java";//URL、User、Password需根据自己的实际情况填写
            String user = "root";
            String password = "root";
            return DriverManager.getConnection(url, user, password);
        }
        return connection;
    }
    
}

TencentPosition代码如下:

public class TencentPosition {

    private String positionName;
    private String positionLink;
    private String positionType;
    private String positionNum;
    private String workLocation;
    private String publishTime;

    public TencentPosition() {
        super();
    }

    public TencentPosition(String positionName, String positionLink, String positionType, String positionNum,
            String workLocation, String publishTime) {
        super();
        this.positionName = positionName;
        this.positionLink = positionLink;
        this.positionType = positionType;
        this.positionNum = positionNum;
        this.workLocation = workLocation;
        this.publishTime = publishTime;
    }

    public String getPositionName() {
        return positionName;
    }

    public void setPositionName(String positionName) {
        this.positionName = positionName;
    }

    public String getPositionLink() {
        return positionLink;
    }

    public void setPositionLink(String positionLink) {
        this.positionLink = positionLink;
    }

    public String getPositionType() {
        return positionType;
    }

    public void setPositionType(String positionType) {
        this.positionType = positionType;
    }

    public String getPositionNum() {
        return positionNum;
    }

    public void setPositionNum(String positionNum) {
        this.positionNum = positionNum;
    }

    public String getWorkLocation() {
        return workLocation;
    }

    public void setWorkLocation(String workLocation) {
        this.workLocation = workLocation;
    }

    public String getPublishTime() {
        return publishTime;
    }

    public void setPublishTime(String publishTime) {
        this.publishTime = publishTime;
    }

    @Override
    public String toString() {
        return "TencentPosition [positionName=" + positionName + ", positionLink=" + positionLink + ", positionType="
                + positionType + ", positionNum=" + positionNum + ", workLocation=" + workLocation + ", publishTime="
                + publishTime + "]";
    }

}

TencentPositionDao接口代码如下:

public interface TencentPositionDao {

    int add(TencentPosition position);

}

TencentPositionDaoImpl类代码如下:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TencentPositionDaoImpl implements TencentPositionDao {

    public int add(TencentPosition position) {
        String sql = "INSERT INTO tencent_position(p_name, p_link, p_type, p_num, p_location, p_publish_time)"
                + " VALUES(?, ?, ?, ?, ?, ?)";
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = MySQLUtils.getConnection();
            pst = conn.prepareStatement(sql);
            pst.setString(1, position.getPositionName());
            pst.setString(2, position.getPositionLink());
            pst.setString(3, position.getPositionType());
            pst.setString(4, position.getPositionNum());
            pst.setString(5, position.getWorkLocation());
            pst.setString(6, position.getPublishTime());
            return pst.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (pst != null) {
                try {
                    pst.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                } finally {
                    pst = null;
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                } finally {
                    conn = null;
                }
            }
        }
        return 0;
    }

}

TencentPageProcessor类代码如下:

import java.util.List;
import java.util.concurrent.atomic.AtomicLong;import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.pipeline.JsonFilePipeline;
import us.codecraft.webmagic.processor.PageProcessor;

public class TencentPageProcessor implements PageProcessor {

    private Site site = Site.me().setRetryTimes(5).setSleepTime(1000);

    private static TencentPositionDao dao = new TencentPositionDaoImpl();
    
    public static AtomicLong count = new AtomicLong();
    public static AtomicLong total = new AtomicLong();

    public Site getSite() {
        return site;
    }

    public void process(Page page) {
        List<String> urlList = page.getHtml().links().regex("https://hr.tencent.com/position.php\\?&start=\\d+").all();
        System.out.println(urlList);
        page.addTargetRequests(urlList);
        
        List<String> positionNames = page.getHtml().xpath("//tr[@class='odd']/td[1]/a/text()").all();
        List<String> positionLinks = page.getHtml().xpath("//tr[@class='odd']/td[1]/a/@href").all();
        List<String> positionTypes = page.getHtml().xpath("//tr[@class='odd']/td[2]/text()").all();
        List<String> positionNums = page.getHtml().xpath("//tr[@class='odd']/td[3]/text()").all();
        List<String> workLocations = page.getHtml().xpath("//tr[@class='odd']/td[4]/text()").all();
        List<String> publishTimes = page.getHtml().xpath("//tr[@class='odd']/td[5]/text()").all();
        for (int i = 0; i < positionNames.size(); i++) {
            TencentPosition position = new TencentPosition();
            position.setPositionName(positionNames.get(i));
            position.setPositionLink(positionLinks.get(i));
            position.setPositionType(positionTypes.get(i));
            position.setPositionNum(positionNums.get(i));
            position.setPublishTime(publishTimes.get(i));
            position.setWorkLocation(workLocations.get(i));
            dao.add(position);
        }
        
        //String positionName = page.getHtml().xpath("//tr[@class='odd']/td[1]/a/text()").get();
        //String positionType = page.getHtml().xpath("//tr[@class='odd']/td[2]/text()").get();
        //String positionLink = "https://hr.tencent.com/" + page.getHtml().xpath("//tr[@class='odd']/td[1]/a/@href").get();
        //String positionNum = page.getHtml().xpath("//tr[@class='odd']/td[3]/text()").get();
        //String workLocation = page.getHtml().xpath("//tr[@class='odd']/td[4]/text()").get();
        //String publishTime = page.getHtml().xpath("//tr[@class='odd']/td[5]/text()").get();
        //page.putField("positionName", positionName);
        //page.putField("positionLink", positionLink);
        //page.putField("positionType", positionType);
        //page.putField("positionNum", positionNum);
        //page.putField("workLocation", workLocation);
        //page.putField("publishTime", publishTime);
        //TencentPosition position = new TencentPosition();
        //position.setPositionName(positionName);
        //position.setPositionLink(positionLink);
        //position.setPositionType(positionType);
        //position.setPositionNum(positionNum);
        //position.setPublishTime(publishTime);
        //position.setWorkLocation(workLocation);
        //dao.add(position);
    }

    public static void main(String[] args) {
        Spider.create(new TencentPageProcessor())
            .addUrl("https://hr.tencent.com/position.php?&start=0")
            .addPipeline(new JsonFilePipeline("web_code"))
            .thread(100)
            .run();
    }

}

4、编码完成,点击运行、进行测试

当控制台显示如下内容时,则表示抓取成功:

image

此时可以查看自己的数据库看是否有数据,如果有数据,并且数据库中的数据和网页中需要抓取的数据一致,则表示Java爬虫项目已完成:

image

实验完成。

转载请保留或注明出处:https://www.jianshu.com/p/afa7071a4458

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351