Kettle获取html网页数据存储到mysql表

        最近在学Kettle,今天自己实践用Kettle获取html网页数据的时候,写java的时候遇到一下困难,整理一下。

目录

 一、版本信息

二、获取浏览器的User-Agent和Accept

1.进入豆瓣网,右键选择检查或者F12进入开发者工具

2.在“网络”中,任意点击一个元素,在“标头”中,下拉找到“Request Headers”

三、配置“自定义常量数据”控件

1.回到Kettle中,新建转换

2.在“核心对象”-“输入”中找到“自定义常量数据”控件

3.“元数据”对话框中,定义字段常量

4.“数据”对话框中,为字段常量赋值

四、配置“HTTP client”控件

1.在“核心对象”-“查询”中找到“HTTP client”控件

2.“General”对话框

3.“Fields”对话框

五、配置“Java代码”控件

1.在“核心对象”-“脚本”中找到“Java代码”控件

2.在“类与代码片段”中点击“Code Snippits”,“Common use”,“Main”插入main方法

3.将代码中的提示代码删除,替换为下方的代码

        4.下面是修改后的代码

5.在下方的“字段”对话框中,填写新的字段

6.在下方的“参数”对话框中,指定参数

7.运行转换

8.在mysql中查看结果

 一、版本信息

Kettle(Pentaho Data Integration)8.2
Mysql8.0
JDK1.8
数据库管理系统Navicat
浏览器Edge
目标网页豆瓣网

注意:mysql中的数据库和数据表需要提前创建

use kettle;
create table html(
contents VARCHAR(255));

二、获取浏览器的User-Agent和Accept

        学过爬虫的应该都知道想要爬取网页数据,单靠一个URL只能完成一些简单网站的爬取任务,由于网页的反爬机制,需要User-Agent和Accept将程序伪装成浏览器进行网页的访问,Kettle也是这样。(User-Agent取决于电脑系统、浏览器类别等等因素,所以每个人的User-Agent是不同的)

        以豆瓣网为例:

1.进入豆瓣网,右键选择检查或者F12进入开发者工具

2.在“网络”中,任意点击一个元素,在“标头”中,下拉找到“Request Headers”

将User-Agent和Accept的内容复制下来

三、配置“自定义常量数据”控件

1.回到Kettle中,新建转换
2.在“核心对象”-“输入”中找到“自定义常量数据”控件
3.“元数据”对话框中,定义字段常量

4.“数据”对话框中,为字段常量赋值
  • filename:      要抽取网页的URL
  • User-Agent: 浏览器中的User-Agent
  • Accept:        浏览器中的Accept

以豆瓣网为例:

  • filename:     https://movie.douban.com/chart
  • Accept:        image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
  • User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0

注意:在此处指定User-Agent和Accept之后可以直接使用,否则要在Java代码中定义

四、配置“HTTP client”控件

1.在“核心对象”-“查询”中找到“HTTP client”控件
2.“General”对话框
  • 勾选“从字段中获取URL”
  • “URL字段名”:                                            “filename”
  • “Encoding(empty means standard)”:   “UTF-8”
  • “结果字段名”:                                            “result”

3.“Fields”对话框

五、配置“Java代码”控件

1.在“核心对象”-“脚本”中找到“Java代码”控件
2.在“类与代码片段”中点击“Code Snippits”,“Common use”,“Main”插入main方法
3.将代码中的提示代码删除,替换为下方的代码

注意:

        代码中的变量“url”、“userName”、“userPwd”、Class.forName()的值这四个位置,需要替换成自己的

        这段代码可能只适合mysql8.0之前的版本,具体原因在代码下方,不想看原因的可以直接跳到第4小节

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
 
