Кто-то помог мне написать скрипт, который будет брать 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](https://i.stack.imgur.com/4P9Dw.png)
Проблема, как написано, просто возвращает SQL из строки:
ids = scrapers.filter(Scrapers.scraper_dom.in_(que))
Что-то вроде (учитывая ввод www.1688.com):
![broken_output](https://i.stack.imgur.com/pdXXB.png)
Что мне не хватает? Я пытался написать 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]