CaptchaCracker训练模型识别验证码

新的项目需要去一个网站上获取一些数据,做一个爬虫,网站上有验证码,以前的时候简单的验证码可以直接使用tesseract直接识别,但是这次的验证码长这个样子:
Captcha1
Captcha2
Captcha3
尝试了几次OCR的解决方案,发现不能成功,这里面有斜线干扰,数字是彩色的,且歪歪扭扭的。

所以计划使用tensorflow训练个模型,在尝试的过程中发现了一个参数都已经调好的python lib, CaptchaCracker

训练的时候,需要调整的参数不是很多,只需要给定验证码的图片宽度高度就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import glob
import CaptchaCracker as cc

# Training image data path
train_img_path_list = glob.glob("./image/*.png")

# Training image data size
img_width = 120
img_height = 50

# Creating an instance that creates a model
CM = cc.CreateModel(train_img_path_list, img_width, img_height)

# Performing model training
model = CM.train_model(epochs=100)

# Saving the weights learned by the model to a file
model.save_weights("./weights.h5")

利用脚本从网站上获取了1000多的验证码图片,批量命令后,利用excel记录标记的结果,这个过程比较辛苦,需要一点一点的标记所有的图片。
标记了1500张图,基本上样本就够了,因为这个验证码的范围是0-8,且只是4位数字。
开始运行训练代码后,我的电脑ntel(R) Core(TM) Ultra 5 (16核), 32G内存,跑了大概十来分钟,生成了一个.h5的模型文件。

下面的代码是使用模型识别新的验证码图片,同样也是需要设置一下验证码图片的高度宽度,数字长度,字符的识别范围。
应用模型后,就可以识别出来结果了。

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
import os

import CaptchaCracker as cc

# Target image data size
img_width = 120
img_height = 50
# Target image label length
max_length = 4
# Target image label component
characters = {'0', '1', '2', '3', '4', '5', '6', '7', '8'}

# Model weight file path
weights_path = "./weights.h5"
# Creating a model application instance
AM = cc.ApplyModel(weights_path, img_width, img_height, max_length, characters)


# Target image path
target_img_path = "../img_2.png"

# Predicted value
pred = AM.predict(target_img_path)
print(pred)

最后的识别效果还是非常棒的,基本能到95%以上的成功率。

在Ubuntu里启动docker mysql,导入来自阿里云的RDS数据库

项目需要低功耗运转,暂时没有太大的访问量,不太需要购买阿里云的RDS mysql,所以计划把数据移动到一个ECS里。

登录阿里云,从DMS页面的右上角的一排按钮中,找到导出,勾选所有表,然后导出一个sql文件。在本地打开,发现文字没有乱码,正常可用。

尝试在Ubuntu系统里安装mysql8,但是修改lower_case_table_names=1的时候,mysql无法启动,所以没有办法只能尝试用docker启动以后,后面发现docker启动真的很方便,即使是操作失误,也可以里面恢复,重新再试。

安装docker-ce

添加 Docker 的官方 GPG 密钥:

1
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

提示OK后, 增加官方安装源

1
2
3
4
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"

更新 apt 包索引,安装最新版本的 Docker Engine-Community

1
2
sudo apt update
sudo apt install docker-ce

拉取镜像

直接从一个镜像加速站点,拉取mysql的最新镜像。

1
2
3
4
5
docker pull dockerproxy.cn/mysql:latest

# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dockerproxy.cn/mysql latest be960704dfac 9 days ago 602MB

启动镜像

先创建几个目录,用于挂载,然后启动docker的mysql instance。

1
2
3
mkdir -p /mydata/mysql/log /mydata/mysql/data /mydata/mysql/conf

docker run --name mysql -v /mydata/mysql/log:/var/log/mysql -v /mydata/mysql/data:/var/lib/mysql -v /mydata/mysql/conf:/etc/mysql/conf.d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql --lower_case_table_names=1 --init-connect="SET collation_connection=utf8mb4_0900_ai_ci" --init-connect="SET NAMES utf8mb4"

创建用户

1
2
3
4
5
6
7
8
9
10
docker exec -it mysql /bin/bash

mysql -u root -p

# 密码 123456, 在docker的启动命令里。

CREATE USER 'a_new_user'@'%' IDENTIFIED BY 'password_need_to_change';
GRANT ALL PRIVILEGES ON *.* TO 'a_new_user'@'%';
flush privileges;

到这里,就可以远程连接这个数据库了。

