环境说明

Linux环境:deepin 15.5 (debian / x64) tomcattomcat8 IDEA:jetbrain IntelliJ IDEA Ultimate(支持java web环境)

tomcat 安装配置

安装tomcat8

1
2
sudo apt-get update
sudo apt-get install tomcat8

设置tomcat文件权限

  • Tomcat home directory : /usr/share/tomcat8
  • Tomcat base directory : /var/lib/tomcat8
1
2
cd /usr/share/tomcat8 && sudo chmod -R 755 *
cd /var/lib/tomcat8 && sudo chmod -R 755 *

启用与关闭tomcat

1
2
sudo service tomcat8 start  #开启tomcat8服务,会占用8080端口
sudo service tomcat8 stop #关闭tomcat8服务

文件环境

run/debug 参数

项目结构

文件结构

JcaptchaServlet源码:后端生成验证图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Random;

public class JcaptchaServlet extends HttpServlet {
private Random random = new Random();
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

int height = 220; //图片高
int width = 220; //图片宽
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) image.getGraphics();
String picPath= JcaptchaServlet.class.getClassLoader().getResource("../image/"+(random.nextInt(4)+1)+".jpg").getPath(); //读取本地图片,做背景图片
g.drawImage(ImageIO.read(new File(picPath)), 0, 20, width, height, null); //将背景图片从高度20开始
g.setColor(Color.white); //设置颜色
g.drawRect(0, 0, width-1, height-1); //画边框

g.setFont(new Font("宋体",Font.BOLD,20)); //设置字体
Integer x=null,y=null; //用于记录坐标
String target=null; // 用于记录文字
for(int i=0;i<4;i++){ //随机产生4个文字,坐标,颜色都不同
g.setColor(new Color(random.nextInt(50)+200, random.nextInt(150)+100, random.nextInt(50)+200));
String str=getRandomChineseChar();
int a=random.nextInt(width-100) + 50;
int b=random.nextInt(height-70) + 55;
if(x==null){
x=a; //记录第一个x坐标
}
if(y==null){
y=b;//记录第一个y坐标
}
if(target==null){
target=str; //记录第一个文字
}
g.drawString(str, a, b);
}
g.setColor(Color.white);
g.drawString("点击"+target, 0,20);//写入验证码第一行文字 “点击..”
request.getSession().setAttribute("gap",x+":"+y);//将坐标放入session
//5.释放资源
g.dispose();
//6.利用ImageIO进行输出
ImageIO.write(image, "jpg", response.getOutputStream()); //将图片输出

}
//网上找的,随机产生汉字的方法
private String getRandomChineseChar()
{
String str = null;
int hs, ls;
Random random = new Random();
hs = (176 + Math.abs(random.nextInt(39)));
ls = (161 + Math.abs(random.nextInt(93)));
byte[] b = new byte[2];
b[0] = (new Integer(hs).byteValue());
b[1] = (new Integer(ls).byteValue());
try
{
str = new String(b, "GBk"); //转成中文
}
catch (UnsupportedEncodingException ex)
{
ex.printStackTrace();
}
return str;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

Login源码:用于登陆正确与否确认

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
* Servlet implementation class Login
*/
@WebServlet("/Login")
public class Login extends HttpServlet {
private static final long serialVersionUID = 1L;


protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html;charset=utf-8"); //设置编码
//获取前端传来的坐标

String xs=request.getParameter("x");
String ys=request.getParameter("y");
HttpSession session = request.getSession();

String str = (String) session.getAttribute("gap");//获取session中的gap
if(str==null){
response.getWriter().write("验证码超时");
return;
}
String[] split2 = str.split(":");
int x= Integer.parseInt(xs);
int y=Integer.parseInt(ys);
int x1= Integer.parseInt(split2[0]);
int y1=Integer.parseInt(split2[1]);
if(x1-2<x && x<x1+22 && y1-22<y && y<y1+2){ //若前端上传的坐标在session中记录的坐标的一定范围内则验证成功
response.getWriter().write("验证成功");
}else{
response.getWriter().write("验证失败");
}
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}

}

