diff --git a/.gitignore b/.gitignore index 0faec54271be18d1fb894ced7819979bde4e1dff..f6f9a9d6e7aea91feddb8e14349e25e1a33ba8bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .idea/ venv/ -app/__pycache__/ \ No newline at end of file +__pycache__/ diff --git a/app/__init__.py b/app/__init__.py index 7cd47794c6a4a8fd3cf7acd216fbce00855dbaec..90f0df8441da80bb53dc71bbcb65e1e61ba0e337 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -5,7 +5,7 @@ from .config import BaseConfig # 导入配置文件 # Flask 限流器 from flask_limiter import Limiter -from flask_limiter.util import get_remote_address, get_ipaddr +# from flask_limiter.util import get_remote_address, get_ipaddr # 导入过滤器 from .filter_fun import datauri @@ -14,6 +14,7 @@ app = Flask(__name__) app.config.from_object(BaseConfig) # 启用配置 app.jinja_env.filters['datauri'] = datauri +app.secret_key = 'xiangpica' def get_real_ip(): diff --git a/app/antispider/__pycache__/__init__.cpython-36.pyc b/app/antispider/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index da34b17b33ba8fd71070fe71d86303e409a12573..0000000000000000000000000000000000000000 Binary files a/app/antispider/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/app/antispider/__pycache__/index.cpython-36.pyc b/app/antispider/__pycache__/index.cpython-36.pyc deleted file mode 100644 index a17f924b4aff2f8b8b8df998007a559a19bd40c8..0000000000000000000000000000000000000000 Binary files a/app/antispider/__pycache__/index.cpython-36.pyc and /dev/null differ diff --git a/app/apis/__pycache__/__init__.cpython-36.pyc b/app/apis/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 5b7314c6394a85083fba305acd1cd07d042672d6..0000000000000000000000000000000000000000 Binary files a/app/apis/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/app/apis/__pycache__/index.cpython-36.pyc b/app/apis/__pycache__/index.cpython-36.pyc deleted file mode 100644 index ca290a7521757691335d4d1a2dd6514bd3ff3ccb..0000000000000000000000000000000000000000 Binary files a/app/apis/__pycache__/index.cpython-36.pyc and /dev/null differ diff --git a/app/csdn/__pycache__/__init__.cpython-36.pyc b/app/csdn/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index a37ae4b333e336b9e3ad663f9b98a3b4588ae254..0000000000000000000000000000000000000000 Binary files a/app/csdn/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/app/csdn/__pycache__/index.cpython-36.pyc b/app/csdn/__pycache__/index.cpython-36.pyc deleted file mode 100644 index a61da33faf7faee670f012d2d053463152e14475..0000000000000000000000000000000000000000 Binary files a/app/csdn/__pycache__/index.cpython-36.pyc and /dev/null differ diff --git a/app/file/__pycache__/__init__.cpython-36.pyc b/app/file/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 1b87e16ed2b4dc7c0eb0029485c6bf7bd6a7d59a..0000000000000000000000000000000000000000 Binary files a/app/file/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/app/file/__pycache__/index.cpython-36.pyc b/app/file/__pycache__/index.cpython-36.pyc deleted file mode 100644 index 4cba6fa4b66ed8aff752507f2c071a5dfb73cbcb..0000000000000000000000000000000000000000 Binary files a/app/file/__pycache__/index.cpython-36.pyc and /dev/null differ diff --git a/app/hw/__pycache__/__init__.cpython-36.pyc b/app/hw/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 315a8854a4f2aa6d89badde2396dd1b8d669afa4..0000000000000000000000000000000000000000 Binary files a/app/hw/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/app/hw/__pycache__/index.cpython-36.pyc b/app/hw/__pycache__/index.cpython-36.pyc deleted file mode 100644 index e2e9c45399e4a6bcb1855cdcaa2364d6d6fbe770..0000000000000000000000000000000000000000 Binary files a/app/hw/__pycache__/index.cpython-36.pyc and /dev/null differ diff --git a/app/login_form.py b/app/login_form.py new file mode 100644 index 0000000000000000000000000000000000000000..a33c76371068a5a2c84042434bb0c5f40786d0ce --- /dev/null +++ b/app/login_form.py @@ -0,0 +1,10 @@ +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('登录') \ No newline at end of file diff --git a/app/login_model.py b/app/login_model.py new file mode 100644 index 0000000000000000000000000000000000000000..8ac1a117d03607c9030f6ec5ff6c36191f34fc4e --- /dev/null +++ b/app/login_model.py @@ -0,0 +1,25 @@ +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) diff --git a/app/routes.py b/app/routes.py index 334e8147b3cc72c8b642dae2aed55ec5eeee6eed..5599a369333f9a0d9b658f69d3fe54ddc1e8bcf1 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1,7 +1,31 @@ -from flask import render_template, make_response +from flask import render_template, make_response, request, redirect, url_for, flash from app import app import hashlib +""" +# 临时处理插入一下数据 +from sqlalchemy.orm import sessionmaker +from app import db +""" + +# 用户权限认证相关数据 +from app.login_form import UserForm +from app.login_model import User + +from flask_login import LoginManager,login_user,login_required,logout_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)) + + """ 首页相关路由配置 """ @@ -52,3 +76,43 @@ def timeline(): nav = dict() nav['time'] = 'active' return render_template('timeline.html', nav=nav) + + +@app.route("/login", methods=['GET', 'POST']) +def login(): + form = UserForm() + print(form.validate_on_submit()) + """ + # 创建session类型 + DBSession = sessionmaker(bind=db.engine) + + # 创建session对象 + session = DBSession() + # 创建新的user对象 + new_user = User() + new_user.username = 'xiangpica' + new_user.password = '123456' + session.add(new_user) + # 提交即保存到数据库 + session.commit() + # 关闭session + session.close() + """ + + 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) + +# 退出登录 +@app.route('/logout') +@login_required +def logout(): + logout_user() + return redirect(url_for('login')) \ No newline at end of file diff --git a/app/school/__pycache__/__init__.cpython-36.pyc b/app/school/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 895f1886c6a846bead00f8d982aedb283b0725dc..0000000000000000000000000000000000000000 Binary files a/app/school/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/app/school/__pycache__/index.cpython-36.pyc b/app/school/__pycache__/index.cpython-36.pyc deleted file mode 100644 index 5fa0a744b2c89ad73f09c8babfe62e75ee984f33..0000000000000000000000000000000000000000 Binary files a/app/school/__pycache__/index.cpython-36.pyc and /dev/null differ diff --git a/app/school/index.py b/app/school/index.py index 37431aa92cd488419810eb4035d9b29e77b45d14..8dbe9255ca5440a113d5324b9f80d3b5b2ed174f 100644 --- a/app/school/index.py +++ b/app/school/index.py @@ -10,6 +10,8 @@ from ..model import School # 导入上级模块 # 从 app 中导入 limiter 对象 from app import limiter +# 导入 flask_login 内部函数 +from flask_login import login_required s = Blueprint('school', __name__, url_prefix='/ss') @@ -82,6 +84,15 @@ def list_school(): pagination = pagination_object(page) return render_template('school/index.html', pagination=pagination) +# 登录后可以查阅 +@s.route('/login_list') +@login_required +def login_list_school(): + page = int(request.args.get("page", 1)) # 获取页码 + pagination = pagination_object(page) + return render_template('school/login_index.html', pagination=pagination) + + @s.route('ajax_list') def ajax_list(): diff --git a/app/slow/__pycache__/__init__.cpython-36.pyc b/app/slow/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 700167e1c28606a6cae85cb5eda46a2bb2326b28..0000000000000000000000000000000000000000 Binary files a/app/slow/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/app/slow/__pycache__/index.cpython-36.pyc b/app/slow/__pycache__/index.cpython-36.pyc deleted file mode 100644 index 46f7f8f6198049837db3f5b655ec57c725edd5a0..0000000000000000000000000000000000000000 Binary files a/app/slow/__pycache__/index.cpython-36.pyc and /dev/null differ diff --git a/app/templates/index.html b/app/templates/index.html index d33e1b3f46f6047e430d0001040d5bbb2244a919..212ac1f522a580acd47680a5c5e9646597469bde 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -105,9 +105,7 @@

