Python for Web Scraping in Flask, Jinja 2, SQLite
Flask (a lightweight web framework), Jinja2 for templates, and SQLite as the database for storing blog posts.
Here's a step-by-step guide:
Step 1: Set Up Your Project
Create a project folder and install the required dependencies.
mkdir python_web_scraping_blog
cd python_web_scraping_blog
python3 -m venv venv
source venv/bin/activate # for Linux/macOS
# For Windows:
# venv\Scripts\activate
pip install flask flask_sqlalchemy
Step 2: Project Structure
Create the following folder structure:
python_web_scraping_blog/
├── app.py # Main Flask app file
├── templates/
│ ├── base.html # Base template
│ ├── index.html # Homepage
│ └── post.html # Individual blog post
├── static/
│ ├── css/
│ │ └── style.css # Stylesheet
└── models.py # Database models
Step 3: Set Up Flask App (app.py
)
from flask import Flask, render_template
from models import db, BlogPost
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
@app.route('/')
def index():
posts = BlogPost.query.all() # Fetch all posts from the database
return render_template('index.html', posts=posts)
@app.route('/post/<int:post_id>')
def post(post_id):
post = BlogPost.query.get_or_404(post_id) # Fetch individual post
return render_template('post.html', post=post)
if __name__ == '__main__':
app.run(debug=True)
Step 4: Create Database Models (models.py
)
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class BlogPost(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=db.func.now())
def __repr__(self):
return f"<BlogPost {self.title}>"
Step 5: Initialize Database
Before running the app, initialize the database:
from app import app
from models import db
with app.app_context():
db.create_all()
This creates a blog.db
SQLite file with a BlogPost
table.
Step 6: Create HTML Templates
base.html
(Shared Layout)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python Web Scraping Blog</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<header>
<h1>Python Web Scraping Blog</h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>© 2025 Python Web Scraping Blog</p>
</footer>
</body>
</html>
index.html
(Homepage Listing All Posts)
{% extends 'base.html' %}
{% block content %}
<h2>Latest Posts</h2>
<ul>
{% for post in posts %}
<li><a href="/post/{{ post.id }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
{% endblock %}
post.html
(Individual Post)
{% extends 'base.html' %}
{% block content %}
<article>
<h2>{{ post.title }}</h2>
<p><strong>Published on:</strong> {{ post.created_at }}</p>
<div>
{{ post.content | safe }}
</div>
</article>
{% endblock %}
Sponsor Key-Word
"This Content Sponsored by Buymote Shopping app
BuyMote E-Shopping Application is One of the Online Shopping App
Now Available on Play Store & App Store (Buymote E-Shopping)
Click Below Link and Install Application: https://buymote.shop/links/0f5993744a9213079a6b53e8
Sponsor Content: #buymote #buymoteeshopping #buymoteonline #buymoteshopping #buymoteapplication"
Step 7: Add Some Example Blog Posts to Database
You can manually add posts to the database using the Flask shell or by creating a script to insert data.
Example of adding blog posts using Python:
from app import app
from models import db, BlogPost
with app.app_context():
post1 = BlogPost(title="Introduction to Web Scraping", content="Web scraping is...")
post2 = BlogPost(title="Libraries for Python Web Scraping", content="The best libraries for web scraping are...")
db.session.add(post1)
db.session.add(post2)
db.session.commit()
Step 8: Add Styles (style.css
)
Create the CSS file in static/css/style.css
.
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
}
header {
background-color: #333;
color: white;
padding: 10px;
}
header h1 {
margin: 0;
font-size: 2em;
}
nav ul {
list-style: none;
padding: 0;
}
nav ul li {
display: inline;
margin-right: 15px;
}
nav ul li a {
color: white;
text-decoration: none;
}
main {
padding: 20px;
}
footer {
background-color: #333;
color: white;
text-align: center;
padding: 10px;
position: fixed;
bottom: 0;
width: 100%;
}
Step 9: Run the Application
Now that everything is set up, you can run your Flask app.
python app.py
This will start the web server at http://127.0.0.1:5000/
. You can view your blog homepage, read individual posts, and add new content.
Step 10: Expand the Blog with Topics
To organize the blog by topics such as Python for Web Scraping, you can add a category
field to the BlogPost
model.
Update models.py
:
class BlogPost(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
category = db.Column(db.String(50), nullable=False) # Added category
created_at = db.Column(db.DateTime, default=db.func.now())
def __repr__(self):
return f"<BlogPost {self.title}>"
Update the index.html
to filter by category or display them as tags:
<h2>Blog Topics</h2>
<ul>
<li><a href="/category/python-web-scraping">Python for Web Scraping</a></li>
<li><a href="/category/beautifulsoup">BeautifulSoup</a></li>
<li><a href="/category/scrapy">Scrapy</a></li>
</ul>
You can also create a route to filter posts by category:
@app.route('/category/<category_name>')
def category(category_name):
posts = BlogPost.query.filter_by(category=category_name).all()
return render_template('index.html', posts=posts)
Sponsor Key-Word
"This Content Sponsored by Buymote Shopping app
BuyMote E-Shopping Application is One of the Online Shopping App
Now Available on Play Store & App Store (Buymote E-Shopping)
Click Below Link and Install Application: https://buymote.shop/links/0f5993744a9213079a6b53e8
Sponsor Content: #buymote #buymoteeshopping #buymoteonline #buymoteshopping #buymoteapplication"
Step 11: Add User Authentication (Login/Signup)
To allow users to register and log in, we'll use Flask-Login for session management and Flask-WTF for handling forms securely.
11.1: Install Dependencies
First, install the necessary libraries for user authentication and form handling.
pip install flask-login flask-wtf flask-bcrypt
11.2: Update models.py
for User Model
We’ll add a User
model to handle user accounts.
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from flask_bcrypt import Bcrypt
db = SQLAlchemy()
bcrypt = Bcrypt()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(120), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(200), nullable=False)
def __repr__(self):
return f"<User {self.username}>"
def check_password(self, password):
return bcrypt.check_password_hash(self.password, password)
class BlogPost(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
category = db.Column(db.String(50), nullable=False)
created_at = db.Column(db.DateTime, default=db.func.now())
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
user = db.relationship('User', backref=db.backref('posts', lazy=True))
def __repr__(self):
return f"<BlogPost {self.title}>"
-
User
model hasusername
,email
, andpassword
. -
BlogPost
model now has auser_id
to associate each post with a user.
11.3: Add User Authentication Routes
Update your app.py
to manage user registration and login:
from flask import Flask, render_template, redirect, url_for, flash, request
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from models import db, User, BlogPost
from flask_bcrypt import Bcrypt
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Email, EqualTo
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
# User Loader
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# Login Form
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Login')
# Register Form
class RegisterForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Register')
# Routes
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterForm()
if form.validate_on_submit():
hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
new_user = User(username=form.username.data, email=form.email.data, password=hashed_password)
db.session.add(new_user)
db.session.commit()
flash('Your account has been created!', 'success')
return redirect(url_for('login'))
return render_template('register.html', form=form)
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user and bcrypt.check_password_hash(user.password, form.password.data):
login_user(user)
flash('Login successful!', 'success')
return redirect(url_for('index'))
else:
flash('Login unsuccessful. Check username and password', 'danger')
return render_template('login.html', form=form)
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('index'))
# Other routes (index, post, etc.) go here as before
-
User model: Includes fields for
username
,email
, andpassword
. -
Flask-WTF forms: Used to create secure forms for login and registration.
-
Flask-Login: Handles login, logout, and session management.
11.4: Create the Login and Register Templates
Create login.html
and register.html
inside the templates
folder.
login.html:
{% extends 'base.html' %}
{% block content %}
<h2>Login</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div>
{{ form.username.label }}: {{ form.username() }}
</div>
<div>
{{ form.password.label }}: {{ form.password() }}
</div>
<div>
{{ form.submit() }}
</div>
</form>
{% endblock %}
register.html:
{% extends 'base.html' %}
{% block content %}
<h2>Register</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div>
{{ form.username.label }}: {{ form.username() }}
</div>
<div>
{{ form.email.label }}: {{ form.email() }}
</div>
<div>
{{ form.password.label }}: {{ form.password() }}
</div>
<div>
{{ form.confirm_password.label }}: {{ form.confirm_password() }}
</div>
<div>
{{ form.submit() }}
</div>
</form>
{% endblock %}
11.5: Protect Routes with login_required
Update your blog post creation routes to only allow logged-in users to add new posts.
@app.route('/create', methods=['GET', 'POST'])
@login_required
def create_post():
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
category = request.form['category']
new_post = BlogPost(title=title, content=content, category=category, user_id=current_user.id)
db.session.add(new_post)
db.session.commit()
flash('Your post has been created!', 'success')
return redirect(url_for('index'))
return render_template('create_post.html')
Sponsor Key-Word
"This Content Sponsored by Buymote Shopping app
BuyMote E-Shopping Application is One of the Online Shopping App
Now Available on Play Store & App Store (Buymote E-Shopping)
Click Below Link and Install Application: https://buymote.shop/links/0f5993744a9213079a6b53e8
Sponsor Content: #buymote #buymoteeshopping #buymoteonline #buymoteshopping #buymoteapplication"
Step 12: Create Post Submission Form
We’ll also need a form to submit new blog posts. Create a create_post.html
template for this.
{% extends 'base.html' %}
{% block content %}
<h2>Create New Post</h2>
<form method="POST">
<div>
<label>Title</label>
<input type="text" name="title" required>
</div>
<div>
<label>Content</label>
<textarea name="content" required></textarea>
</div>
<div>
<label>Category</label>
<input type="text" name="category" required>
</div>
<div>
<button type="submit">Create Post</button>
</div>
</form>
{% endblock %}
Step 13: Implement User-Specific Content
To make the website even more user-specific, you can show the logged-in user's posts on the homepage or provide an option for them to edit or delete their posts.
Show User's Posts on Dashboard
@app.route('/dashboard')
@login_required
def dashboard():
posts = BlogPost.query.filter_by(user_id=current_user.id).all()
return render_template('dashboard.html', posts=posts)
Create dashboard.html
{% extends 'base.html' %}
{% block content %}
<h2>Your Posts</h2>
<ul>
{% for post in posts %}
<li>{{ post.title }} - <a href="/post/{{ post.id }}">Read</a></li>
{% endfor %}
</ul>
{% endblock %}
Conclusion
At this point, you've built a blog website with user authentication, the ability to create posts, and the framework for handling user-specific content. Here are some further improvements you could add next:
-
Post Editing and Deletion: Allow users to edit or delete their posts.
-
Markdown Support: Let users write posts in Markdown format.
-
Pagination: Implement pagination for the blog posts.
-
Admin Panel: Allow admins to manage all posts
Sponsor Key-Word
"This Content Sponsored by Buymote Shopping app
BuyMote E-Shopping Application is One of the Online Shopping App
Now Available on Play Store & App Store (Buymote E-Shopping)
Click Below Link and Install Application: https://buymote.shop/links/0f5993744a9213079a6b53e8
Sponsor Content: #buymote #buymoteeshopping #buymoteonline #buymoteshopping #buymoteapplication"
By using Flask, Flask-Login, Flask-WTF, and Flask-SQLAlchemy, you now have a solid foundation for a Python web scraping blog website with authentication and post creation functionality. Keep building and expanding!
1. Homepage (/
):
-
The homepage displays a list of blog posts on the topic of Python Web Scraping.
-
Each blog post will show its title as a link, which leads to the individual post page.
-
Visitors can browse posts on various topics (e.g., BeautifulSoup, Scrapy, Selenium) organized in a list.
Example Output (Homepage):
Python Web Scraping Blog
-------------------------------------------
Home | About
Latest Posts
-------------------------------------------
- Introduction to Web Scraping
- Libraries for Python Web Scraping
- Handling Real-World Challenges in Web Scraping
2. Individual Blog Post Page (/post/<id>
):
-
When users click on a blog post title from the homepage, they are directed to the individual post page.
-
The individual post page displays the post's full content and a timestamp for when it was created.
Example Output (Post Page):
Introduction to Web Scraping
-------------------------------------------
Published on: 2025-07-09 14:32:45
Web scraping is the process of extracting data from websites...
3. User Authentication:
Login Page (/login
):
-
Users can log in using their username and password.
-
On successful login, they are redirected to the homepage or their dashboard (if they have one).
Example Output (Login Page):
Login
-------------------------------------------
Username: [_______]
Password: [_______]
[Login]
Register Page (/register
):
-
New users can register by providing a username, email, password, and confirm password.
Example Output (Register Page):
Register
-------------------------------------------
Username: [_______]
Email: [_______]
Password: [_______]
Confirm Password: [_______]
[Register]
4. Dashboard (/dashboard
):
-
After logging in, users can view their personal dashboard, which lists all the posts they've created.
-
Each post can be linked to a view page where the user can edit or delete their posts.
Example Output (Dashboard):
Your Posts
-------------------------------------------
- Introduction to Web Scraping - [Read]
- Libraries for Python Web Scraping - [Read]
5. Create New Post Page (/create
):
-
Registered and logged-in users can create new blog posts from the "Create New Post" page.
-
They can add title, content, and category to their post and then submit it to the database.
Example Output (Create Post Page):
Create New Post
-------------------------------------------
Title: [_________]
Content: [_________]
Category: [_________]
[Create Post]
6. Post Management (Edit/Delete):
-
If you're expanding the project with features to edit or delete posts, users can modify or remove posts they have created from the dashboard or the post's detail page.
7. User Logout:
-
A logged-in user can log out, which will end the current session and redirect them back to the homepage.
Example Output (Logout):
-
Users will be redirected to the homepage with a message such as "You have been logged out successfully."
Final Output Flow
-
Homepage (
/
):-
Displays a list of all blog posts.
-
-
Login/Register:
-
Users can log in to create, edit, or delete posts.
-
-
Dashboard (
/dashboard
):-
Logged-in users can see and manage their posts.
-
-
Create Post (
/create
):-
Registered users can add new blog posts.
-
-
Post Page (
/post/<id>
):-
Displays the full content of a blog post when clicked.
-
-
Logout (
/logout
): -
Logs out the user and redirects to the homepage.
Sponsor Key-Word
"This Content Sponsored by Buymote Shopping app
BuyMote E-Shopping Application is One of the Online Shopping App
Now Available on Play Store & App Store (Buymote E-Shopping)
Click Below Link and Install Application: https://buymote.shop/links/0f5993744a9213079a6b53e8
Sponsor Content: #buymote #buymoteeshopping #buymoteonline #buymoteshopping #buymoteapplication"
Example of a Full Blog Cycle (for a User)
-
First Visit:
-
User lands on the homepage showing a list of blog posts.
-
-
Login:
-
The user navigates to the login page, enters credentials, and logs in.
-
-
Dashboard:
-
After logging in, the user is redirected to their dashboard, where they can see the list of their previously created posts.
-
-
Create New Post:
-
The user clicks on Create Post, enters the title, content, and category for the new post, and submits it.
-
-
Post View:
-
The post appears on the homepage. The user can click the title to view the full post.
-
-
Logout:
-
After managing the posts, the user logs out, and the session is terminated.
-
Possible Enhancements:
-
Admin Panel:
-
If you want to manage content from an admin perspective, you can add an admin user who has more control (e.g., delete any post, approve user registrations).
-
-
Pagination:
-
If you have a large number of blog posts, you can implement pagination to load a certain number of posts per page.
-
-
Comment System:
-
Allow users to comment on each post.
-
-
Markdown Support:
-
Enable users to write posts using Markdown, which can then be converted to HTML for display.
-
-
Styling Enhancements:
-
Improve the website's look by using CSS frameworks like Bootstrap or custom styling for a more polished and professional appearance.
-
Screenshot or Mockup:
If you were to create a mockup, here’s what it could look like:
Homepage:
+-----------------------------------------+
| Python Web Scraping Blog |
|-----------------------------------------|
| Home | About | Login |
+-----------------------------------------+
Latest Posts:
-----------------------------------------
| - Introduction to Web Scraping |
| - Libraries for Python Web Scraping |
| - Handling Real-World Challenges |
+-----------------------------------------+
Post Page:
+-----------------------------------------+
| Introduction to Web Scraping |
|-----------------------------------------|
| Published on: 2025-07-09 14:32:45 |
|-----------------------------------------|
| Content: |
| Web scraping is the process of... |
+-----------------------------------------+
Dashboard:
+-----------------------------------------+
| Your Posts |
|-----------------------------------------|
| - Introduction to Web Scraping |
| - Libraries for Python Web Scraping |
+-----------------------------------------+
This simple blog website should work well for users to read and interact with posts, manage their own content, and have a user-friendly experience.
Comments
Post a Comment