web.xml:servlet配置参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>CheckCode</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<servlet>
<servlet-name>captcha</servlet-name>
<servlet-class>JcaptchaServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>Login</servlet-name>
<servlet-class>Login</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Login</servlet-name>
<url-pattern>*.shtml</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>captcha</servlet-name>
<url-pattern>/captcha.svl</url-pattern>
</servlet-mapping>
</web-app>

index.jsp:前端界面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<html lang = "zh-CN">
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="{pageContext.request.contextPath}/js/jquery.min.js"> </span>(function(){
<span class="katex math inline">("#image").click(function(event){ var obj=this; var x=event.offsetX;//获取点击时鼠标相对图片坐标 var y=event.offsetY; </span>.ajax({
url:"login.shtml", //ajax提交
type:"post",
data:{'x':x,"y":y},
success:function(data){

alert(data)
obj.src=obj.src+"?date="+new Date();
}
})
});
})
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;img id="image" src="${pageContext.request.contextPath}/captcha.svl" style="cursor: pointer;" &gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<ul>
<li>注意:需要另行配置依赖(位置见结构图)<br />
jar包:<code>javax.servlet-api-4.0.0.jar</code><br />
jQuery包:<code>jquery.min.js</code><code>v1.11.3</code></li>
</ul>
</div>

<div class="section section-blog-info">
<div class="row">
<div class="col-md-6">
<div class="entry-categories">分类: <span class="label label-primary"><a href="http://liuchang.men/category/uncategorized/">未分类</a></span> </div>
</div>

<div class="col-md-6">
<div class="entry-social">
<a target="_blank" rel="tooltip"
data-original-title="分享到 Facebook"
class="btn btn-just-icon btn-round btn-facebook"
href="https://www.facebook.com/sharer.php?u=http://liuchang.men/2018/05/12/linux%e4%b8%8b%e7%94%a8idea%e8%b0%83%e8%af%95java-web%ef%bc%9a%e7%82%b9%e5%87%bb%e5%9b%be%e7%89%87%e6%96%87%e5%ad%97%e9%aa%8c%e8%af%81%e7%a0%81/">
<i class="fa fa-facebook"></i>
</a>

<a target="_blank" rel="tooltip"
data-original-title="分享至微博"
class="btn btn-just-icon btn-round btn-twitter"
href="http://twitter.com/share?url=http://liuchang.men/2018/05/12/linux%e4%b8%8b%e7%94%a8idea%e8%b0%83%e8%af%95java-web%ef%bc%9a%e7%82%b9%e5%87%bb%e5%9b%be%e7%89%87%e6%96%87%e5%ad%97%e9%aa%8c%e8%af%81%e7%a0%81/&#038;text=linux%E4%B8%8B%E7%94%A8idea%E8%B0%83%E8%AF%95java%20web%EF%BC%9A%E7%82%B9%E5%87%BB%E5%9B%BE%E7%89%87%E6%96%87%E5%AD%97%E9%AA%8C%E8%AF%81%E7%A0%81">
<i class="fa fa-twitter"></i>
</a>

<a rel="tooltip"
data-original-title=" Share on Email"
class="btn btn-just-icon btn-round"
href="mailto:?subject=linux下用idea调试java%20web:点击图片文字验证码&#038;body=http://liuchang.men/2018/05/12/linux%e4%b8%8b%e7%94%a8idea%e8%b0%83%e8%af%95java-web%ef%bc%9a%e7%82%b9%e5%87%bb%e5%9b%be%e7%89%87%e6%96%87%e5%ad%97%e9%aa%8c%e8%af%81%e7%a0%81/">
<i class="fa fa-envelope"></i>
</a>
</div>
</div> </div>
<hr>

