Несоответствие данных выводимых на экран с данными экспортируемыми в excel-файл
Есть Flask-проект:
from flask import Flask, request, render_template, send_file
import requests
# import csv
import pandas as pd
from io import BytesIO
import logging
import json
# import pandas as pd
# from io import BytesIO
# -*- coding: utf-8 -*-
import sys
sys.stdout.reconfigure(encoding='utf-8')
logging.basicConfig(level=logging.DEBUG)
app = Flask(__name__)
# Функция для поиска вакансий
def search_vacancies(keyword):
BASE_URL = "https://api.hh.ru/vacancies"
vacancies_found = [] # Список для хранения найденных вакансий
per_page = 100
page = 0
while True:
params = {
'text': keyword,
'page': page,
'per_page': per_page,
'only_with_salary': True # Только вакансии с зарплатой
}
response = requests.get(BASE_URL, params=params)
if response.status_code != 200:
print("Ошибка при обращении к API")
break
lan = response.json()
if not lan['items']:
break
for item in lan['items']:
# vacancy_name = item['name']
vacancy_name = item['name'].lower() # Приводим название вакансии к нижнему регистру для сравнения
# Проверяем, содержит ли название вакансии ключевое слово
if keyword in vacancy_name:
salary_from = item['salary']['from'] if item['salary'] else None
salary_to = item['salary']['to'] if item['salary'] else None
currency = item['salary']['currency'] if item['salary'] else None
city = item['area']['name'] if 'area' in item else None
link = item['alternate_url'] if 'alternate_url' in item else None
discription = item['snippet']['responsibility'] if 'snippet' in item else None
vacancies_found.append({
'name': vacancy_name,
'salary_from': salary_from,
'salary_to': salary_to,
'currency': currency,
'city': city,
'link': link,
'discription': discription
})
page += 1
return vacancies_found
@app.route('/download', methods=['POST'])
def download():
keyword = request.form['work_name']
vacancies = search_vacancies(keyword)
df = pd.DataFrame(vacancies)
output = BytesIO()
df.to_excel(output, index=False)
output.seek(0)
return send_file(output, as_attachment=True, download_name='vacancies.xlsx')
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
keyword = request.form['keyword']
vacancies = search_vacancies(keyword)
print(len(vacancies))
all_vacancies = (len(vacancies))
if vacancies:
# filename = save_to_json(vacancies)
return render_template('index.html', vacancies=vacancies, download=True, all_vacancies=all_vacancies)
else:
return render_template('index.html', all_vacancies=0)
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
<h1>Парсер вакансий</h1>
<form method="POST">
<label for="keyword">Введите вакансию для поиска:</label>
<input type="text" id="keyword" style="margin-left: -2%;" name="keyword" required>
<button type="submit">Искать</button>
</form>
{% if vacancies %}
<h2>Найденные вакансии: {{ all_vacancies }}</h2>
<form method="post" action="/download">
<input type="hidden" name="work_name" value="{{ keyword }}">
<input type="submit" value="Скачать в Excel">
</form>
<table>
<tr>
<th>Название</th>
<th>Зарплата от</th>
<th>Зарплата до</th>
<th>Валюта</th>
<th>Город</th>
<th>Описание</th>
<th>Ссылка</th>
</tr>
{% for vacancy in vacancies %}
<tr>
<td>{{ vacancy.name }}</td>
<td>{{ vacancy.salary_from }}</td>
<td>{{ vacancy.salary_to }}</td>
<td>{{ vacancy.currency }}</td>
<td>{{ vacancy.city }}</td>
<td>{{ vacancy.discription }}</td>
<td><a href="{{ vacancy.link }}" class="vacancy-link">{{ vacancy.link }}</a></td>
</tr>
{% endfor %}
</table>
{% elif message %}
<p>{{ message }}</p>
{% endif %}
<form method="post" action="/download">
<input type="hidden" name="work_name" value="{{ keyword }}">
<input type="submit" value="Скачать в Excel">
</form>
<!--{#</table>#}-->
</body>
</html>
Проблема в том, что результаты парсинга выводимых на экран не совпадают с данными экспортируемыми в excel-файл. Причём запрашиваю разные данные по ключевому слову и выводятся на экран данные соответствуюшие этому ключевому слову, а данные экспортируемые в excel-файл всегда одни и те же, хотя должны соответствовать данным на отображаемым на экране. Не могу понять почему так происходит, если кто знает подскажите в чём проблема.
Ссылка на проект: https://abram742.pythonanywhere.com/
Ответы (1 шт):
Относительно разницы между данными в браузере и Excel, есть два замечания.
Во-первых, вы не передали в render_template
значение keyword
, сохраняемое в форме "work_name"
. При сохранении в Excel-файл вы повторно запрашиваете данные, используя значение из "work_name"
как keyword
, но там ничего нет. То есть, в таблице каждый раз сохраняется результат запроса по пустой строке.
Во-вторых, после первого запроса данные могут измениться (вакансии удаляются или добавляются), и результат может не совпасть с экраном. Лучше сохранять данные в таблицу на стороне клиента, или хотя бы кешировать их на своём сервере, чтобы избежать повторных запросов к источнику данных.
Минимальные изменения, чтобы сделать приложение рабочим:
from flask import redirect
def download():
keyword = request.form.get('work_name', '').strip()
if keyword == '': # ничего не делать если keyword не задан
return redirect('/')
...
def index():
keyword = request.form.get('keyword', '').strip()
if request.method == 'POST' and keyword: # обновлять страницу только если задано ключевое слово
vacancies = search_vacancies(keyword)
...
if vacancies:
return render_template('index.html',
vacancies=vacancies,
download=True,
all_vacancies=all_vacancies,
keyword=keyword) # сохранить keyword на html-странице
else:
return render_template('index.html',
all_vacancies=0, # даже если по запросу ничего нет
keyword=keyword) # сохранить keyword на html-странице
return render_template('index.html') # пустой keyword приемлем для стартовой страницы без каких-либо данных
Минимальное изменение, чтобы не повторять запрос при сохранении:
from functools import lru_cache
@lru_cache(maxsize=1) # хранить в кеше только результат крайнего запроса
def search_vacancies(keyword):
...
Недостаток такого кеширования в том, что повторный запрос по тому же слову возвращает устаревший результат. Например, если клиент сделал запрос, свернул браузер, вернулся через сутки и повторил тот же поиск, то он получит прежний ответ. Стоит очищать кеш через значимое время.