不推荐在这里直接创建数据库,会有编码,困扰了我好几次。

导入数据库

用Navicat输入创建的用户名和密码(a_new_user / password_need_to_change),连接数据库。
创建一个新的数据库,编码保持默认,然后执行从阿里云导出的sql,编码也保持默认,这样数据就导入进去了。

在windows的git bash里使用rsync命令

rsync非常的好用,具体的用法可以参考阮一峰前辈写的教程

最近打算做的的一个小项目,打算继续用Python语言来实现后端,框架计划尝试用FastAPI,看起来性能与Flask比要高很多,甚至能比肩NodeJS和Go。

值得一试。

服务器打算放到阿里云的云小站的ECS里,ECS里配置好Nginx和ssl,用supervisor管理一下程序

1
2
3
4
5
6
7
8
# cat sfydoc_api.conf 
[program:sfydoc-api]
command=/bin/bash -c 'cd /home/tiaobug/sfydoc/backend && source .venv/bin/activate && uvicorn main:app --reload --port 888'
directory=/home/tiaobug/sfydoc/backend
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/tiaobug/sfydoc/backend/logs/sfydoc.log

uvicorn检查到代码文件有变动,就会自动重启,这样就只需要在本地改完代码,执行命令同步一下代码,从本地的开发环境同步到服务器端,服务器就自动重启,可以测试了。

代码多了以后,scp就不是很方便,所以在git-bash里装个rsync就是最好的选择,把git-bash集成到VSCode或者PyCharm里,一路很丝滑。

但是网上的教程,需要下载ztsd解压工具,然后下载msys2库里的rsync包,已经它的依赖包,过程比较麻烦,参考这里

现在把所有的准备工作都已经完成了,把重新压缩好的安装包,解压后,覆盖到git的安装目录下的usr目录(C:\Program Files\Git\usr)即可。

在pycharm或者vscode可以直接调用gitbash执行下面的脚本就可以自动同步文件到服务器上去了。

1
2
3
4
5
6
7
rsync -avz \
--exclude='__pycache__/' \
--exclude='.git/' \
--exclude='venv/' \
--exclude='*.log' \
--exclude='*.pyc' \
"$LOCAL_PROJECT_PATH" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH"

我在git version 2.45.2 windows.11 测试好用。

acme.sh自动化配置证书,永久免费SSL

acme.sh是一个开源的项目,实现了ACME协议, 可以从let’s encrypt生成免费的证书,配合一些cronjob可以实现自动化的部署证书。
现在的免费证书,需要3个月一刷新,即使是买的证书,一次性买多年,也要一年一更换,acme.sh很好的解决了这个问题。
尝试了一下,把博客移动到了阿里云的ECS里,这里有一个阿里云的云小站 , 99可以搞一个2C2G/40GSSD/3M带宽的ECS还是非常合适的。

安装 acme.sh

以下都以当前域名 tiaobug.com 和 www.tiaobug.com 为例。安装使用root或non-root用户都可以。

1
curl https://get.acme.sh | sh -s email=i@tiaobug.com # 改成自己的邮箱

脚本中间会访问github,如果访问有困难,可以参考用gitee的镜像。

1
2
3
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m i@tiaobug.com

安装后,会自动增加一个定时任务用于刷新证书。

1
2
# crontab -l
24 21 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

同时,安装过程不会新增和修改任何的系统功能和文件, 所有的修改都在安装目录 ~/.acme.sh/ 中,所以删除的时候也就很容易。

验证域名

acme.sh生成证书前,需要验证域名的所有权和服务的可用,它实现了acme协议支持的所有验证协议,支持http文件访问和dns text文本解析验证.

http文件访问验证

这里推荐http文件解析认证,预先nginx里配置一个80服务,让域名可以访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# vi /etc/nginx/sites-available/default

server {
listen 80;
listen [::]:80;

server_name tiaobug.com www.tiaobug.com ;

root /home/tiaobug/web-sites/tiaobug.com/;
index index.html;

location / {
try_files $uri $uri/ =404;
}
}

执行验证:

1
acme.sh --issue -d tiaobug.com -d www.tiaobug.com --webroot /home/tiaobug/web-sites/tiaobug.com/

执行完成后,会在webroot目录下生成多个文件