private String result;
private String contents;
private Connection connection = null;
 
 
public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException,SQLException{
  if (first) {    
	result=getParameter("result");
	first = false;
  }
 
  Object[] r = getRow();
 
  if (r == null) {
    setOutputDone();
    return false;
  }
  Object[] outputRow = createOutputRow(r, data.outputRowMeta.size());
  String foobar = get(Fields.In, result).getString(r); 
  String pattern ="<a[^>]*href(\\\"([^\\\"]*)\\\"|\\'([^\\']*)\\'|([^\\\\s>]*))[^>]*>(.*?)</a>";
  Pattern patterns = Pattern.compile(pattern);
  Matcher m = patterns.matcher(foobar);
  while(m.find()){
		get(Fields.Out, "contents").setValue(outputRow, m.group().replaceAll("<[^>]*>",""));
		String url = "jdbc:mysql://localhost:3306/kettle?useUnicode=true&
			characterEncoding=UTF-8&useSSL=false";

		String userName = "root";
		String userPwd = "147369";
			try{
				// 加载驱动程序
				Class.forName("com.mysql.cj.jdbc.Driver");
				// 获取连接对象
				connection= (Connection) DriverManager.getConnection(url, userName, userPwd);
				} catch (Exception e) {
					e.printStackTrace();
				}
				//要执行的SQL语句
				String sql="insert into html (contents) values (?);";
				PreparedStatement stat = (PreparedStatement) connection.prepareStatement(sql);
				contents=m.group().replaceAll("<[^>]*>","");
				stat.setString(1, contents);
				//3.ResultSet类,用来存放获取的结果集!!	
				stat.executeUpdate();
 
  			putRow(data.outputRowMeta, outputRow);
			}
  return true;
 
}

        这一段代码是书上的代码,鄙人跑这个代码会报错,报错日志如下

2024/03/24 14:31:05 - Java 代码.0 - ERROR (version 8.2.0.0-342, build 8.2.0.0-342 from 2018-11-14 10.30.55 by buildguy) : Error initializing UserDefinedJavaClass:
2024/03/24 14:31:05 - Java 代码.0 - ERROR (version 8.2.0.0-342, build 8.2.0.0-342 from 2018-11-14 10.30.55 by buildguy) : org.codehaus.commons.compiler.CompileException: Line 10, Column 8: Imported class "com.mysql.jdbc.Connection" could not be loaded
2024/03/24 14:31:05 - Java 代码.0 - ERROR (version 8.2.0.0-342, build 8.2.0.0-342 from 2018-11-14 10.30.55 by buildguy) : 错误初始化步骤[Java 代码]
2024/03/24 14:31:05 - 4-2-1 - ERROR (version 8.2.0.0-342, build 8.2.0.0-342 from 2018-11-14 10.30.55 by buildguy) : 步骤 [Java 代码.0] 初始化失败!
2024/03/24 14:31:05 - Spoon - ERROR (version 8.2.0.0-342, build 8.2.0.0-342 from 2018-11-14 10.30.55 by buildguy) : 4-2-1: preparing transformation execution failed
2024/03/24 14:31:05 - Spoon - ERROR (version 8.2.0.0-342, build 8.2.0.0-342 from 2018-11-14 10.30.55 by buildguy) : org.pentaho.di.core.exception.KettleException: 
2024/03/24 14:31:05 - Spoon - 无法初始化至少一个步骤.  执行无法开始!
2024/03/24 14:31:05 - Spoon - 
2024/03/24 14:31:05 - Spoon - 
2024/03/24 14:31:05 - Spoon -     at org.pentaho.di.trans.Trans.prepareExecution(Trans.java:1272)
2024/03/24 14:31:05 - Spoon -     at org.pentaho.di.ui.spoon.trans.TransGraph$30.run(TransGraph.java:4287)
2024/03/24 14:31:05 - Spoon -     at java.lang.Thread.run(Thread.java:750)
2024/03/24 14:31:05 - 4-2-1 - ERROR (version 8.2.0.0-342, build 8.2.0.0-342 from 2018-11-14 10.30.55 by buildguy) : 错误被检测到!
2024/03/24 14:31:05 - 4-2-1 - ERROR (version 8.2.0.0-342, build 8.2.0.0-342 from 2018-11-14 10.30.55 by buildguy) : 错误被检测到!

        反过来找原因,原因明显是第二行的

 Imported class "com.mysql.jdbc.Connection" could not be loaded

        仔细一想确实是这样,因为鄙人的mysq是8.0版本的,其中jdbc的大部分类已经换地方了 ,换到了“com.mysql.cj.jdbc”下边

        然后就去改代码,把之前导包的代码变成了