慢速爬虫

-
最新更新 -
+

本案例通过控制请求响应速度,来实现慢速爬虫,编写采集程序,需要控制请求和响应时间。

@@ -147,7 +145,29 @@
- +
+
+
+

登录加载数据

+
最新更新 +
+
+
+

本案例需模拟登录,然后才可采集数据,实践中可分析登录之后系统在客户端存储的用户状态信息。

+

难度:⭐⭐

+

+ 案例: + 学校清单 +

+
+ +
+
@@ -285,7 +305,7 @@

diff --git a/app/templates/login.html b/app/templates/login.html new file mode 100644 index 0000000000000000000000000000000000000000..50b92188bd6deb214b8df16dac9f89b9e69197e7 --- /dev/null +++ b/app/templates/login.html @@ -0,0 +1,51 @@ +{% extends "base.html" %} +{% block style %} + + +{% endblock style %} +{% block script %} + + + +{% endblock script %} + +{% block content %} +
+ +
+
+

登录窗口

+
+ +
+ {{ form.username.label }} : + {{form.username(class="form-control",placeholder="请输入用户名",data_toggle="tooltip",title="测试账号:xiangpica") + }} + 用户名至少3个字符 +
+ +
+ {{ form.password.label }} : + {{ form.password(class="form-control",placeholder="请输入密码",data_toggle="tooltip",title="测试密码:123456") }}
+
+
+ {{ form.submit(class="btn btn-primary" ) }} +
+ {{ form.csrf_token }} +
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/app/templates/school/login_index.html b/app/templates/school/login_index.html new file mode 100644 index 0000000000000000000000000000000000000000..4efe462d434d9af8f2cbd25f88f0645163f95e99 --- /dev/null +++ b/app/templates/school/login_index.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} +{% block style %} + +{% endblock style %} +{% block content %} +
+ + {% for school in pagination.data_list %} +
+
+
+
+ + + +
+
+
{{school.name}}
+

