【问题标题】:Store scraped data from news website using PostgreSQL through flask_sqlalchemy使用 PostgreSQL 通过 flask_sqlalchemy 存储从新闻网站抓取的数据
【发布时间】:2021-10-28 04:56:05
【问题描述】:

项目思路简述: 我想将从新闻网站抓取的数据存储在 Postgres 数据库中,然后查询这些数据并使用 Flask 框架将其显示在网站中。

我要抓取的数据类型:标题、链接、图片、日期(日期保存为字符串,因为每个网站的日期格式会有所不同)、新闻文章类型(政治、经济和体育新闻)。

我在数据库中创建一对多关系(一种类型有很多新闻数据)。

我使用 BeautifulSoup 并请求库进行抓取


models.py

import os
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Type(db.Model):
    __tablename__ = 'Type'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    type_name = db.Column(db.String(80))
    news = db.relationship('News', backref='type_news', lazy='dynamic')
    
    def __init__(self, type_name):
        self.type_name = type_name
    
    def __repr__(self):
        return f'<Type {self.id}>'


class News(db.Model):
    __tablename__ = 'news'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(200))
    link = db.Column(db.String(200))
    date = db.Column(db.String(200))
    img = db.Column(db.String(300))

    type_id = db.Column(db.Integer, db.ForeignKey('type.type_id'))
    type = db.relationship('Type')
    
    def __init__(self, title, link, date, img):
        self.title = title
        self.link = link
        self.date = date
        self.img = img
        
    def __repr__(self):
        return f'<News {self.id}>'

config.py

from os import environ, path



db_host = environ.get('DB_HOST', default='localhost')
db_name = environ.get('DB_NAME', default='NewsSqlDB')
db_password = environ.get('DB_PASSWORD', default='securepass')
db_port = environ.get('DB_PORT', default='5432')
db_user = environ.get('DB_USERNAME', default='postgres')


# Database
SQLALCHEMY_DATABASE_URI = f"postgresql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
SQLALCHEMY_TRACK_MODIFICATIONS = False


init.py

import os
from flask import Flask


def create_app(config_filename=None):
    app = Flask(__name__, instance_relative_config=False)
    app.config.from_mapping(
        SECRET_KEY=os.getenv('SECRET_KEY') or b'\x01\xeb\xab/\x026\xd3\xc4?\xfd\x02\x1b\x058\x81`\xe6['
                                              b'\xd6\x8bR\n\xec5',

    )
    if config_filename is None:
        app.config.from_pyfile('config.py', silent=True)
    else:
        app.config.from_mapping(config_filename)

    from .models import db
    db.init_app(app)

    return app

数据抓取后的样子:这是我在抓取网站后保存数据的方式(我为每种类型保存了大量数据)。

data = {
    'Type': 'Sport',
    'Title': ['any title about sport', 'any title about sport', 'any title about sport', ...],
    'Link': ['https://www.ninanews.com/Website/News/Details?key=923825', ...],
    'Date': ['الجمعة 27 , آب 2021 19:08', ...],
    'Image': 
      ['https://images.weserv.nl/url=ninanews.net/Uploads/Images/2021/8/923825c67
3d87e-ef7c-4d68-ad58-1981d5681284.jpg&w=200&h=150&t=absolute', ...],
}

scrape.py

data = {}
for i in [2, 4, 5]:
    url = f'https://www.ninanews.com/Website/News/List?key={i}'
    data["Type"] = get_url_type(url)[0]
    data["Title"] = get_title(i, pages)
    data["Link"] = get_link(i, pages)
    data["Date"] = get_date(i, pages)
    data["Image"] = get_images(i, pages)
    news = News(title=data['Title'], link=data['Link'], date=data['Date'], img=data['Image'])
    type_ = Type(type_name=data['Type'])
    type_.news.append(news)
    db.session.add(type_)
    db.session.add(news)
    db.session.commit()

app.py

from News import create_app
from News.models import db, News, Type

app = create_app()


@app.route('/')
def hello_world():
    type_ = Type.query.order_by(Type.type_name).all()
    titles = News.query.order_by(News.title).all()
    return f"Titles: {type_}" # Titles: []


if __name__ == '__main__':
    with app.app_context():
        import News.scrape_ninanews
        db.create_all()
        app.run()

我的问题:我无法将这些数据保存到 postgresql 数据库(flask_sqlalchemy),因此我可以将其显示在我的网站中。 我看到这个错误:

[SQL: INSERT INTO news (title, link, date, img, type_id) VALUES (%(titl
e)s, %(link)s, %(date)s, %(img)s, %(type_id)s) RETURNING news.id]
[parameters: {'title': ['العراق يحرز المركز الثاني في بطولة العالم بالق
وة البدنية', 'باير ليفركوزن يتصدر الدوري الألماني', 'منتخبنا الوطني يغا
در إلى كوريا الجنوبية', 'اتحاد  ... (336 characters truncated) ... كأس
السوبر', 'الجوية يخطف الدولي علاء عباس', 'غدا.. طائرة خاصة تنقل منتخبنا
 إلى كوريا الجنوبية', 'منتخبنا الأولمبي يخسر أمام منتخب ليبيا الأول ودي
اً'], 'link': ['https://www.ninanews.com/Website/News/Details?key=92420
2', 'https://www.ninanews.com/Website/News/Details?key=924200', 'https:
//www.ninanews.com/Web ... (480 characters truncated) ... site/News/Det
ails?key=923773', 'https://www.ninanews.com/Website/News/Details?key=92
3757', 'https://www.ninanews.com/Website/News/Details?key=923755'], 'da
te': ['السبت 28 , آب 2021 21:14', 'السبت 28 , آب 2021 20:53', 'السبت 28
 , آب 2021 20:12', 'السبت 28 , آب 2021 19:34', 'السبت 28 , آب 2021 17:1
3', 'الجمعة 2 ... (72 characters truncated) ... :13', 'الجمعة 27 , آب 2
021 14:29', 'الجمعة 27 , آب 2021 14:19', 'الجمعة 27 , آب 2021 14:12', '
الجمعة 27 , آب 2021 13:37', 'الجمعة 27 , آب 2021 13:34'], 'img': ['http
s://images.weserv.nl/?url=ninanews.net/Uploads/Images/2021/8/924202-e4e
b72b7-f1d5-46f3-ae45-543e35073a79.jpg&w=200&h=150&t=absolute', 'https:/
/i ... (1229 characters truncated) ... =absolute', 'https://images.wese
rv.nl/?url=ninanews.net/Uploads/Images/2021/8/923755-48f28451-08c1-452b
-9de5-14bb07e842fa.jpg&w=200&h=150&t=absolute'], 'type_id': 1}]
(Background on this error at: https://sqlalche.me/e/14/9h9h)

【问题讨论】:

  • 对于这样的问题,它有助于将它们分解成碎片,这使得编写测试变得更加简单。 “如何将数据刮成字符串”和“如何将字符串存储到 PostreSQL 中”显然是可分离的。会面点是一个字符串——一个的细节不会影响另一个的细节。
  • 请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example

标签: python postgresql flask web-scraping beautifulsoup


【解决方案1】:

News表中的列长度为200。您尝试插入的某些字段的数据> 200。您可以将长度设置为更高的值,然后再试一次。

【讨论】:

  • 很遗憾,这不起作用,我尝试将其设置为 600 或更多,但不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 2022-08-04
相关资源
最近更新 更多