import com.mysql.cj.jdbc.Connection;
import com.mysql.cj.jdbc.PreparedStatement;

        还是报错,我就在想会不会是jar包的原因,随后把连接mysql 的驱动jar包放在java 的jar/lib路径下。

        结果还是找不到,就反过来看mysql 的驱动,在mysql的驱动jar包中确实没有com.mysql.cj.jdbc.Connection,随后看到一个和这个长的比较像的类

        叫做“ConnectWapper.class”,我用这个类试了一下还是报错,但是这次报错信息是找不到类里的方法,说明Kettle已经读取到这个驱动jar包了,鄙人把jar解压放到IDEA里边看源码

        误打误撞发现java.sql中就有Connect和PreparedStatement类,就把导包的代码改成从java.sql中导入了,结果居然运行成功了,这次是运气好才运行成功的,如果以后想要解决其他问题还是要多多学习,也希望有大佬可以指点一下具体是什么问题,谢谢。

        4.下面是修改后的代码
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Connection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

//声明输入的结果字段
private String result;
//声明输出的结果字段
private String contents;
//声明数据库连接
private Connection connection = null;
 
 
public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException,SQLException{
  if (first) {
	//获取传入的结果参数    
	result=getParameter("result");
	first = false;
  }
 
//获取一行记录,即抽取到的每行超链接数据
  Object[] r = getRow();
 
  if (r == null) {
    setOutputDone();
    return false;
  }
  Object[] outputRow = createOutputRow(r, data.outputRowMeta.size());
  String foobar = get(Fields.In, result).getString(r); 
  //编写抽取超链接<a><a>标签中数据的正则表达式规则
  String pattern ="<a[^>]*href(\\\"([^\\\"]*)\\\"|\\'([^\\']*)\\'|([^\\\\s>]*))[^>]*>(.*?)</a>";
  //将匹配规则进行编译,生成Pattern对象,Pattern对象表示编译后的正则表达式
  Pattern patterns = Pattern.compile(pattern);
  //将匹配规则与输入界面的foobar字段进行匹配,生成Matcher对象
  Matcher m = patterns.matcher(foobar);
  //查找与该匹配规则匹配的数据,并输出到数据库的html数据表中

  while(m.find()){
  //获取输出的字段,并进行赋值
		get(Fields.Out, "contents").setValue(outputRow, m.group().replaceAll("<[^>]*>",""));
		//配置数据库连接,用于保存抽取到的数据
		String url = "jdbc:mysql://localhost:3306/kettle?useUnicode=true&characterEncoding=UTF-8&useSSL=false";
		String userName = "root";
		String userPwd = "147369";
			try{
				// 加载驱动程序
				Class.forName("com.mysql.cj.jdbc.Driver");
				// 获取连接对象
				connection= (Connection) DriverManager.getConnection(url, userName, userPwd);
				} catch (Exception e) {
					e.printStackTrace();
				}
				//要执行的SQL语句
				String sql="insert into html (contents) values (?);";
				PreparedStatement stat = (PreparedStatement) connection.prepareStatement(sql);
				contents=m.group().replaceAll("<[^>]*>","");
				stat.setString(1, contents);
				//ResultSet类,用来存放获取的结果集!!	
				stat.executeUpdate();
 
  			putRow(data.outputRowMeta, outputRow);
			}
  return true;
 
}
5.在下方的“字段”对话框中,填写新的字段

6.在下方的“参数”对话框中,指定参数

7.运行转换

8.在mysql中查看结果

  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值