1
2
3
4
[Thu Oct 17 09:30:36 AM CST 2024] Your cert is in: /root/.acme.sh/tiaobug.com_ecc/tiaobug.com.cer
[Thu Oct 17 09:30:36 AM CST 2024] Your cert key is in: /root/.acme.sh/tiaobug.com_ecc/tiaobug.com.key
[Thu Oct 17 09:30:36 AM CST 2024] The intermediate CA cert is in: /root/.acme.sh/tiaobug.com_ecc/ca.cer
[Thu Oct 17 09:30:36 AM CST 2024] And the full-chain cert is in: /root/.acme.sh/tiaobug.com_ecc/fullchain.cer

acme.sh会全自动的生成验证文件, 并放到网站的根目录, 然后自动完成验证,完成验证后会删除验证文件,不用担心文件会泄露。

参照文件,acme.sh还提供其他的几个封装好的测试工具,在nginx或apache有直接的验证工作,不过我没有测试过。

1
2
acme.sh --issue -d tiaobug.com -d www.tiaobug.com --apache
acme.sh --issue -d tiaobug.com -d www.tiaobug.com --nginx

如果你还没有运行任何web服务, 80端口是空闲的, 那么acme.sh还能假装自己是一个webserver, 临时侦听80端口, 完成验证。

1
acme.sh --issue  -d tiaobug.com -d www.tiaobug.com --standalone

DNS text解析验证

如果做完了上面的一步,这一步不需要,两种验证方式选一种就可以了,在aliyun ECS的条件下相对来说http验证更加简单一些。
DNS text解析验证的好处是, 你不需要任何服务器, 不需要任何公网IP, 只需要DNS的解析记录即可完成验证. 坏处是,如果不同时配置 Automatic DNS API,使用这种方式 acme.sh 将无法自动更新证书,每次都需要手动再次重新解析验证域名所有权。

1
acme.sh --issue --dns -d tiaobug.com -d www.tiaobug.com --yes-I-know-dns-manual-mode-enough-go-ahead-please

然后, acme.sh 会生成相应的解析记录显示出来, 你只需要在你的域名管理面板中添加这条 txt 记录即可.

等待解析完成之后, 重新生成证书:

1
acme.sh --renew -d tiaobug.com -d www.tiaobug.com --yes-I-know-dns-manual-mode-enough-go-ahead-please

注意第二次这里用的是 –renew

dns方式的真正强大之处在于可以使用域名解析商提供的api自动添加txt记录完成验证.

acme.sh目前支持 cloudflare, dnspod, cloudxns, godaddy 以及 ovh 等数十种解析商的自动集成.

以dnspod为例, 你需要先登录到dnspod账号, 生成你的api id和api key, 都是免费的. 然后:

1
2
3
export DP_Id="1234"
export DP_Key="sADDsdasdgdsf"
acme.sh --issue --dns dns_dp -d tiaobug.com -d www.tiaobug.com

证书就会自动生成了. 这里给出的api id和api key会被自动记录下来, 将来你在使用dnspod api的时候, 就不需要再次指定了, 直接生成就好了:

1
acme.sh --issue -d mydomain2.com --dns  dns_dp

更详细的 api 用法: https://github.com/Neilpang/acme.sh/blob/master/dnsapi/README.md

生成并安装证书

验证成功以后,我们就可以生成证书了:

1
2
3
4
5
# mkdir -p /home/tiaobug/ssl/tiaobug.com/
# acme.sh --install-cert -d tiaobug.com -d www.tiaobug.com \
--key-file /home/tiaobug/ssl/tiaobug.com/key.pem \
--fullchain-file /home/tiaobug/ssl/tiaobug.com/cert.pem \
--reloadcmd "service nginx force-reload"

这里用的是service nginx force-reload, 不是service nginx reload, reload并不会重新加载证书, 所以用的force-reload。
如果不指定路径–key-file和–fullchain-file,默认生成的证书都放在安装目录下: ~/.acme.sh/, 尽量不要直接使用此目录下的文件。

–install-cert命令可以携带很多参数, 来指定目标文件. 并且可以指定 reloadcmd, 当证书更新以后, reloadcmd会被自动调用,让服务器生效.
详细参数请参考: https://github.com/Neilpang/acme.sh#3-install-the-issued-cert-to-apachenginx-etc

查看已安装证书信息

1
acme.sh --info -d www.tiaobug.com

配置nginx,安装证书

在nginx的配置文件增加下面的一段,配置完成, 执行命令nginx -s reload重启nginx即可.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 443 ssl;
listen [::]:443 ssl;

server_name tiaobug.com www.tiaobug.com;

