导入json
从 PyQt5.QtCore 导入 pyqtSignal,QThread 从 bs4 导入 BeautifulSoup
// TazzExtractor.py
import requests
from unidecode import unidecode
class TazzExtractor(QThread):
data = pyqtSignal(object)
progress = pyqtSignal(int)
def __init__(self):
super().__init__()
def extractData(self):
# Extract all cities from TAZZ
url = "https://tazz.ro"
# make a request to the site
response = requests.get(url)
# pull data out of HTML file
soup = BeautifulSoup(response.content, 'html.parser')
cities = []
# add every city to cities array
for city in soup.select('div.cities-cards-list a'):
cities.append(city.text.strip())
# Extract restaurants info for each city
data = {}
for city in cities:
# remove the discritics in the city name
city = unidecode(city)
# make the city name lowercase to match the https request
city = city.lower()
url = f"https://tazz.ro/{city}/restaurante"
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
restaurants = []
for i, restaurant in soup.select('div.partnersListLayout div.store-card'):
name = restaurant.select_one('div.store-info h3')
if name is not None:
name = name.text.strip()
else:
name = ''
stars = restaurant.select_one('div.store-info div.store-rating')
if stars is not None:
stars = stars.text.strip()
else:
stars = ''
description = restaurant.select_one('div.store-delivery')
if description is not None:
description = description.text.strip()
else:
description = ''
restaurants.append({"name": name, "stars": stars, "description": description})
progressPercent = int((i+1) / len(cities) * 100)
self.progress.emit(progressPercent)
data[city] = restaurants
self.data.emit(data)
// 主视图.py
from helpers.TazzExtractor import TazzExtractor
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QTableWidgetItem, QTableWidget, QProgressBar
# display the extracted data in a table
class RestaurantTable(QWidget):
def __init__(self, data):
super().__init__()
self.title = "Tazz Restaurants"
self.width = 800
self.height = 600
self.setWindowTitle(self.title)
self.setGeometry(200, 200, self.width, self.height)
self.table_widget = QTableWidget()
# set the number of rows to the length of data
row_count = sum(len(restaurants) for city, restaurants in data.items())
self.table_widget.setRowCount(row_count)
# set column count to 3 (name, description, stars)
self.table_widget.setColumnCount(3)
self.table_widget.setHorizontalHeaderLabels(['Restaurant', 'Description', 'Stars'])
row = 0
print(data)
for city, restaurants in data.items():
for restaurant in restaurants:
self.table_widget.setItem(row, 0, QTableWidgetItem(restaurant["name"]))
self.table_widget.setItem(row, 1, QTableWidgetItem(restaurant["description"]))
self.table_widget.setItem(row, 2, QTableWidgetItem(restaurant["stars"]))
row += 1
self.table_widget.setItem(row, 0, QTableWidgetItem(''))
self.table_widget.setItem(row, 1, QTableWidgetItem(''))
class MainView(QWidget):
def __init__(self):
super().__init__()
self.data = None
self.title = "Tazz Cities"
self.width = 800
self.height = 600
self.setWindowTitle(self.title)
self.setGeometry(200, 200, self.width, self.height)
self.extractor = TazzExtractor()
self.progressBar = QProgressBar()
self.progressBar.setMinimum(0)
self.progressBar.setMaximum(100)
self.extractButton = QPushButton("Extract data")
self.extractButton.clicked.connect(self.extractData)
self.tableButton = QPushButton("Show Data Table")
self.tableButton.setDisabled(True)
self.tableButton.clicked.connect(self.showTable)
layout = QVBoxLayout()
layout.addWidget(self.extractButton)
layout.addWidget(self.progressBar)
layout.addWidget(self.tableButton)
self.setLayout(layout)
self.extractor.data.connect(self.saveData)
self.tableWindow = None
def extractData(self):
self.progressBar.setValue(0)
self.extractor.progress.connect(self.updateProgressBar)
self.extractor.start()
self.tableButton.setDisabled(False)
def updateProgressBar(self, progressPercent):
self.progressBar.setValue(progressPercent)
def saveData(self, data):
self.data = data
def showTable(self):
if self.tableWindow is None:
self.tableWindow = RestaurantTable(self.data)
self.tableWindow.show()
在MainView的extractData方法中提取数据,但是窗口不显示