反爬案例:不登录不给,要数据请先登录我的站点
登录之后,可以查看数据,是部分站点常用规则,本篇博客将在爬虫训练场中实现该需求。
安装必备模块
实现 Python Flask 项目的登录,最需要的模块是 flask-login
,除此之外,还需要用到以下三个模块:
flask-wtf
:该模块用于在 Flask 应用程序中处理 Web 表单的功能。wtf
:用于跟踪和报告程序崩溃的功能;werkzeug
:Web 服务器和 Web 应用程序的功能,包括 HTTP 处理和 WSGI 支持。
模块全部安装完毕,首先要做的准备工作是在 MySQL 数据库中建立 users
表,结构相对简单,仅包含 2 个字段即可。
建立 models
数据库表建立完毕,可以在 app
目录下创建 login_model.py
文件,并输入模型代码。
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from app import db
class User(UserMixin, db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True)
password_hash = db.Column(db.String(128))
@property
def password(self):
# 设置密码的属性为只写
raise AttributeError('密码不能读取')
@password.setter
def password(self, password):
# 当类初始化时自动调用,把 password 的值转换为 hash 值
self.password_hash = generate_password_hash(password)
def verify_password(self, password) -> bool:
# 登录时验证密码
return check_password_hash(self.password_hash, password)
这里用到的几个核心函数说明如下:
flask_login 中 UserMixin 类说明
UserMixin 类可以被用户类继承。 这个类包含了一些必要的属性和方法,以便于 Flask-Login 来管理登录状态,如 is_authenticated
, is_active
, is_anonymous
以及 get_id
。用户需要实现的只需要继承 UserMixin,然后实现它的函数 get_id()
即可。
werkzeug.security 中的两个函数 generate_password_hash(), check_password_hash()
Werkzeug.security 模块提供了两个主要的函数,用于生成和验证密码哈希:
generate_password_hash(password, method='sha256', salt_length=8)
:这个函数用于生成密码哈希。参数 password 是需要加密的明文密码, method 参数用于指定使用的哈希算法, 默认为'sha256'
,salt_length 为指定盐的长度;check_password_hash(hashed_password, password)
:这个函数用于检查给定的明文密码和哈希值是否匹配。参数 hashed_password 是上面generate_password_hash()
函数生成的哈希值,password
是需要校验的密码。
建立 login_form 表单文件
在 app
目录建立 login_form.py
,然后输入如下代码。
from flask_wtf import FlaskForm
from wtforms.validators import DataRequired, Length
from wtforms import StringField, SubmitField, PasswordField
# 定义的表单都需要继承自FlaskForm
class UserForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired(), Length(3, 15)])
password = PasswordField('密码', validators=[DataRequired(), Length(5, 15)])
submit = SubmitField('登录')
由于 flask_wtf
模块用于处理表单,所以我们自定义一个表单。
上述代码涉及的知识点如下所示。
flask_wtf 中 FlaskForm 类
Flask-WTF 是 Flask 框架中的一个扩展库,主要用于构建和处理 HTML 表单。在 Flask-WTF 中,FlaskForm 类是一个非常重要的类,它是所有表单类的基类。
FlaskForm 类提供了一些基础的功能,包括验证,渲染,和 CSRF 保护等功能。通常,我们会定义一个继承于 FlaskForm 的自定义表单类来处理特定的表单。
例如上述代码,我们集成 FlaskForm 创建了一个表单对象,用于处理用户的登录信息,并且通过在类中使用 Flask-WTF 内置的字段类和验证器来验证用户的输入。
除此之外,还可以在模板中可以使用 {{form.csrf_token}}
生成隐藏的 csrf_token
。
建立登录视图函数
打开 routes.py
文件,在其中添加登录视图函数,首先将 UserForm()
实例化的对象传递到模板中,后续可以在 login.html
中直接进行渲染。
@app.route("/login", methods=['GET', 'POST'])
def login():
form = UserForm()
if form.validate_on_submit():
# 查询用户信息
user = User.query.filter_by(username=form.username.data).first()
if user is not None:
if user.verify_password(form.password.data):
flash('登录成功')
login_user(user) # login_user 的参数为要登录的用户
return redirect(request.args.get('next') or url_for('school.login_list_school'))
flash('登录失败')
return render_template('login.html', form=form)
既然已经开始修改 routes.py
文件,那再这里需要首先实例化 LoginManager
类 ,该类用于管理用户登录状态。
然后使用 init_app()
函数将 LoginManager
类对象绑定到指定 Flask 应用上。
from flask_login import LoginManager,login_user
# use login manager to manage session
login_manager = LoginManager(app)
login_manager.login_view = 'login' # 设置登录页面
# 回调函数,用来加载用户
@login_manager.user_loader #
def load_user(id):
'''用于加载用户'''
return User.query.get(int(id))
除此之外,还需要增加 load_user()
函数,该函数用于加载用户,关于 Flask-Login 的详细用法,可以参考下述博客。
Python flask 框架使用 flask-login 模块,来学习一下吧
配置 login.html 页面
打开 login.html
文件,输入如下代码,完成最后收尾工作。
{% extends "base.html" %} {% block style %}
<style type="text/css">
.required:after {
content: "*";
color: red;
}
</style>
{% endblock style %} {% block script %}
<script
type="text/javascript"
src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.6.0.min.js"
></script>
<script type="text/javascript">
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
});
</script>
{% endblock script %} {% block content %}
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 mt-5 mb-5 p-5 border border-success shadow-lg ">
<h1 class="text-primary">登录窗口</h1>
<form action="{{ url_for('login') }}" method="POST" class="mt-4">
<div class="form-group">
<span class="required"> {{ form.username.label }} </span>:
{{form.username(class="form-control",placeholder="请输入用户名",data_toggle="tooltip",title="测试账号:xiangpica")
}}
<small id="username_help" class="form-text text-muted"
>用户名至少3个字符</small
>
</div>
<div class="form-group">
<span class="required"> {{ form.password.label }} </span> : {{
form.password(class="form-control",placeholder="请输入密码",data_toggle="tooltip",title="测试密码:123456")
}} <br />
</div>
<div class="form-group">
{{ form.submit(class="btn btn-primary" ) }}
</div>
{{ form.csrf_token }}
</form>
</div>
</div>
</div>
{% endblock %}
运行代码,得到如下登录窗口。
本案例到此结束,已更新到 爬虫训练场 欢迎大家访问学习。
项目同步到代码仓库 https://gitcode.net/hihell/spider_playground
📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 828 篇原创博客
- 点赞
- 收藏
- 关注作者
评论(0)