root /home/tiaobug/web-sites/tiaobug.com/;
index index.html;
ssl_certificate "/home/tiaobug/ssl/tiaobug.com/cert.pem";
ssl_certificate_key "/home/tiaobug/ssl/tiaobug.com/key.pem";

ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;

ssl_prefer_server_ciphers on;
location / {
try_files $uri $uri/ =404;
}
}

ssl_certificate和ssl_certificate_key一定要指向正确的证书文件,cert和key文件不要搞反了。

证书自动更新

目前证书在60天以后会自动更新,无需任何操作,cronjob会代劳,不过按照ACME的尿性,以后肯定还会再次改短,可能会缩短这个自动更新时间, 不过都是自动的, 不用关心.

acme.sh的本身的更新

目前由于acme协议和let’s encrypt CA都在频繁的更新, 因此acme.sh也经常更新以保持同步.

升级 acme.sh 到最新版:

1
acme.sh --upgrade

如果你不想手动升级, 可以开启自动升级:

1
acme.sh --upgrade --auto-upgrade

之后, acme.sh 就会自动保持更新了.

也可以随时关闭自动更新:

1
acme.sh --upgrade --auto-upgrade  0

树莓派配置桥接网络,热点接入ETH0网络,支持SADP扫描

功能目标

在手机端安装海康的客户端软件“易调试”,通过树莓派上释放的热点wifi接入,能直接访问树莓派上的eth0网络,并支持SADP协议扫描eth0网络里的海康设备。

预研

SADP

海康威视(Hikvision)SADP(Search Active Device Protocol)是一款用于搜索和管理海康威视网络摄像头和其他设备的软件工具。它可以帮助用户快速发现网络中的海康设备,并进行配置和管理。

主要功能:

  1. 设备搜索:自动扫描网络,找到所有连接的海康威视设备。
  2. 设备管理:查看设备的状态、IP地址、序列号等信息。
  3. 批量配置:可以对多个设备进行批量设置,包括修改IP地址、重置密码等。
  4. 固件升级:支持对设备进行固件更新。
  5. 用户友好的界面:提供直观的图形用户界面,方便用户操作。

技术方面上,SADP工作在二层网络上,基于UDP实现。所以即使是没有配置或者没有获取IP,甚至配置错误IP的手机,也是可以扫描发现子网内的设备的。

常见做法

大致参考这里 https://blog.csdn.net/maizaozao/article/details/138666005 就可以配置完成支持热点接入。
通过修改iptables规则使eth0作为NAT协议的出口,就可以完成手机加入热点,并可以访问eth0内的IP设备。

1
sudo iptables -t nat -A  POSTROUTING -o eth0 -j MASQUERADE

但是当前的方案无法解决SADP扫描出设备的问题,在树莓派的eth0用tcpdump抓包后发现,使用wireshark分析后发现,手机上的易调试软件向239.255.255.250:37020发送基于ONVIF协议的udp组播,海康的设备默认会监听239.255.255.250:37020,收到指令,会向发送组播的机器,返回设备信息,也会向239.255.255.250:37020发送设备信息的组播。
所以在当前的配置下,eth0里的网络是能收到来自手机的组播消息,但是设备回复的组播消息手机却收不到,原因是NAT转发没办法把组播消息回复给手机。
所以这个方案尝试了几次发现基本走不通,那就只能尝试用桥接解决这个问题。

详细步骤

OS相关

操作是在Raspberry Pi OS lite 12 (bookworm)

安装软件

准备工作

更改APT源

1
2
3
4
5
6
7
8
9
# sudo vi /etc/apt/sources.list

deb https://mirrors.tuna.tsinghua.edu.cn/debian bookworm main contrib non-free-firmware
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free-firmware
deb https://mirrors.tuna.tsinghua.edu.cn/debian bookworm-updates main contrib non-free-firmware

#sudo vi /etc/apt/sources.list.d/raspi.list

deb https://mirrors.tuna.tsinghua.edu.cn/raspberrypi bookworm main

安装hostapd,dnsmasq,bridge-utils

安装一个hostapd,并设置开机启动

1
2
3
sudo apt install hostapd
sudo apt-get install bridge-utils
sudo apt install dnsmasq

修改配置