<div id="comments" class="section section-comments">
<div class="row">
<div class="col-md-12">
<div class="media-area">
<h3 class="hestia-title text-center">
</h3>
</div>
<div class="media-body">
<div id="respond" class="comment-respond">
<h3 class="hestia-title text-center">发表评论 <small><a rel="nofollow" id="cancel-comment-reply-link" href="/2018/05/12/linux%e4%b8%8b%e7%94%a8idea%e8%b0%83%e8%af%95java-web%ef%bc%9a%e7%82%b9%e5%87%bb%e5%9b%be%e7%89%87%e6%96%87%e5%ad%97%e9%aa%8c%e8%af%81%e7%a0%81/#respond" style="display:none;">取消回复</a></small></h3> <span class="pull-left author"> <div class="avatar"><img alt='' src='http://1.gravatar.com/avatar/783dfac778f4f63a2889a4d32384232c?s=64&#038;d=mm&#038;r=g' srcset='http://1.gravatar.com/avatar/783dfac778f4f63a2889a4d32384232c?s=128&#038;d=mm&#038;r=g 2x' class='avatar avatar-64 photo' height='64' width='64' /></div> </span> <form action="http://liuchang.men/wp-comments-post.php" method="post" id="commentform" class="form media-body">
<p class="logged-in-as"><a href="http://liuchang.men/wp-admin/profile.php" aria-label="已登入为admin。编辑您的个人资料。">已登入为admin</a><a href="http://liuchang.men/wp-login.php?action=logout&amp;redirect_to=http%3A%2F%2Fliuchang.men%2F2018%2F05%2F12%2Flinux%25e4%25b8%258b%25e7%2594%25a8idea%25e8%25b0%2583%25e8%25af%2595java-web%25ef%25bc%259a%25e7%2582%25b9%25e5%2587%25bb%25e5%259b%25be%25e7%2589%2587%25e6%2596%2587%25e5%25ad%2597%25e9%25aa%258c%25e8%25af%2581%25e7%25a0%2581%2F&amp;_wpnonce=92457eb6ae">登出?</a></p><div class="form-group label-floating is-empty"> <label class="control-label">在想些什么?</label><textarea id="comment" name="comment" class="form-control" rows="6" aria-required="true"></textarea><span class="hestia-input"></span> </div><p class="form-submit"><input name="submit" type="submit" id="submit" class="btn btn-primary pull-right" value="发表评论" /> <input type='hidden' name='comment_post_ID' value='625' id='comment_post_ID' />
<input type='hidden' name='comment_parent' id='comment_parent' value='0' />
</p><input type="hidden" id="_wp_unfiltered_html_comment_disabled" name="_wp_unfiltered_html_comment_disabled" value="7d727c2e29" /><script>(function(){if(window===window.parent){document.getElementById('_wp_unfiltered_html_comment_disabled').name='_wp_unfiltered_html_comment';}})();


首先,此次项目正好需要对某云服务商的帮助文档进行全文抓取,涉及到对图片进行转存,需要重新搭建一个图片服务器方便管理,也避免数据丢失,经过多方案尝试,最终选择如下的方法,话不多说,开始行动。

环境说明

  • 系统 Ubuntu 18.04
  • 已开放 21号端口(ftp),80号端口(http)

安装Nginx

安装所需依赖库

1
2
3
4
5
sudo apt-get update
sudo apt-get install build-essential # 安装gcc g++依赖库
sudo apt-get install libpcre3 libpcre3-dev # 安装prce依赖库
sudo apt-get install zlib1g-dev # 安装 zlib依赖库
sudo apt-get install openssl # 安装 ssl依赖库

编译Nginx

先下载Nginx对应的最新版本(linux) 我当前的最新版本是:1.13.

1
2
3
4
5
6
tar -zxvf nginx-*   #解压下载下来的压缩包
cd nginx-* #进入解压目录
./configure --prefix=/usr/local/nginx #配置并生成makefile,自行配置安装位置
sudo make #编译
make install #安装
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf #启动Nginx

