凊风
发表于 2024-4-15 22:12:22
FishC 发表于 2024-4-15 17:35
非常抱歉造成了误解。根据你提供的信息,我已经修改了代码以适应你所持有的《行政区划.xlsx》文件,其 ...
请问为什么会报错:
Traceback (most recent call last):
line 771, in on_combobox_clicked
self.select_folder(self)
line 810, in select_folder
self.region_select(self.Region_file)
line 819, in region_select
self.load_data(self.Region_file)
line 848, in load_data
if code.startswith(province_code) and code.startswith(city_code):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: startswith first arg must be str or a tuple of str, not NoneType
FishC
发表于 2024-4-15 22:12:36
凊风 发表于 2024-04-15 22:12
请问为什么会报错:
Traceback (most recent call la ...
这个错误是因为在`load_data`函数中,`province_code`和`city_code`可能为`None`导致的。要解决这个问题,你可以在使用`startswith`之前先进行判断。请修改以下代码:
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
code = row
name = row
if level == 1:
self.data_model.append((code, name))
elif level == 2:
province_code = self.combo_province.itemData(self.combo_province.currentIndex())
if province_code and 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 province_code and city_code and code.startswith(province_code) and code.startswith(city_code):
self.data_model.append((code, name))
在这个修改后的代码中,我们在使用`startswith`之前先检查了`province_code`和`city_code`是否存在。只有当它们都存在时,才进行`startswith`的判断。这样就避免了`NoneType`错误。
希望这次能够解决你的问题!如果还有其他疑问,请随时告诉我。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
凊风
发表于 2024-4-15 22:18:38
FishC 发表于 2024-4-15 22:12
这个错误是因为在`load_data`函数中,`province_code`和`city_code`可能为`None`导致的。要解决这个问 ...
我改成这样以后:if (code.startswith(province_code) and code.startswith(city_code) and code.startswith(city_code)):
self.data_model.append((code, name))
仍然报错:
Traceback (most recent call last):
line 771, in on_combobox_clicked
self.select_folder(self)
line 810, in select_folder
self.region_select(self.Region_file)
line 819, in region_select
self.load_data(self.Region_file)
line 848, in load_data
if (code.startswith(province_code) and code.startswith(city_code) and code.startswith(city_code)):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: startswith first arg must be str or a tuple of str, not NoneType
FishC
发表于 2024-4-15 22:18:50
凊风 发表于 2024-04-15 22:18
我改成这样以后:if (code.startswith(province_code) ...
对不起,我之前的回答有误。在逻辑上,同一个字符串怎么可能既以`province_code`开头又以`city_code`开头呢?这就是报错的原因。
如果你想要通过两个条件来筛选数据,可以使用逻辑运算符`or`,而不是`and`。修改代码如下:
if (code.startswith(province_code) or code.startswith(city_code)):
self.data_model.append((code, name))
这样修改后,只要字符串以`province_code`或者`city_code`开头,就会将数据添加到`data_model`中。
希望这次能够解决你的问题!如果还有其他疑问,请随时告诉我。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
凊风
发表于 2024-4-15 22:20:14
FishC 发表于 2024-4-15 22:18
对不起,我之前的回答有误。在逻辑上,同一个字符串怎么可能既以`province_code`开头又以`city_code`开 ...
同样的报错:
if (code.startswith(province_code) or code.startswith(city_code)):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: startswith first arg must be str or a tuple of str, not NoneType
FishC
发表于 2024-4-15 22:20:25
凊风 发表于 2024-04-15 22:20
同样的报错:
if (code.startswith(province_code) o ...
非常抱歉,我忽略了错误提示中的重要信息。根据错误提示,`startswith`的第一个参数不能是NoneType,这意味着`province_code`或`city_code`其中之一是None。请确保`province_code`和`city_code`都有合适的值传递给`startswith`方法。你可以在使用`startswith`前添加一些条件来确保这些值不为空,例如:if province_code is not None and city_code is not None: if code.startswith(province_code) or code.startswith(city_code): self.data_model.append((code, name))这样修改后,在进行startswith比较之前,会先检查province_code和city_code是否为None,以避免出现错误。希望这次解决了你的问题!如果还有其他疑问,请随时告诉我。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
凊风
发表于 2024-4-16 08:22:42
请问这又是什么原因报错?
Traceback (most recent call last):
line 100, 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)
~~~~~~~~~~~~~~~~^~~~~~
TypeError: can only concatenate str (not "NoneType") to str
数据已经下载到了7万多条,然后报错,中止了.....
FishC
发表于 2024-4-16 08:22:51
凊风 发表于 2024-04-16 08:22
请问这又是什么原因报错?
Traceback (most recent c ...
这个错误提示表明在某个地方出现了NoneType类型的值,在字符串连接的过程中导致了错误。根据代码,出错的部分应该是`get_prefix(province_url) + href`这一行。
报错的原因可能是`get_prefix(province_url)`返回了None,无法与字符串类型的`href`进行连接操作。
您可以检查一下`get_prefix()`函数的实现,确保它能够正确返回一个字符串类型的值。如果有必要,可以加入一些异常处理机制,以应对返回None的情况。
另外,还需要检查一下变量`province_url`的赋值过程,确保它被正确初始化为一个有效的URL字符串。
最后,如果仍然无法解决问题,请提供更多与错误相关的代码,以便我能够更详细地帮助您找到问题所在。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
凊风
发表于 2024-4-16 08:32:03
FishC 发表于 2024-4-16 08:22
这个错误提示表明在某个地方出现了NoneType类型的值,在字符串连接的过程中导致了错误。根据代码,出错 ...
完整代码是这样的:
def get_html(url):
while True:
try:
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
# 递归抓取下一页面
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
item_td_name = item_td
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()
wb.save(r'E:\Temp\代码库.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")
province_code = href + "0000000000"
province_name = province.text
# 输出:级别、区划代码、名称
content = "1\t" + province_code + "\t" + province_name
print(content)
sheet.append()
spider_next(get_prefix(province_url) + href, 2, sheet)
# 保存xlsx文件
wb.save(r'E:\Temp\代码库.xlsx')
finally:
wb.close()
报错:
Traceback (most recent call last):
line 100, 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)
~~~~~~~~~~~~~~~~^~~~~~
TypeError: can only concatenate str (not "NoneType") to str
FishC
发表于 2024-4-16 08:32:15
凊风 发表于 2024-04-16 08:32
完整代码是这样的:
def get_html(url):
...
感谢提供完整的代码。根据您提供的代码,出错的原因在于`get_prefix()`函数的实现问题。在您给出的代码中,`get_prefix()`函数只简单地返回了参数`url`,而没有进行任何处理。这导致在拼接URL时可能会出现`None`值,从而引发错误。
为了解决这个问题,我建议修改`get_prefix()`函数的实现,以确保它能够正确地获取地址的前缀。您可以尝试使用`urlparse`模块来解析URL并提取出前缀部分。具体修改如下:
from urllib.parse import urlparse
# 获取地址前缀(用于相对地址)
def get_prefix(url):
parsed_url = urlparse(url)
prefix = f"{parsed_url.scheme}://{parsed_url.netloc}"
return prefix
通过使用`urlparse`函数,我们将URL分解为其组成部分,并使用`scheme`和`netloc`属性构建前缀。这样,您就可以在拼接URL时排除`None`值的情况。
请将这个修改后的`get_prefix()`函数替换原来的函数,并再次运行程序,看看是否能够解决报错问题。如果仍然有其他问题,请随时告诉我。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
凊风
发表于 2024-4-16 08:45:20
FishC 发表于 2024-4-16 08:32
感谢提供完整的代码。根据您提供的代码,出错的原因在于`get_prefix()`函数的实现问题。在您给出的代码 ...
这样修改后,程序未建立E:\Temp\代码库.xlsx,也没有爬取数据。。。。
FishC
发表于 2024-4-16 08:45:35
凊风 发表于 2024-04-16 08:45
这样修改后,程序未建立E:\Temp\代码库.xlsx,也没有 ...
非常抱歉,我犯了一个低级错误。在 `spider_next` 函数的最后,我忘记将抓取到的数据添加到 `sheet` 中了。请将以下代码行添加到 `spider_next` 函数的最后:
sheet.append()
这样就会将抓取到的数据添加到表格中了。修复后的完整代码如下:
from openpyxl import Workbook
import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse
# 获取网页内容
def get_html(url):
while True:
try:
res = requests.get(url, 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):
parsed_url = urlparse(url)
prefix = f"{parsed_url.scheme}://{parsed_url.netloc}"
return prefix
# 递归抓取下一页面
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
item_td_name = item_td
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()
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")
province_code = href + "0000000000"
province_name = province.text
# 输出:级别、区划代码、名称
content = "1\t" + province_code + "\t" + province_name
print(content)
sheet.append()
spider_next(get_prefix(province_url) + href, 2, sheet)
# 保存xlsx文件
wb.save(r'E:\Temp\代码库.xlsx')
finally:
wb.close()
现在再次运行程序时,你应该能够成功地抓取数据并将其保存到 `E:\Temp\代码库.xlsx` 文件中。如果还有其他问题,请随时告诉我。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
凊风
发表于 2024-4-16 08:47:20
FishC 发表于 2024-4-16 08:45
非常抱歉,我犯了一个低级错误。在 `spider_next` 函数的最后,我忘记将抓取到的数据添加到 `sheet` 中 ...
这句sheet.append()在原代码段中是有的。。。
FishC
发表于 2024-4-16 08:47:37
凊风 发表于 2024-04-16 08:47
这句sheet.append()在原代码段中是有的。。。
非常抱歉,我犯了一个低级错误。是我在回答中遗漏了将抓取到的数据添加到 `sheet` 中的代码。你可以在 `spider_next` 函数的最后添加以下代码:sheet.append()这样就会将抓取到的数据添加到表格中了。修复后的完整代码如下:from openpyxl import Workbookimport requestsfrom bs4 import BeautifulSoupfrom urllib.parse import urlparse# 获取网页内容def get_html(url): while True: try: res = requests.get(url, 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): parsed_url = urlparse(url) prefix = f"{parsed_url.scheme}://{parsed_url.netloc}" return prefix# 递归抓取下一页面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 item_td_name = item_td 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()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") province_code = href + "0000000000" province_name = province.text # 输出:级别、区划代码、名称 content = "1\t" + province_code + "\t" + province_name print(content) sheet.append() spider_next(get_prefix(province_url) + href, 2, sheet) # 保存xlsx文件 wb.save(r'E:\Temp\代码库.xlsx') finally: wb.close()现在再次运行程序时,你应该能够成功地抓取数据并将其保存到 `E:\Temp\代码库.xlsx` 文件中。如果还有其他问题,请随时告诉我。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
凊风
发表于 2024-4-16 08:56:03
FishC 发表于 2024-4-16 08:47
非常抱歉,我犯了一个低级错误。是我在回答中遗漏了将抓取到的数据添加到 `sheet` 中的代码。你可以在...
请问folder_path = QFileDialog.getExistingDirectory(
self, "请指定文件夹", "", QFileDialog.ShowDirsOnly)
这个QFileDialog的大小、位置可以设定吗?
FishC
发表于 2024-4-16 08:56:16
凊风 发表于 2024-04-16 08:56
请问folder_path = QFileDialog.getExistingDirectory ...
是的,QFileDialog的大小和位置可以进行设定。你可以使用`setGeometry`方法来设置它的位置和大小,例如:= QFileDialog.getExistingDirectory(self, "请指定本次查询数据即将存入的文件夹", "", QFileDialog.ShowDirsOnly)dialog = QFileDialog()dialog.setGeometry(100, 100, 500, 500)在上面的代码中,`setGeometry(100, 100, 500, 500)`将设置QFileDialog的左上角在屏幕上的位置为(100, 100),宽度为500,高度为500。你可以根据需要调整这些参数来满足你的要求。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
凊风
发表于 2024-4-16 09:03:25
FishC 发表于 2024-4-16 08:56
是的,QFileDialog的大小和位置可以进行设定。你可以使用`setGeometry`方法来设置它的位置和大小,例如 ...
这样修改代码后,QFileDialog的大小、位置都没有改变,还是原大小、原位置。
FishC
发表于 2024-4-16 09:03:43
凊风 发表于 2024-04-16 09:03
这样修改代码后,QFileDialog的大小、位置都没有改变 ...
非常抱歉,我在之前的回答中给出了错误的解决方案。实际上,QFileDialog是一个模态对话框,其大小和位置无法直接通过setGeometry方法进行设置。如果你需要自定义FileDialog的界面,可能需要考虑使用Qt的其他类来创建自定义的文件选择对话框。
一种解决方案是使用QDialog类来创建一个自定义的对话框,然后在其中添加一个QFileDialog作为其子部件,并在自定义的对话框中对其进行布局和调整大小和位置。下面是一个简单的示例代码:
from PyQt6.QtWidgets import QApplication, QDialog, QFileDialog
class CustomFileDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
# 创建QFileDialog作为子部件
self.file_dialog = QFileDialog(self)
# 设置QFileDialog的属性(例如:默认打开的目录)
self.file_dialog.setDirectory("path/to/directory")
# 在自定义对话框中布局QFileDialog
layout = QVBoxLayout()
layout.addWidget(self.file_dialog)
self.setLayout(layout)
# 设置对话框的大小和位置
self.setGeometry(100, 100, 500, 500)
if __name__ == "__main__":
app = QApplication([])
dialog = CustomFileDialog()
dialog.exec()
在这个示例中,我们创建了一个CustomFileDialog类继承自QDialog,将QFileDialog作为子部件添加到自定义对话框中,并在对话框中进行布局和设置大小和位置。你可以根据需要进一步自定义CustomFileDialog类,例如添加其他的按钮或文本框等。
希望这次的回答能够解决你的问题,如果还有其他疑问,请随时向我提问!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
凊风
发表于 2024-4-16 09:06:54
FishC 发表于 2024-4-16 09:03
非常抱歉,我在之前的回答中给出了错误的解决方案。实际上,QFileDialog是一个模态对话框,其大小和位 ...
能不能定义成一个可以传大小、坐标、进去的QFileDialog函数,方便以后调用?
FishC
发表于 2024-4-16 09:07:02
凊风 发表于 2024-04-16 09:06
能不能定义成一个可以传大小、坐标、进去的QFileDialo ...
当然可以!你可以定义一个函数,它接受大小、位置等参数,并创建一个自定义的QFileDialog。下面是一个示例代码:from PyQt6.QtWidgets import QApplication, QDialog, QFileDialogdef show_custom_file_dialog(directory, size, position): app = QApplication([]) dialog = QDialog() dialog.setWindowTitle("Custom File Dialog") dialog.setGeometry(*position, *size) dialog.file_dialog = QFileDialog(dialog) dialog.file_dialog.setDirectory(directory) layout = QVBoxLayout() layout.addWidget(dialog.file_dialog) dialog.setLayout(layout) dialog.exec()使用这个函数,你可以在其他地方调用它来创建一个自定义的文件对话框,并传递目录、大小和位置等参数。例如:if __name__ == "__main__": directory = "path/to/directory" size = (500, 500) position = (100, 100) show_custom_file_dialog(directory, size, position)在这个示例中,我们首先定义了一个show_custom_file_dialog函数,它接受目录、大小和位置等参数。在函数内部,我们创建了一个QDialog作为父窗口,然后在这个对话框中布局一个QFileDialog,并根据传递的参数设置对话框的大小和位置。最后,我们调用exec方法来显示对话框。希望这个示例代码能够满足你的需求,如果还有其他问题,请随时提问!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
1
2
3
[4]
5
6
7
8
9
10
11