22. 听说你想要用爬虫采集我的手机号?哎 ~ 我展示用的是图片
本篇博客我们实现图片渲染手机号码案例,用于防止爬虫直接采集文字信息。
爬虫训练场
本案例实现的效果如下所示
@[toc]
bootstrap5 实现名片样式卡片
在 Bootstrap5 中实现一个名片样式,可以直接使用卡片模板,示例代码如下。
<div class="card" style="width: 18rem;">
<img src="image.jpg" class="card-img-top" alt="image" />
<div class="card-body">
<h5 class="card-title">梦想橡皮擦</h5>
<p class="card-text">爬虫训练场项目主导人</p>
<a href="#" class="btn btn-primary">点击去他的博客</a>
</div>
</div>
该例子使用了 .card
类来创建名片卡片,但我们还需要进行一下修改,将图片修改为圆形,可以使用 Bootstrap 的 .avatar
类。
<div class="card" style="width: 18rem;">
<img src="image.jpg" class="avatar avatar-sm" alt="image" />
<div class="card-body">
<h5 class="card-title">梦想橡皮擦</h5>
<p class="card-text">爬虫训练场项目主导人</p>
<a href="#" class="btn btn-primary">点击去他的博客</a>
</div>
</div>
这里使用了 .avatar
类和 .avatar-sm
类来创建头像。.avatar
类用于创建圆形图像,而 .avatar-sm
类用于调整头像的大小。
还需要手动添加一些样式,圆角,阴影和背景色。
.card {
border-radius: 10px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
background-color: white;
}
简单的调整样式之后,就可以编写核心代码环节了,重点是 user/index.py
文件的修改,该文件承接所有页面数据逻辑。
补充数据生成逻辑
本部分代码由三部分组成,分别是:
- 生成用户 5 个汉字的昵称;
- 用昵称调用头像生成 API,生成头像
- 调用随机手机号接口,生成手机号,并将其转换为图片。
步骤罗列完毕,下面开始逐一实现。
生成用户 5 个汉字的昵称
在过往的博客中,我们已经实现了随机汉字的生成,参考文章为 《Python 随机生成一个汉字》,在这篇文章中,重点函数为 get_random_common_char()
,接下来将其进行封装,并在 user/index.py
中进行导入。
from ..apis.index import get_random_common_char, generate_phone_number,static_path
特别提醒:爬虫训练场项目为综合项目,前后有很强的承接性,大家在阅读学习的时候,尽量中间不要有停顿。
可以看到在模块导入时,我们将 apis.index
模块中的 get_random_common_char()
, generate_phone_number()
函数 和 static_path
变量都进行了导入,然后调用对应函数即可完成目标需求。
例如,生成 5 个汉字昵称:
name = "".join([get_random_common_char() for i in range(5)])
调用头像 API,生成图片
本步骤相对简单,仅修改 免费头像 API 博客对应的接口逻辑即可。
在视图函数中补充接口参数解析逻辑,如果传递 name
参数,则获取前 2 个汉字,示例代码如下:
name = request.args.get("name", '空值')
han_char = '' # 待生成的字符串
if name == '空值':
# 执行默认逻辑
else:
# 截取前2个汉字
最后只需要在模板页面,调用该接口传入参数即可。
<img
src="{{url_for('apis.index')}}?name={{item.name}}"
class="avatar avatar-sm"
alt="image"
/>
将手机号码生成图片
该步骤是本案例的核心逻辑,为了防止爬虫采集数据,需要将文字内容转换成图片形式展现。文字转图片依旧使用 pillow
库。
这里首先封装一个基本函数,在 user/index.py
中编写代码即可。
# 手机号码转换为图片
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
可以看到,上述代码实例化了一个长 110 像素,宽 20 像素的白色背景区域,然后在其上部绘制手机号码,特别需要注意的地方是我们需要将图片转换为 BLOB
,即二进制图片格式。
buf = io.BytesIO()
image.save(buf, format='png')
buf.seek(0)
但是 _io.BytesIO
对象是无法在模板引擎中进行图像渲染的,还需要将其转换为 base64 编码。
所有的代码编写完毕,我们就可以在模板中,使用 data:
URL 格式来显示图像,示例代码如下:
<img src="data:image/png;base64, {{ item.phone }}" />
完整案例可以下载源码之后,查看 templates/user/index.html 文件内容。
此外,这里还可以使用 jinja2 自定义过滤器实现,首先在项目 app
目录中建立 filter_fun.py
文件,用于放置所有过滤器代码,然后编写 datauri()
函数,内容如下。
def datauri(uri):
return f'data:image/png;base64,{uri}'
最后一个步骤就是在 flask
中注册该过滤器,打开 app/__init__.py
文件,输入如下代码。
# 导入过滤器
from .filter_fun import datauri
app.jinja_env.filters['datauri'] = datauri
回到模板文件中,手机号码图片的加载就可以使用过滤器展示。
<img src="{{ item.phone|datauri }}" alt="phone" />
本案例到此结束,已更新到 爬虫训练场 欢迎大家访问学习。
项目同步到代码仓库 https://gitcode.net/hihell/spider_playground
📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 826 篇原创博客
- 点赞
- 收藏
- 关注作者
评论(0)