此时Nginx就安装完成了,会使用默认的80端口启动,如果有启动,启动完成可直接通过服务器ip或者云解析的域名查看默认网页。

默认网页如图所示:

安装与配置vsftpd

1
2
sudo apt-get install vsftpd #安装vsftpd
sudo service vsftpd start #启动vsftpd服务

下面方法目的在于单独为ftp建立一个用户,并建立images文件夹存储图片

1
2
3
4
5
sudo mkdir /home/ftpuser    #新建ftpuser目录作为ftp主目录
sudo useradd -d /home/ftpuser -s /bin/bash ftpuser #新建ftpuser用户指定用户主目录
passwd ftpuser #设置用户密码
chown ftpuser /home/ftpuser #制定用户组
chmod 777 -R /home/ftpuser #为ftpuser下所有文件开放访问权限

新建文件/etc/vsftpd.user_list,用于存放允许访问ftp的用户

1
sudo nano /etc/vsftpd.user_list

文本中添加ftpuser用户名

编辑vsftpd配置文件

1
sudo nano /etc/vsftpd.conf

作如下修改

  1. 去除注释 write_enable=YES
  2. 末尾添加 userlist_file=/etc/vsftpd.user_list
  3. 末尾添加 userlist_enable=YES
  4. 末尾添加 userlist_deny=NO

保存,退出

重启vsftpd服务

1
sudo service vsftpd restart

filezilla或其他ftp软件,并使用刚刚新建的用户名密码访问测试是否成功。

创建存储图片的根目录

1
2
3
4
sudo su 
cd /home/ftpuser
mkdir -p www/images #这里使用www/images为例
mkdir /usr/local/nginx/html/images #在nginx目录下创建images目录
1
sudo nano /usr/local/nginx/conf/nginx.conf    #在默认的server里再添加一个location并指定实际路径

插入内容为:

1
2
3
4
location /images/ {
root /home/ftpuser/www/;
autoindex on;
}

停用与重新载入nginx

1
2
/usr/local/nginx/sbin/nginx -s stop
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

最后测试

简介

BeautifulSoup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。 BeautifulSoup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。 BeautifulSoup已成为和lxmlhtml6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度。

CSS 选择器

通过标签名查找

1
2
print(soup.select('title'))
print(soup.select('a'))

通过类名查找

1
print(soup.select('.sister'))

通过id查找

1
print(soup.select('#link1'))

组合查找

1
2
print(soup.select('p #link1'))      #查找p标签中内容为id属性为link1的标签
print(soup.select("head > title")) #直接查找子标签(绝对路径)

属性查找

查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。

1
2
print(soup.select('a[class="sister"]'))
print(soup.select('a[href="http://example.com/elsie"]'))

MySQL安装

首先在命令行中输入三个命令:

1
2
3
sudo apt-get install mysql-server
sudo apt install mysql-client
sudo apt install libmysqlclient-dev

接下来确认系统是否已经安装上Mysql: 输入命令:mysql --help 出现如下一大串help,即为成功: 可以通过如下命令进入MySQL服务: mysql -uroot -p 会让你输入密码,在安装的时候有时候会出现让你设置密码,有些是默认登录。

现在设置mysql允许远程访问,首先编辑文件 /etc/mysql/mysql.conf.d/mysqld.cnf:

1
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

注释掉bind-address = 127.0.0.1sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

保存退出,然后进入mysql服务,执行授权命令:

1
2
Grant all on *.* to 'root'@'%' identified by 'root用户的密码' with grant option;
flush privileges;

然后执行quit命令退出mysql服务,执行如下命令重启mysql:

1
service mysql restart

补充:在进入MySQL时,输入mysql -uroot -p命令时,会出现 > ERROR 1045 (28000): Access denied for user ‘root’@’localhost’这种情况。于是在网上查了许多技术网站,发现一篇不错的,据此解决。链接: https://blog.csdn.net/learner_lps/article/details/62887343

0%