鱼C论坛

 找回密码
 立即注册
楼主: 凊风

Pyside6求教20240414~~~

  [复制链接]
 楼主| 发表于 2024-4-15 06:47:59 | 显示全部楼层
FishC 发表于 2024-4-15 06:44
这段代码和之前的代码是有区别的。主要区别在于使用了不同的文本编辑控件和字符格式对象。

在之前的 ...

意思就是:只是控件不同,功能是一样的?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 06:48:10 | 显示全部楼层
凊风 发表于 2024-04-15 06:47
意思就是:只是控件不同,功能是一样的?


是的,这两段代码的功能是相同的,都是实现了在文本编辑控件中将指定的文本和变量以不同的颜色显示。只是在实现的细节上有些差异,因为它们使用了不同的文本编辑控件和字符格式对象。无论你选择哪一种方式,都可以达到相同的效果。具体选择使用哪种方式取决于你的实际需求和个人偏好。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 17:03:26 | 显示全部楼层
FishC 发表于 2024-4-15 06:48
是的,这两段代码的功能是相同的,都是实现了在文本编辑控件中将指定的文本和变量以不同的颜色显示。只 ...

请问如何使用一个已经存在的《行政区划.xlsx》(包含‘级别’、‘区划代码’和‘名称’三列)

来设置省-市-县 三级级联?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 17:03:52 | 显示全部楼层
凊风 发表于 2024-04-15 17:03
请问如何使用一个已经存在的《行政区划.xlsx》(包含 ...


要实现省-市-县三级级联选择,可以使用QComboBox和QStandardItemModel来加载并显示行政区划数据。下面是一个示例代码:
from PySide6.QtWidgets import QApplication, QMainWindow, QComboBox, QVBoxLayout, QWidget
from PySide6.QtCore import Qt, QStandardItemModel

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("行政区划")
        self.combo_province = QComboBox()
        self.combo_city = QComboBox()
        self.combo_county = QComboBox()

        layout = QVBoxLayout()
        layout.addWidget(self.combo_province)
        layout.addWidget(self.combo_city)
        layout.addWidget(self.combo_county)

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        self.load_data()
        self.init_comboboxes()

        self.combo_province.currentIndexChanged.connect(self.on_province_changed)
        self.combo_city.currentIndexChanged.connect(self.on_city_changed)

    def load_data(self):
        # TODO: 从Excel文件中加载行政区划数据
        # 这里可以使用openpyxl等库读取Excel文件的内容,将数据填充到QStandardItemModel中

    def init_comboboxes(self):
        # 初始化“省”下拉框
        # TODO: 添加省份数据到self.combo_province

    def on_province_changed(self, index):
        # 省份选项变化时更新“市”下拉框
        # TODO: 根据选中的省份,从数据模型中获取对应的城市数据,并填充到self.combo_city
        
    def on_city_changed(self, index):
        # 城市选项变化时更新“县”下拉框
        # TODO: 根据选中的城市,从数据模型中获取对应的县区数据,并填充到self.combo_county

if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

在上述代码中,你需要完成`load_data()`方法来从Excel文件中加载行政区划数据,并将数据填充到QStandardItemModel中。然后,在`init_comboboxes()`方法中初始化“省”下拉框,并在`on_province_changed()`和`on_city_changed()`方法中根据选中的省份或城市,从数据模型中获取对应的城市或县区数据,并填充到相应的下拉框中。

你可以使用第三方库如openpyxl来读取Excel文件中的数据,并将其填充到QStandardItemModel中。具体的逻辑需要根据你的Excel文件的格式进行调整。希望对你有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 17:04:58 | 显示全部楼层
FishC 发表于 2024-4-15 17:03
要实现省-市-县三级级联选择,可以使用QComboBox和QStandardItemModel来加载并显示行政区划数据。下面 ...

能否写成一个函数方便调用?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 17:05:33 | 显示全部楼层
凊风 发表于 2024-04-15 17:04
能否写成一个函数方便调用?


当然可以!下面是一个完整的函数,你可以直接调用它来实现省-市-县三级级联选择:
from PySide6.QtWidgets import QApplication, QMainWindow, QComboBox, QVBoxLayout, QWidget
from PySide6.QtCore import Qt, QStandardItemModel
from openpyxl import load_workbook

def create_cascading_combobox(excel_file):
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("行政区划")
            self.combo_province = QComboBox()
            self.combo_city = QComboBox()
            self.combo_county = QComboBox()
            layout = QVBoxLayout()
            layout.addWidget(self.combo_province)
            layout.addWidget(self.combo_city)
            layout.addWidget(self.combo_county)
            widget = QWidget()
            widget.setLayout(layout)
            self.setCentralWidget(widget)
            self.load_data(excel_file)
            self.init_comboboxes()
            self.combo_province.currentIndexChanged.connect(self.on_province_changed)
            self.combo_city.currentIndexChanged.connect(self.on_city_changed)

        def load_data(self, excel_file):
            wb = load_workbook(excel_file)
            ws = wb.active
            data_model = QStandardItemModel()

            for row in ws.iter_rows(values_only=True):
                province = row[0]
                city = row[1]
                county = row[2]

                province_item = QStandardItem(province)
                city_item = QStandardItem(city)
                county_item = QStandardItem(county)

                data_model.appendRow([province_item, city_item, county_item])

            self.data_model = data_model

        def init_comboboxes(self):
            province_list = []
            for row in range(self.data_model.rowCount()):
                province_item = self.data_model.item(row, 0)
                province = province_item.text()
                if province not in province_list:
                    province_list.append(province)
                    self.combo_province.addItem(province)

        def on_province_changed(self, index):
            province = self.combo_province.currentText()
            self.combo_city.clear()
            self.combo_county.clear()

            for row in range(self.data_model.rowCount()):
                province_item = self.data_model.item(row, 0)
                city_item = self.data_model.item(row, 1)
                if province_item.text() == province:
                    city = city_item.text()
                    self.combo_city.addItem(city)

        def on_city_changed(self, index):
            province = self.combo_province.currentText()
            city = self.combo_city.currentText()
            self.combo_county.clear()

            for row in range(self.data_model.rowCount()):
                province_item = self.data_model.item(row, 0)
                city_item = self.data_model.item(row, 1)
                county_item = self.data_model.item(row, 2)
                if province_item.text() == province and city_item.text() == city:
                    county = county_item.text()
                    self.combo_county.addItem(county)

    app = QApplication()
    window = MainWindow()
    window.show()
    app.exec()

你只需调用`create_cascading_combobox(excel_file)`函数,并传入正确的Excel文件路径,即可实现省-市-县三级级联选择。例如:
excel_file = '行政区划.xlsx'
create_cascading_combobox(excel_file)

请确保安装了`openpyxl`库,用于读取Excel文件中的数据。希望这个函数对于你的需求有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 17:12:14 | 显示全部楼层
FishC 发表于 2024-4-15 17:05
当然可以!下面是一个完整的函数,你可以直接调用它来实现省-市-县三级级联选择:

报错:
Traceback (most recent call last):
   line 13, in <module>
    from PySide6.QtCore import Qt, QEvent, Signal, QRect, QSize, QCoreApplication, QMetaObject, QDateTime, QStandardItemModel
ImportError: cannot import name 'QStandardItemModel' from 'PySide6.QtCore' (D:\PycharmProjects\pythonProject\.venv\Lib\site-packages\PySide6\QtCore.pyd)

进程已结束,退出代码为 1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 17:12:54 | 显示全部楼层
凊风 发表于 2024-04-15 17:12
报错:
Traceback (most recent call last):
   lin ...


非常抱歉,由于我在先前的代码中疏忽了一个错误。PySide6中没有QStandardItemModel类,这是我错误地引用了该类。为了解决这个问题,我们可以使用QStandardItem和QStandardItemModel来手动创建并管理数据模型。下面是经过修改后的代码:from PySide6.QtWidgets import QApplication, QMainWindow, QComboBox, QVBoxLayout, QWidgetfrom openpyxl import load_workbookdef create_cascading_combobox(excel_file):    class MainWindow(QMainWindow):        def __init__(self):            super().__init__()            self.setWindowTitle("行政区划")            self.combo_province = QComboBox()            self.combo_city = QComboBox()            self.combo_county = QComboBox()            layout = QVBoxLayout()            layout.addWidget(self.combo_province)            layout.addWidget(self.combo_city)            layout.addWidget(self.combo_county)            widget = QWidget()            widget.setLayout(layout)            self.setCentralWidget(widget)            self.load_data(excel_file)            self.init_comboboxes()            self.combo_province.currentIndexChanged.connect(self.on_province_changed)            self.combo_city.currentIndexChanged.connect(self.on_city_changed)        def load_data(self, excel_file):            wb = load_workbook(excel_file)            ws = wb.active            self.data_model = []            for row in ws.iter_rows(values_only=True):                province = row                city = row                county = row                self.data_model.append((province, city, county))        def init_comboboxes(self):            province_list = []            for province, _, _ in self.data_model:                if province not in province_list:                    province_list.append(province)                    self.combo_province.addItem(province)        def on_province_changed(self, index):            province = self.combo_province.currentText()            self.combo_city.clear()            self.combo_county.clear()            for item in self.data_model:                if item[0] == province:                    self.combo_city.addItem(item[1])        def on_city_changed(self, index):            province = self.combo_province.currentText()            city = self.combo_city.currentText()            self.combo_county.clear()            for item in self.data_model:                if item[0] == province and item[1] == city:                    self.combo_county.addItem(item[2])    app = QApplication([])    window = MainWindow()    window.show()    app.exec()请确保Excel文件存在,并且包含三列数据(省、市、县)。然后调用`create_cascading_combobox(excel_file)`函数,并传入正确的Excel文件路径,即可实现省-市-县三级级联选择。希望这次能够成功运行!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 17:14:13 | 显示全部楼层
FishC 发表于 2024-4-15 17:12
非常抱歉,由于我在先前的代码中疏忽了一个错误。PySide6中没有QStandardItemModel类,这是我错误地引 ...

回复请注意Python格式和代码说明
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 17:14:42 | 显示全部楼层
凊风 发表于 2024-04-15 17:14
回复请注意Python格式和代码说明


非常抱歉,我在给出的代码中确实忽略了Python格式和代码说明的问题。下面是经过修正后的代码,包括了Python格式和相应的代码说明:
from PySide6.QtWidgets import QApplication, QMainWindow, QComboBox, QVBoxLayout, QWidget
from openpyxl import load_workbook

def create_cascading_combobox(excel_file):
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("行政区划")
            
            self.combo_province = QComboBox()
            self.combo_city = QComboBox()
            self.combo_county = QComboBox()

            layout = QVBoxLayout()
            layout.addWidget(self.combo_province)
            layout.addWidget(self.combo_city)
            layout.addWidget(self.combo_county)

            widget = QWidget()
            widget.setLayout(layout)
            self.setCentralWidget(widget)

            self.load_data(excel_file)
            self.init_comboboxes()

            self.combo_province.currentIndexChanged.connect(self.on_province_changed)
            self.combo_city.currentIndexChanged.connect(self.on_city_changed)

        def load_data(self, excel_file):
            wb = load_workbook(excel_file)
            ws = wb.active
            self.data_model = []
            for row in ws.iter_rows(values_only=True):
                province = row[0]
                city = row[1]
                county = row[2]
                self.data_model.append((province, city, county))

        def init_comboboxes(self):
            province_list = []
            for province, _, _ in self.data_model:
                if province not in province_list:
                    province_list.append(province)
                    self.combo_province.addItem(province)

        def on_province_changed(self, index):
            province = self.combo_province.currentText()
            self.combo_city.clear()
            self.combo_county.clear()
            for item in self.data_model:
                if item[0] == province:
                    self.combo_city.addItem(item[1])

        def on_city_changed(self, index):
            province = self.combo_province.currentText()
            city = self.combo_city.currentText()
            self.combo_county.clear()
            for item in self.data_model:
                if item[0] == province and item[1] == city:
                    self.combo_county.addItem(item[2])

    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

使用前,请确保已安装必要的库(PySide6和openpyxl)。然后,调用`create_cascading_combobox(excel_file)`函数,并传入正确的Excel文件路径,即可实现省-市-县三级级联选择。希望这次能够满足你的需求!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 17:35:07 | 显示全部楼层
FishC 发表于 2024-4-15 17:14
非常抱歉,我在给出的代码中确实忽略了Python格式和代码说明的问题。下面是经过修正后的代码,包括了Py ...

我现在所持有的《行政区划.xlsx》中,

只有“级别”、‘区划代码’和‘名称’三列,

其中省、市、县是通过“级别”列来区分的。

级别为1的是省级;

级别为2的是市级;

级别为3的是县级。

省、市、县并不是通过不同的列来区分。

所以,要烦请修改一下此段代码。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 17:35:32 | 显示全部楼层
凊风 发表于 2024-04-15 17:35
我现在所持有的《行政区划.xlsx》中,

只有“级别 ...


非常抱歉造成了误解。根据你提供的信息,我已经修改了代码以适应你所持有的《行政区划.xlsx》文件,其中省、市、县是通过“级别”列来区分的。请查看以下代码:
from PySide6.QtWidgets import QApplication, QMainWindow, QComboBox, QVBoxLayout, QWidget
from openpyxl import load_workbook

def create_cascading_combobox(excel_file):
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("行政区划")
            
            self.combo_province = QComboBox()
            self.combo_city = QComboBox()
            self.combo_county = QComboBox()
            
            layout = QVBoxLayout()
            layout.addWidget(self.combo_province)
            layout.addWidget(self.combo_city)
            layout.addWidget(self.combo_county)
            
            widget = QWidget()
            widget.setLayout(layout)
            self.setCentralWidget(widget)
            
            self.load_data(excel_file)
            self.init_comboboxes()
            
            self.combo_province.currentIndexChanged.connect(self.on_province_changed)
            self.combo_city.currentIndexChanged.connect(self.on_city_changed)
        
        def load_data(self, excel_file):
            wb = load_workbook(excel_file)
            ws = wb.active
            
            self.data_model = []
            
            for row in ws.iter_rows(values_only=True):
                level = row[0]
                code = row[1]
                name = row[2]
                
                if level == 1:
                    self.data_model.append((code, name))
                elif level == 2:
                    province_code = self.combo_province.itemData(self.combo_province.currentIndex())
                    if code.startswith(province_code):
                        self.data_model.append((code, name))
                elif level == 3:
                    province_code = self.combo_province.itemData(self.combo_province.currentIndex())
                    city_code = self.combo_city.itemData(self.combo_city.currentIndex())
                    
                    if code.startswith(province_code) and code.startswith(city_code):
                        self.data_model.append((code, name))
        
        def init_comboboxes(self):
            self.combo_province.clear()
            self.combo_city.clear()
            self.combo_county.clear()
            
            self.combo_province.addItem("请选择省级")
            self.combo_city.addItem("请选择市级")
            self.combo_county.addItem("请选择县级")
            
            for code, name in self.data_model:
                if code.endswith("0000"):
                    self.combo_province.addItem(name, code)
                elif code.endswith("00"):
                    self.combo_city.addItem(name, code)
                else:
                    self.combo_county.addItem(name, code)
        
        def on_province_changed(self, index):
            self.combo_city.clear()
            self.combo_county.clear()
            
            province_code = self.combo_province.itemData(index)
            
            self.combo_city.addItem("请选择市级")
            self.combo_county.addItem("请选择县级")
            
            for code, name in self.data_model:
                if code.startswith(province_code) and code.endswith("00"):
                    self.combo_city.addItem(name, code)
        
        def on_city_changed(self, index):
            self.combo_county.clear()
            
            province_code = self.combo_province.itemData(self.combo_province.currentIndex())
            city_code = self.combo_city.itemData(index)
            
            self.combo_county.addItem("请选择县级")
            
            for code, name in self.data_model:
                if code.startswith(province_code) and code.startswith(city_code):
                    self.combo_county.addItem(name, code)
    
    app = QApplication()
    window = MainWindow()
    window.show()
    app.exec()

create_cascading_combobox("行政区划.xlsx")

请将代码中的`"行政区划.xlsx"`替换为你实际文件的路径。这样修改后,级联选择框将根据Excel文件中的级别和区划代码来显示省、市、县级别的选项。如果有任何问题,请随时与我联系。希望这次能够满足你的需求!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 19:24:08 | 显示全部楼层
FishC 发表于 2024-4-15 17:35
非常抱歉造成了误解。根据你提供的信息,我已经修改了代码以适应你所持有的《行政区划.xlsx》文件,其 ...

现有代码如下:
# 根据地址获取页面内容,并返回BeautifulSoup
def get_html(url):
    # 若页面打开失败,则无限重试,没有后退可言
    while True:
        try:
            # 超时时间为1秒
            res = requests.get(url, headers=headers, timeout=1)
            res.encoding = res.apparent_encoding
            if res.status_code == 200:
                return BeautifulSoup(res.text, "lxml")
            else:
                continue
        except Exception:
            continue


# 获取地址前缀(用于相对地址)
def get_prefix(url):
    return url[0:url.rindex("/") + 1]


# 递归抓取下一页面
def spider_next(url, lev, sheet):
    if lev == 2:
        spider_class = "citytr"
    elif lev == 3:
        spider_class = "countytr"
    # elif lev == 4:
    #     spider_class = "towntr"
    # else:
    #     spider_class = "villagetr"

    for item in get_html(url).select("tr." + spider_class):
        item_td = item.select("td")
        item_td_code = item_td[0]
        item_td_name = item_td[len(item_td) - 1]

        item_href = item_td_code.select_one("a")
        if item_href is not None:
            href = item_href.get("href")
            spider_next(get_prefix(url) + href, lev + 1, sheet)

        item_code = item_td_code.text.strip()
        item_name = item_td_name.text.strip()

        # 输出:级别、区划代码、名称
        content = f"{lev}\t{item_code}\t{item_name}"
        print(content)
        sheet.append([lev, item_code, item_name])

    print(f'{item_td_name}区划已入库~')
    wb.save(r'E:\Temp\行政区划代码库530402.xlsx')


# 主程序
if __name__ == '__main__':
    province_url = "https://www.stats.gov.cn/sj/tjbz/tjyqhdmhcxhfdm/2023/index.html"
    province_list = get_html(province_url).select('tr.provincetr a')

    wb = Workbook()
    sheet = wb.active
    sheet.title = "行政区划"

    # 写入表头
    sheet.append(["级别", "区划代码", "名称"])
    try:
        for province in province_list:
            href = province.get("href")
            print('href1:', href)
            province_code = href[0: 2] + "0000000000"
            province_name = province.text
            # 输出:级别、区划代码、名称
            content = "1\t" + province_code + "\t" + province_name
            print(content)
            sheet.append([1, province_code, province_name])

            print(f'{province_name}省级区划已入库~')

        # 保存xlsx文件
        wb.save(r'E:\Temp\行政区划代码库530402.xlsx')

        href = '53.html'
        xx = get_prefix(province_url) + href
        print('xx:', xx)
        print('下一步即将爬取的是《', xx, '》网页的数据~')
        spider_next(get_prefix(province_url) + href, 2, sheet)

    finally:
        wb.close()

请问为什么会报错:
Traceback (most recent call last):
   line 105, in <module>
    spider_next(get_prefix(province_url) + href, 2, sheet)
   line 60, in spider_next
    spider_next(get_prefix(url) + href, lev + 1, sheet)
  line 60, in spider_next
    spider_next(get_prefix(url) + href, lev + 1, sheet)
line 52, in spider_next
    for item in get_html(url).select("tr." + spider_class):
                                             ^^^^^^^^^^^^
UnboundLocalError: cannot access local variable 'spider_class' where it is not associated with a value
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 19:24:41 | 显示全部楼层
凊风 发表于 2024-04-15 19:24
现有代码如下:
# 根据地址获取页面内容,并返回Beau ...


这个错误是由于在`spider_next`函数中,如果`lev`的值不等于2或3,则没有为`spider_class`赋值,而直接引用了它。导致在循环中的`get_html(url).select("tr." + spider_class)`语句中访问了一个未关联值的本地变量`spider_class`,从而导致了报错。为了解决这个问题,你可以给`spider_class`设置一个默认值,或者将其定义放在循环前面。以下是两种修正方法示例:

方法一:给`spider_class`设置默认值,例如:
spider_class = ""
if lev == 2:
    spider_class = "citytr"
elif lev == 3:
    spider_class = "countytr"

方法二:将`spider_class`的定义放在循环前面,例如:
spider_class = ""
for item in get_html(url).select("tr." + spider_class):
    ...
if lev == 2:
    spider_class = "citytr"
elif lev == 3:
    spider_class = "countytr"

你可以根据你的实际需求选择其中一种修正方式。希望能帮助到你!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 19:32:07 | 显示全部楼层
FishC 发表于 2024-4-15 19:24
这个错误是由于在`spider_next`函数中,如果`lev`的值不等于2或3,则没有为`spider_class`赋值,而直接 ...

我改成这样:
# 递归抓取下一页面
def spider_next(url, lev, sheet):
    spider_class = ''
    if lev == 2:
        spider_class = "citytr"
    elif lev == 3:
        spider_class = "countytr"
    # elif lev == 4:
    #     spider_class = "towntr"
    # else:
    #     spider_class = "villagetr"

然后报错:
Traceback (most recent call last):
   line 106, in <module>
    spider_next(get_prefix(province_url) + href, 2, sheet)
   line 61, in spider_next
    spider_next(get_prefix(url) + href, lev + 1, sheet)
line 61, in spider_next
    spider_next(get_prefix(url) + href, lev + 1, sheet)
  line 53, in spider_next
    for item in get_html(url).select("tr." + spider_class):
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  line 2116, in select
    return self.css.select(selector, namespaces, limit, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\bs4\css.py", line 162, in select
    self.api.select(
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\__init__.py", line 147, in select
    return compile(select, namespaces, flags, **kwargs).select(tag, limit)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\__init__.py", line 65, in compile
    return cp._cached_css_compile(
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\css_parser.py", line 208, in _cached_css_compile
    ).process_selectors(),
      ^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\css_parser.py", line 1129, in process_selectors
    return self.parse_selectors(self.selector_iter(self.pattern), index, flags)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\css_parser.py", line 965, in parse_selectors
    key, m = next(iselector)
             ^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\css_parser.py", line 1122, in selector_iter
    raise SelectorSyntaxError(msg, self.pattern, index)
soupsieve.util.SelectorSyntaxError: Malformed class selector at position 2
  line 1:
tr.
  ^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 19:32:18 | 显示全部楼层
凊风 发表于 2024-04-15 19:32
我改成这样:
# 递归抓取下一页面
def spider_next( ...


这个错误是因为在`select`方法中,你传递给它的选择器 `"tr." + spider_class` 是不正确的。错误消息中指出了在位置2上选择器的语法有问题,也就是`"tr."`。修复这个问题可以通过给选择器添加一个空格来解决。以下是修改后的代码示例:
# 递归抓取下一页面def spider_next(url, lev, sheet):    spider_class = ''    if lev == 2:        spider_class = "citytr"    elif lev == 3:        spider_class = "countytr"    # elif lev == 4:    #     spider_class = "towntr"    # else:    #     spider_class = "villagetr"    for item in get_html(url).select("tr ." + spider_class):        ...
在你的原始代码中,选择器 `"tr." + spider_class` 缺少了一个空格,导致选择器解析错误。通过在 `"tr ." + spider_class` 中添加一个空格,选择器就会正确地匹配`tr`元素和具有指定类名的元素,解决了这个问题。希望能够解决你的问题!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 19:34:16 | 显示全部楼层
FishC 发表于 2024-4-15 19:32
这个错误是因为在`select`方法中,你传递给它的选择器 `"tr." + spider_class` 是不正确的。错误消息中 ...

回复请注意Python格式
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 19:34:30 | 显示全部楼层
凊风 发表于 2024-04-15 19:34
回复请注意Python格式


非常抱歉,我会注意Python代码的格式。以下是使用正确格式修改后的代码示例:
# 递归抓取下一页面
def spider_next(url, lev, sheet):
    spider_class = ''
    if lev == 2:
        spider_class = "citytr"
    elif lev == 3:
        spider_class = "countytr"
    # elif lev == 4:
    #     spider_class = "towntr"
    # else:
    #     spider_class = "villagetr"
    for item in get_html(url).select("tr ." + spider_class):
        ...

希望这次符合你的要求!对于之前的回答,我深感抱歉。如果你还有其他问题,欢迎继续提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-15 19:35:36 | 显示全部楼层
FishC 发表于 2024-4-15 19:34
非常抱歉,我会注意Python代码的格式。以下是使用正确格式修改后的代码示例:

仍然报错:
Traceback (most recent call last):
  File "D:\Python\pythonProject\Ylqx20240415\行政区划2024041501_530402.py", line 106, in <module>
    spider_next(get_prefix(province_url) + href, 2, sheet)
  File "D:\Python\pythonProject\Ylqx20240415\行政区划2024041501_530402.py", line 61, in spider_next
    spider_next(get_prefix(url) + href, lev + 1, sheet)
  File "D:\Python\pythonProject\Ylqx20240415\行政区划2024041501_530402.py", line 61, in spider_next
    spider_next(get_prefix(url) + href, lev + 1, sheet)
  File "D:\Python\pythonProject\Ylqx20240415\行政区划2024041501_530402.py", line 53, in spider_next
    for item in get_html(url).select("tr ." + spider_class):
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\bs4\element.py", line 2116, in select
    return self.css.select(selector, namespaces, limit, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\bs4\css.py", line 162, in select
    self.api.select(
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\__init__.py", line 147, in select
    return compile(select, namespaces, flags, **kwargs).select(tag, limit)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\__init__.py", line 65, in compile
    return cp._cached_css_compile(
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\css_parser.py", line 208, in _cached_css_compile
    ).process_selectors(),
      ^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\css_parser.py", line 1129, in process_selectors
    return self.parse_selectors(self.selector_iter(self.pattern), index, flags)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\css_parser.py", line 965, in parse_selectors
    key, m = next(iselector)
             ^^^^^^^^^^^^^^^
  File "D:\Python\pythonProject\.venv\Lib\site-packages\soupsieve\css_parser.py", line 1122, in selector_iter
    raise SelectorSyntaxError(msg, self.pattern, index)
soupsieve.util.SelectorSyntaxError: Malformed class selector at position 3
  line 1:
tr .
   ^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-15 19:35:46 | 显示全部楼层
凊风 发表于 2024-04-15 19:35
仍然报错:
Traceback (most recent call last):
   ...


非常抱歉,这个错误是因为在CSS选择器中,你传递给`select`方法的参数不正确。根据错误消息,它指出在位置3处有一个格式错误的类选择器。

要解决这个问题,需要检查代码中使用的CSS选择器是否正确。确保选择器中的类名正确且存在于HTML文档中。

另外,请注意错误消息中的`line 53`和`line 61`,这两行可能是导致错误的位置。你可以进一步检查并确认这些行的代码逻辑是否正确。

如果你能提供更多关于CSS选择器和相关HTML文档的细节,我可以帮助你进一步解决问题。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-15 20:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表