提交 c738b98b 编写于 作者: 梦想橡皮擦's avatar 梦想橡皮擦 💬

反爬案例,手机转换为图片

上级 2b14716c
......@@ -34,6 +34,11 @@
2. [【小知识点】Python Flask 部署,生成环境的爬虫训练场项目](https://blog.csdn.net/hihell/article/details/128422613)
3. [【小知识点】给PythonWeb项目添加百度统计,爬虫训练场](https://blog.csdn.net/hihell/article/details/128448271)
4. [【小知识点】为爬虫训练场项目添加 Bootstrap5 时间轴](https://dream.blog.csdn.net/article/details/128543088)
5. [【小知识点】Python Flask 中使用 cryptography 模块实现加密](https://blog.csdn.net/hihell/article/details/128569293?spm=1001.2014.3001.5501)
6. [【小知识点】Python 随机生成一个汉字,提供了多种办法,目的竞然是用于创建头像](https://blog.csdn.net/hihell/article/details/128582632?spm=1001.2014.3001.5501)
7. [【小知识点】免费头像API,用 Python Flask 动态生成一个汉字头像](https://blog.csdn.net/hihell/article/details/128583823?spm=1001.2014.3001.5501)
8. [【小知识点】Python随机生成 Phone 号码,测试用~](https://blog.csdn.net/hihell/article/details/128594941?spm=1001.2014.3001.5501)
9. [【小知识点】Centos 自动任务,定时执行 Python 脚本](https://blog.csdn.net/hihell/article/details/128600920?spm=1001.2014.3001.5501)
## 站点数据储备博客
......
......@@ -7,9 +7,13 @@ from .config import BaseConfig # 导入配置文件
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address, get_ipaddr
# 导入过滤器
from .filter_fun import datauri
app = Flask(__name__)
app.config.from_object(BaseConfig) # 启用配置
app.jinja_env.filters['datauri'] = datauri
def get_real_ip():
......
from flask import Blueprint, send_file, jsonify
from flask import Blueprint, send_file, jsonify, request
from PIL import Image, ImageDraw, ImageFont
import random
......@@ -8,15 +8,13 @@ import io
api = Blueprint('apis', __name__, url_prefix='/api')
app_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@api.route('/avatars')
def index():
app_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
static_path = os.path.join(app_root, 'static')
static_path = os.path.join(app_root, 'static')
# 生成随机汉字
def get_random_common_char():
# 生成随机汉字
def get_random_common_char():
# 读取文件中的常用汉字
with open(os.path.join(static_path, 'demo.txt'), 'r', encoding='utf-8') as f:
......@@ -33,10 +31,32 @@ def index():
return random.choice(s)
# 生成电话号码
def generate_phone_number():
# 随机生成手机号码的前缀
prefix = random.choice(['130', '131', '132', '133', '134', '135', '136', '137', '138', '139',
'150', '151', '152', '153', '155', '156', '157', '158', '159',
'180', '181', '182', '183', '184', '185', '186', '187', '188', '189'])
# 随机生成手机号码的后缀
suffix = ''.join(random.choice(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) for _ in range(8))
# 将前缀和后缀组合起来,生成手机号码
return prefix + suffix
@api.route('/avatars')
def index():
name = request.args.get("name", '空值')
han_char = '' # 待生成的字符串
if name == '空值':
# 可以生成任意内容
han_char1 = get_random_common_char()
han_char2 = get_random_common_char()
han_char = han_char1 + han_char2
else:
han_char = name[:2]
# 生成图片
image = Image.new('RGB', (64, 64), (255, 255, 255))
draw = ImageDraw.Draw(image)
......@@ -67,16 +87,6 @@ def index():
@api.route('/phone')
def phone():
def generate_phone_number():
# 随机生成手机号码的前缀
prefix = random.choice(['130', '131', '132', '133', '134', '135', '136', '137', '138', '139',
'150', '151', '152', '153', '155', '156', '157', '158', '159',
'180', '181', '182', '183', '184', '185', '186', '187', '188', '189'])
# 随机生成手机号码的后缀
suffix = ''.join(random.choice(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) for _ in range(8))
# 将前缀和后缀组合起来,生成手机号码
return prefix + suffix
phone_number = generate_phone_number()
phone = {
'phone': phone_number
......
from jinja2 import Template
def datauri(uri):
return f'data:image/png;base64,{uri}'
\ No newline at end of file
......@@ -4,6 +4,7 @@
<head>
{% include 'common/header.html'%}
{% block link %}{% endblock link %}
{% block style %}{% endblock style %}
{% block script %}{% endblock script %}
{% include 'common/tj.html'%}
</head>
......
......@@ -7,6 +7,7 @@ padding:3px;}
</style>
<div class="container">
<table class="table table-hover table-bordered table-striped table-responsive">
......
......@@ -24,7 +24,8 @@
</p>
</div>
<div class="card-footer text-end">
<a href="https://blog.csdn.net/hihell/article/details/128420246" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://blog.csdn.net/hihell/article/details/128420246" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
......@@ -45,7 +46,8 @@
</p>
</div>
<div class="card-footer text-end">
<a href="https://blog.csdn.net/hihell/article/details/128429345" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://blog.csdn.net/hihell/article/details/128429345" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
</div>
......@@ -67,7 +69,8 @@
</p>
</div>
<div class="card-footer text-end">
<a href="https://blog.csdn.net/hihell/article/details/128465888" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://blog.csdn.net/hihell/article/details/128465888" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
</div>
......@@ -89,7 +92,8 @@
</p>
</div>
<div class="card-footer text-end">
<a href="https://blog.csdn.net/hihell/article/details/128474866" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://blog.csdn.net/hihell/article/details/128474866" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
</div>
......@@ -114,7 +118,8 @@
</p>
</div>
<div class="card-footer text-end">
<a href="https://blog.csdn.net/hihell/article/details/128474887" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://blog.csdn.net/hihell/article/details/128474887" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
</div>
......@@ -136,7 +141,8 @@
</p>
</div>
<div class="card-footer text-end">
<a href="https://blog.csdn.net/hihell/article/details/128474916" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://blog.csdn.net/hihell/article/details/128474916" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
</div>
......@@ -165,7 +171,8 @@
</div>
<div class="card-footer text-end">
<a href="https://blog.csdn.net/hihell/article/details/128473575" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://blog.csdn.net/hihell/article/details/128473575" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
......@@ -175,9 +182,6 @@
<div class="card border-danger rounded-5 shadow-sm" style="min-height:306px;min-width:300px;">
<div class="card-header text-center">
<h4 class="card-title">定值 Cookie 反爬</h4>
<div class="bg-danger text-white rounded p-1"
style="transform: rotate(20deg); position:absolute;right:0;top:0.5rem;">最新更新
</div>
</div>
<div class="card-body">
<p class="card-text">本案例要求爬虫程序在采集时,必须在请求头中携带固定 Cookie 值,如果缺少无法访问。</p>
......@@ -199,9 +203,7 @@
<div class="card border-info rounded-5 shadow-sm" style="min-height:306px;min-width:300px;">
<div class="card-header text-center">
<h4 class="card-title">简易响应加密</h4>
<div class="bg-danger text-white rounded p-1"
style="transform: rotate(20deg); position:absolute;right:0;top:0.5rem;">最新更新
</div>
</div>
<div class="card-body">
<p class="card-text">本案例请求数据接口之后,会返回加密值,在前台需要对加密串进行解密,然后在渲染数据。</p>
......@@ -212,7 +214,8 @@
</p>
</div>
<div class="card-footer text-end">
<a href="https://dream.blog.csdn.net/article/details/128474924" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://dream.blog.csdn.net/article/details/128474924" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
</div>
......@@ -234,11 +237,14 @@
</p>
</div>
<div class="card-footer text-end">
<a href="https://dream.blog.csdn.net/article/details/128474930" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://dream.blog.csdn.net/article/details/128474930" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
</div>
</div>
</div>
<div class="row align-items-stretch">
<div class="col mt-2">
<div class="card border-info rounded-5 shadow-sm" style="min-height:306px;min-width:300px;">
<div class="card-header text-center">
......@@ -256,7 +262,31 @@
</p>
</div>
<div class="card-footer text-end">
<a href="https://dream.blog.csdn.net/article/details/128474930" target="_blank" class="card-link text-muted small">案例制作教程</a>
<a href="https://dream.blog.csdn.net/article/details/128474930" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
</div>
</div>
<div class="col mt-2">
<div class="card border-info rounded-5 shadow-sm" style="min-height:306px;min-width:300px;">
<div class="card-header text-center">
<h4 class="card-title">手机号码图片展示</h4>
<div class="bg-danger text-white rounded p-1"
style="transform: rotate(20deg); position:absolute;right:0;top:0.5rem;">最新更新
</div>
</div>
<div class="card-body">
<p class="card-text">本案例将重要信息手机号码以图片形式展示,爬虫程序无法通过简单提取获取手机号码</p>
<p class="card-text text-left">难度:⭐⭐</p>
<p class="card-text">
案例:
<a href="/u/i" class="card-link text-success">名片</a>
</p>
</div>
<div class="card-footer text-end">
<a href="https://dream.blog.csdn.net/article/details/128474930" target="_blank"
class="card-link text-muted small">案例制作教程</a>
<a href="#" class="btn btn-success btn-sm card-link disabled" alt="暂未开放">学习博客</a>
</div>
</div>
......
......@@ -16,6 +16,47 @@
<span class="timeline-label">
<span class="label bg-success text-white p-1">正在更新中</span>
</span>
<div class="timeline-item">
<div class="timeline-point timeline-point-success">
<i class="fa fa-times"></i>
</div>
<div class="timeline-event">
<div class="timeline-heading">
<h4>爬虫训练场 V0.18.0 发布</h4>
</div>
<div class="timeline-body">
<p>上线手机号码转图片案例,已上线案例 12 个,同时更新2款API接口,分别如下</p>
<ul>
<li><a href="/api/phone" target="_blank">随机手机号码</a></li>
<li><a href="/api/avatars" target="_blank">随机仿钉钉文字头像</a></li>
</ul>
</div>
<div class="timeline-footer">
<p class="text-right">2023年01月10日</p>
</div>
</div>
</div>
<div class="timeline-item">
<div class="timeline-point timeline-point-success">
<i class="fa fa-times"></i>
</div>
<div class="timeline-event">
<div class="timeline-heading">
<h4>爬虫训练场 V0.17.0 发布</h4>
</div>
<div class="timeline-body">
<p>上线华为云社区月更榜单</p>
</div>
<div class="timeline-footer">
<p class="text-right">2023年01月09日</p>
</div>
</div>
</div>
<div class="timeline-item">
<div class="timeline-point timeline-point-success">
<i class="fa fa-times"></i>
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img src="{{url_for('apis.index')}}" alt="">
</body>
</html>
\ No newline at end of file
{% extends "base.html" %}
{% block style %}
<style type="text/css">
.card {
border-radius: 10px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
background-color: white;
}
.avatar {
}
</style>
{% endblock style %}
{% block content %}
<div class="container text-center">
<div class="row mt-3">
{% for item in user_data %}
<div class="col mt-2">
<div class="card" style="width: 18rem;">
<div class="card-body">
<p>
<img src="{{url_for('apis.index')}}?name={{item.name}}" class="avatar avatar-sm" alt="image">
</p>
<h5 class="card-title">
{{item.name}}</h5>
<p class="card-text">联系方式:<img src="{{ item.phone|datauri }}" alt="phone"/></p>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
\ No newline at end of file
{% extends "base.html" %}
{% block style %}
<style type="text/css">
.card {
border-radius: 10px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
background-color: white;
}
.avatar {
}
</style>
{% endblock style %}
{% block content %}
<div class="container text-center">
<div class="row mt-3">
{% for item in user_data %}
<div class="col mt-2">
<div class="card" style="width: 18rem;">
<div class="card-body">
<p>
<img src="{{url_for('apis.index')}}?name={{item.name}}" class="avatar avatar-sm" alt="image">
</p>
<h5 class="card-title">
{{item.name}}</h5>
<p class="card-text">联系方式:<img src="data:image/png;base64,{{ item.phone }}" alt="phone" /></p>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
\ No newline at end of file
from flask import Blueprint, jsonify, request
from flask import render_template
from ..apis.index import get_random_common_char, generate_phone_number,static_path
from PIL import Image, ImageDraw, ImageFont
import os
import io
import base64
u = Blueprint('user', __name__, url_prefix='/u')
# 手机号码转换为图片
def phone_to_img(phone):
# 生成图片
image = Image.new('RGB', (110, 20), (255, 255, 255))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(os.path.join(static_path, 'font/msyh.ttf'), 16)
draw.text((0, 0), phone, font=font, fill=(0, 0, 0))
buf = io.BytesIO()
image.save(buf, format='png')
buf.seek(0)
b64_image = base64.b64encode(buf.getvalue()).decode('utf-8')
# 转为 base64 编码
return b64_image
@u.route('/i')
def index():
return render_template('user/index.html')
# 随机生成用户姓名
ret = list()
for i in range(0, 20):
name = "".join([get_random_common_char() for i in range(5)])
ret.append({
"name": name,
"phone": phone_to_img(generate_phone_number())
})
return render_template('user/index.html', user_data=ret)
from app import app
# app.jinja_env.auto_reload = True
app.jinja_env.auto_reload = True
app.config['TEMPLATES_AUTO_RELOAD'] = True
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册