+ {% for fea in school.feature.split(',') %} + {{fea}} + {% endfor %} +

+

所在省市:{{school.province}} -- {{school.city}}

+
+
+
+
+ {% endfor %} + 点击退出登录 +
+ +{% endblock %} diff --git a/app/user/__pycache__/__init__.cpython-36.pyc b/app/user/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 15ef23f4bb5a770995dbfa3bf2cbcbe479c4e6b4..0000000000000000000000000000000000000000 Binary files a/app/user/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/app/user/__pycache__/index.cpython-36.pyc b/app/user/__pycache__/index.cpython-36.pyc deleted file mode 100644 index 36084369660880076ba9e35ff10688b90a42b4a7..0000000000000000000000000000000000000000 Binary files a/app/user/__pycache__/index.cpython-36.pyc and /dev/null differ diff --git a/db-sqls/users.sql b/db-sqls/users.sql new file mode 100644 index 0000000000000000000000000000000000000000..6a232d6bfa027664137ff0579c41637179bbfce8 --- /dev/null +++ b/db-sqls/users.sql @@ -0,0 +1,36 @@ +/* + Navicat Premium Data Transfer + + Source Server : a + Source Server Type : MySQL + Source Server Version : 50553 + Source Host : localhost:3306 + Source Schema : playground + + Target Server Type : MySQL + Target Server Version : 50553 + File Encoding : 65001 + + Date: 11/01/2023 16:22:54 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for users +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `password_hash` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of users +-- ---------------------------- +INSERT INTO `users` VALUES (1, 'xiangpica', 'pbkdf2:sha256:260000$YXBcAzNRmppCHIpd$21e3e35e2aa85f9750fb33b3fc9a387afc6f38ade43366b35042487b2d93aa3b'); + +SET FOREIGN_KEY_CHECKS = 1;