Соответствие списка входных значений запросу базы данных в веб-приложении Flask - PullRequest
0 голосов
/ 11 января 2020

Кто-то помог мне написать скрипт, который будет брать URL-адреса из одного CSV-файла, сравнивать его с другим и выводить возвращаемое значение на основе соответствия.

new.csv -> 1 столбец: urls

scrapers.csv -> 2 столбца: scraper_dom , scraper_id

Этот скрипт выглядит следующим образом:

import csv
from urllib.parse import urlparse
from typing import List

def fnetloc(any) -> str:
    try:
        p = urlparse(any)
        return p.netloc
    except IndexError:
        return 'Error'

class Scraper:
    def __init__(self, scraper_dom: str, scraper_id: str):
        self.scraper_dom = scraper_dom
        self.scraper_id = scraper_id
    def matches(self, fnetloc: str) -> bool:
        return fnetloc.endswith(self.scraper_dom)


class Site:
    def __init__(self, url: str):
        self.url = url
        self.fnetloc = fnetloc(url)
    def get_scraperid(self, scrapers: List[Scraper]) -> str:
        try:
            return next(x.scraper_id for x in scrapers if x.matches(self.fnetloc))
        except:
            return "[no scraper id found]"

sites = [Site(row[0]) for row in csv.reader(open("new.csv"))]
scrapers = [Scraper(row[0], row[1]) for row in csv.reader(open("scrapers.csv"))]

for site in sites:
    print(site.get_scraperid(scrapers), site.url, sep="\t")

Это прекрасно работает, но я работаю над тем, чтобы поместить это в веб-приложение, и пытаюсь проработать тот же лог c используя базу данных MySql PythonAnywhere и SQLAlchemy. Вот что у меня есть (кроме шаблонов HTML, которые отображают представления):

from flask import Flask,render_template, request
from flask_sqlalchemy import SQLAlchemy
from urllib.parse import urlparse
from sqlalchemy.ext.declarative import declarative_base


app = Flask(__name__)
app.config["DEBUG"] = True
app.config["SECRET_KEY"] = "secret_key"
db = SQLAlchemy(app)

SQLALCHEMY_DATABASE_URI = db.create_engine("mysql+mysqlconnector://username:password@username.mysql.pythonanywhere-services.com/username$scrapers?charset=utf8mb4".format(
    username="username",
    password="password",
    hostname="username.mysql.pythonanywhere-services.com",
    databasename="username$scrapers",
))
app.config[SQLALCHEMY_DATABASE_URI]  = SQLALCHEMY_DATABASE_URI
app.config["SQLALCHEMY_POOL_RECYCLE"] = 299
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

db.Model = declarative_base()

class Scrapers(db.Model):
    __tablename__ = "Scrapers"

    id = db.Column(db.Integer, primary_key = True)
    scraper_dom = db.Column(db.String(255))
    scraper_id = db.Column(db.String(128))

db.Model.metadata.create_all(SQLALCHEMY_DATABASE_URI)

Session = db.sessionmaker()
Session.configure(bind=SQLALCHEMY_DATABASE_URI)
session = Session()

scrapers = session.query(Scrapers.scraper_dom, Scrapers.scraper_id)

@app.route("/", methods=["GET","POST"])
def index():
    if request.method == "Get":
        return render_template("url_page.html")
    else:
        return render_template("url_page.html")

@app.route("/submit", methods=["GET","POST"])
def submit():
    que = [urlparse(item).netloc for item in request.form["urls"].split('\n')]
    ids = scrapers.filter(Scrapers.scraper_dom.in_(que))
    results = (ids, '\t', request.form["urls"])
    return render_template("submit.html", results=results)

Проблема, с которой я столкнулся, заключается в следующем:

@app.route("/submit", methods=["GET","POST"])
def submit():
    que = [urlparse(item).netloc for item in request.form["urls"].split('\n')]
    ids = scrapers.filter(Scrapers.scraper_dom.in_(que))
    results = (ids, '\t', request.form["urls"])
    return render_template("submit.html", results=results)

I Мне нужно que, чтобы перебрать мой многострочный ввод (пользователи будут вставлять большие списки URL из Excel), и это здорово. Затем мне нужно взять каждое значение .netloc и сравнить его с scraper_dom , чтобы получить соответствующее значение scraper_id . Наконец, вывод исходных значений url и scraper_id в столбцах, аналогично следующему (хотя мне не нужны имена столбцов в выходных данных):

output_example

Проблема, как написано, просто возвращает SQL из строки:

ids = scrapers.filter(Scrapers.scraper_dom.in_(que))

Что-то вроде (учитывая ввод www.1688.com):

broken_output

Что мне не хватает? Я пытался написать ids несколькими различными способами, и я получаю ошибки:

ids = scrapers.filter(scrapers.scraper_dom.in_(que))

Ошибка:

AttributeError: объект 'Query' имеет нет атрибута 'scraper_dom'

ids = Scrapers.query.filter(Scrapers.scraper_dom.in_((que)))

Ошибка:

AttributeError: тип объекта «Скребки» не имеет атрибута «запрос»

Я использую идею соответствия, основанную на: [x for x in a if x in b]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...