File /etc/network/interfaces

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
source /etc/network/interfaces.d/*


auto eth0
iface eth0 inet manual


auto eth1
iface eth1 inet static
address 168.168.168.168
netmask 255.255.255.0

auto wlan0
iface wlan0 inet manual

auto br0
iface br0 inet static
address 172.28.28.28
netmask 255.255.255.0
gateway 172.28.28.1
#address 192.168.10.210
#netmask 255.255.255.0
#gateway 192.168.10.1
bridge_ports eth0 wlan0
bridge_stp off # Disable Spanning Tree Protocol
bridge_fd 0 # No forwarding delay

配置br0后,eth0和wlan0均不再需要配置IP,br0上的IP在eth0和wlan0连个接口都可以被直接访问。

File /etc/hostapd/hostapd.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
country_code=CN
interface=wlan0
bridge=br0
driver=nl80211
ssid=free-wifi
wpa_passphrase=free_pwd_333
wpa_key_mgmt=WPA-PSK
channel=8
auth_algs=1
wpa=2
ieee80211n=1
hw_mode=g
rsn_pairwise=CCMP TKIP
wpa_pairwise=TKIP CCMP
max_num_sta=20

这里的是最关键的配置,在调试过程中被ChatGPT误导了很多次,interface不应该是br0, 设置成br0会报错,应该指向释放热点的接口wlan0,同时在hostapd的官方文档中指出是可以指定桥接的,所以设置bridge=br0非常关键。hw_mode最好是设置成g, 如果设置成a,需要设备硬件支持。
正常到这一步,就可以在接入WiFi后,给手机配置一个静态IP就可以访问eth0的网络了。如果eth0里有DHCP,手机也会自动获取到,如果eth0网络里没有DHCP(大部分的海康设备网络里都是没有的),我们可以尝试给增加一个DHCP服务。

File /etc/dnsmasq.conf

1
2
3
4
5
#interface=wlan0 # Listening interface
interface=br0
#dhcp-range=192.168.10.100,192.168.10.200,255.255.255.0,24h
dhcp-range=172.28.28.100,172.28.28.200,255.255.255.0,24h
address=/abcd.com/172.28.28.28 # 这里是一个固定的域名配置,可以直接接入手机后访问

这里的interface一定要指向br0,可以理解为eth0和wlan0都已经被br0给替代了。这样当前的dnsmasq里就可以在两边的网络里同时提供DHCP服务。

启动

1
2
3
4
sudo systemctl enable dnsmasq
sudo systemctl enable hostapd
sudo systemctl start dnsmasq
sudo systemctl start hostapd

最好是系统直接reboot一下。

总结

到这里,应该正常的表现是,从手机连入wifi: free-wifi, 输入密码: free_pwd_333,手机能自动获取到172.28.28.x网段的IP,虽然不能访问网络,但是使用海康的SADP扫描软件就可以扫描到局域网内部的设备了。

后续工作

如果海康的实施人员使用手机接入后,如果需要再配置,那么就需要通过abcd.com域名访问预设的配置页面,输入真实的IP范围后,调用代码把上述的interfaces和dnsmasq.conf配置文件改动一下,直接重启一遍服务应该就可以了。

备注

如果功能出现问题,除了以上服务的日志外,可以考虑IP转发引起的问题。
编辑/etc/sysctl.conf,根据原有配置反向取消或者增加注释:net.ipv4.ip_forward=1,并sudo sysctl -p保存应用。

windows 11 激活

需要重装了个电脑,记录一个激活Windows 11的小方法

1
irm https://get.activated.win/ | iex

用powershell的管理员模式运行,在新弹出来的窗口选择 1, 等待一会就可以正常激活。

这种方法应该是远程调用了一个KMS激活的,看起来还挺好用。
如果不能访问网络,可以直接下载离线包

这里还有一个全是原版镜像的网站 https://next.itellyou.cn/ 刷系统必备。

近四个月的总结

5月出差安徽,认识前辈老王
6月准备啤酒节的工作,潇洒川藏之旅,值得好好记录一篇文章
7月成功保障啤酒节
8月继续保障,东北之行

活在当下

新年假期在连续两场的大雪后结束了,今天开始了新一周的正式的工作,今年特地为假期写了一个简略的手机笔记,以后需要把这个习惯好好保持下去,假期的每一天都记录下来。

假期中见到了许多人,聊到了许多事,每个场景的切换都一些唐突和无法适应,但是又合情合理。

老舅的话让我印象深刻,他说,人不能总是活在过去,过去的悔恨懊恼会让人抑郁,也不能总是活在未来,未来的彷徨未知让人焦虑,所以最好的选择是活在当下~

以前总是听到活在当下这句话,这次是真的有所理解了。


Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2024 Tiaobug All Rights Reserved.

本站总访问量    次