获取2023年12月数据失败: cannot access local variable 'headers' where it is not associated with a value --------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) Cell In[3], line 61 58 beijing_code = "101010100" 59 year = 2023 ---> 61 weather_df = get_weather_data(beijing_code, year) 63 # 数据清洗 64 weather_df = weather_df.dropna() # 删除空行 Cell In[3], line 48, in get_weather_data(city_code, year) 45 print(f"获取{year}年{month}月数据失败: {e}") 47 # 创建DataFrame ---> 48 df = pd.DataFrame(all_data, columns=headers) 49 return df UnboundLocalError: cannot access local variable 'headers' where it is not associated with a value
时间: 2025-06-17 15:13:01 浏览: 21
<think>我们注意到错误信息:UnboundLocalError:cannotaccesslocalvariable'headers'whereitisnotassociatedwithavalue这个错误通常发生在函数内部试图访问一个局部变量,但在访问之前该变量并没有被赋值。在我们的爬虫代码中,函数`get_weather_data`内部使用了变量`headers`,但是这个变量是在函数外部定义的,而在函数内部并没有定义,也没有通过参数传递进来。解决方案:1.将`headers`作为参数传递给函数`get_weather_data`。2.或者在函数内部重新定义`headers`。我们更推荐第一种方法,因为这样可以让函数更加独立和可配置。修改后的代码:在函数定义中添加`headers`参数,并在调用函数时传入。具体修改如下:原函数定义:defget_weather_data(city_code,year):修改为:defget_weather_data(city_code,year,headers):在调用函数时,传入headers:weather_df=get_weather_data(beijing_code,year,headers)另外,我们也可以考虑将headers定义在函数内部,但这样不够灵活(比如更换User-Agent时需要修改函数)。因此,作为参数传入是更好的选择。下面我们修改之前的代码示例:```pythonimportrequestsfrombs4importBeautifulSoupimportpandasaspdimporttimedefget_weather_data(city_code,year,headers):#修改1:添加headers参数"""获取指定城市一年的天气数据:paramcity_code:城市代码(如北京101010100):paramyear:年份(如2023):paramheaders:请求头:return:包含天气数据的DataFrame"""all_data=[]formonthinrange(1,13):#构造月度URLurl=f"http://www.weather.com.cn/history/{city_code}/month/{year}{month:02d}.html"try:response=requests.get(url,headers=headers)#这里使用传入的headersresponse.encoding='utf-8'soup=BeautifulSoup(response.text,'html.parser')#定位数据表格table=soup.find('table',class_='tqtongji2')ifnottable:continue#提取表头headers_row=[th.get_text(strip=True)forthintable.find('tr').find_all('th')]#提取每日数据forrowintable.find_all('tr')[1:]:row_data=[td.get_text(strip=True)fortdinrow.find_all('td')]#补全年份信息iflen(row_data)>0androw_data[0]:#将日期格式化为年-月-日day=row_data[0].replace('日','')row_data[0]=f"{year}-{month:02d}-{day.zfill(2)}"#确保日是一位数时前面补0all_data.append(row_data)print(f"已获取{year}年{month}月数据")time.sleep(1)#避免请求过快exceptExceptionase:print(f"获取{year}年{month}月数据失败:{e}")#创建DataFramedf=pd.DataFrame(all_data,columns=headers_row)returndfif__name__=="__main__":#定义请求头headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/91.0.4472.124Safari/537.36'}beijing_code="101010100"year=2023#调用时传入headersweather_df=get_weather_data(beijing_code,year,headers)#数据清洗(根据实际情况调整)ifnotweather_df.empty:weather_df=weather_df.dropna(how='all')#删除全为空的行#转换日期列weather_df['日期']=pd.to_datetime(weather_df['日期'],errors='coerce')#删除转换失败的日期行weather_df=weather_df.dropna(subset=['日期'])#保存为CSVweather_df.to_csv(f"北京_{year}年天气数据.csv",index=False,encoding='utf_8_sig')print(f"数据已保存至北京_{year}年天气数据.csv")else:print("未获取到数据")```注意:在函数内部,我们为了避免和参数`headers`冲突,将表格的表头变量名改为了`headers_row`(原变量名为`headers`),这样就不会和参数headers冲突。另外,我们还对日期格式做了一些调整,确保日是一位数时补0(例如1日变成01),这样在转换为日期格式时不会出错。通过以上修改,函数内部就可以正确访问到headers变量了,因为它是作为参数传入的。如果问题仍然存在,请检查:1.函数调用时是否确实传入了headers。2.headers变量在函数调用前是否已经正确定义。这样修改后,应该可以解决UnboundLocalError错误。§§相关问题§§1.如何解决Python函数中的变量作用域问题?2.除了传递参数,还有哪些方法可以避免UnboundLocalError?3.如何调试Python爬虫中的变量未定义错误?4.在爬虫中如何处理动态变化的请求头?5.如何验证请求头是否在爬虫请求中生效?</think>### 解决爬虫中的 UnboundLocalError: cannot access local variable 'headers' 错误
这个错误发生在 Python 尝试访问一个局部变量 `headers`,但在当前作用域中该变量尚未被赋值。以下是完整的解决方案:
#### 问题原因分析
1. **变量作用域问题**:在函数内部访问外部作用域定义的变量时,Python 会将其视为局部变量
2. **赋值位置错误**:函数内部尝试使用 `headers` 前未进行赋值
3. **全局变量访问限制**:函数内部访问外部变量需使用 `global` 声明或通过参数传递
#### 解决方案代码
```python
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
def get_weather_data(city_code, year, headers): # 解决方案1:添加headers参数
"""
获取指定城市一年的天气数据
:param city_code: 城市代码
:param year: 年份
:param headers: 请求头
:return: 包含天气数据的DataFrame
"""
all_data = []
# 解决方案2:确保headers在函数内部已定义
if not headers:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
for month in range(1, 13):
url = f"http://www.weather.com.cn/history/{city_code}/month/{year}{month:02d}.html"
try:
response = requests.get(url, headers=headers) # 正确使用headers
# ... 其余代码不变 ...
except Exception as e:
print(f"获取{year}年{month}月数据失败: {e}")
# ... 数据处理代码 ...
if __name__ == "__main__":
# 解决方案3:定义全局headers并传递给函数
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
beijing_code = "101010100"
year = 2023
# 传递headers参数
weather_df = get_weather_data(beijing_code, year, headers)
# ... 数据保存代码 ...
```
#### 三种解决方法详解
1. **最佳实践:添加函数参数(推荐)**
```python
def get_weather_data(city_code, year, headers): # 添加headers参数
# 函数内部直接使用headers
response = requests.get(url, headers=headers)
```
2. **使用全局变量声明**
```python
def get_weather_data(city_code, year):
global headers # 声明使用全局变量
# 函数内部直接使用headers
```
3. **函数内部重新定义**
```python
def get_weather_data(city_code, year):
# 在函数开头定义headers
headers = {
'User-Agent': 'Mozilla/5.0...'
}
# 使用headers
```
#### 避免此错误的编程技巧
1. **明确变量作用域**:函数内部变量优先使用参数传递
2. **变量初始化**:在函数开头初始化所有局部变量
3. **避免全局变量**:除非必要,否则使用参数传递代替全局变量
4. **异常处理**:添加变量存在性检查
```python
if 'headers' not in locals():
headers = default_headers
```
#### 数学原理说明
在编程中的作用域规则类似于数学中的函数作用域:
$$f(x) = \int_{a}^{b} g(x,y) \,dy$$
这里 $x$ 是外部变量,$y$ 是局部变量。类似地,在Python中:
- 外部变量需显式传递到函数内部
- 内部变量只在函数作用域有效[^4]
阅读全文
相关推荐








