Selenium爬取密码页数据存入Dictionary遇空引用异常求助
解决字典填充时的空引用异常问题
核心错误原因
- 未实例化实体对象:你在向字典添加项时,直接写了
Params_Rezervace(类名),而非创建该类的实例,导致字典中对应键的取值为null,后续赋值时触发空引用异常。 - 类名称不匹配:自定义实体类名为
Params_Rezervation,但字典声明的是Dictionary<int, Params_Rezervace>,名称拼写不一致(RezervationvsRezervace),这会导致编译错误,需先统一名称。
额外需要注意的潜在问题
- 表头行干扰:表格第一行通常是表头(用
<th>标签),数据行则用<td>,遍历所有<tr>会包含表头,可能导致数据格式不匹配。 - 列索引越界:直接访问
columns[0]到columns[5]前,需确保列数足够,避免索引越界异常。 - 元素加载延迟:登录后页面可能未完全加载,直接查找元素会导致找不到目标节点。
修正后的代码
第一步:统一实体类名称
将字典的泛型类型和实体类名称统一,比如都使用Params_Rezervation:
public static Dictionary<int, Params_Rezervation> rezervace_data = new Dictionary<int, Params_Rezervation>();
第二步:修正数据填充方法
public static void LoadReservation() { var chromeOptions = new ChromeOptions(); chromeOptions.AddArguments("--headless"); var chromeDriverService = ChromeDriverService.CreateDefaultService(); chromeDriverService.HideCommandPromptWindow = true; try { using (var browser = new ChromeDriver(chromeDriverService, chromeOptions)) { browser.Navigate().GoToUrl("specific website"); // 执行登录操作 browser.FindElement(By.Id("pwbox-580")).SendKeys("password"); browser.FindElement(By.Name("Submit")).Click(); // 添加隐式等待,确保页面元素加载完成 browser.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10); IWebElement tableElement = browser.FindElement(By.XPath("//*[@id=\"post-580\"]/div/div[2]/table")); IList<IWebElement> rows = tableElement.FindElements(By.XPath(".//tr")); int number = 0; // 跳过表头行(假设第一行是表头) foreach (IWebElement row in rows.Skip(1)) { // 数据行的列使用<td>标签,而非<th> IList<IWebElement> columns = row.FindElements(By.XPath(".//td")); // 检查列数是否符合要求,避免索引越界 if (columns.Count < 6) { continue; } // 实例化实体对象,赋值后再添加到字典 var reservation = new Params_Rezervation(); reservation.Time = columns[0].Text; reservation.Guests = columns[1].Text; reservation.Name = columns[2].Text; reservation.Email = columns[3].Text; reservation.Text = columns[4].Text; reservation.Table = columns[5].Text; rezervace_data.Add(number, reservation); number++; } } } catch (Exception ex) { MessageBox.Show($"Error while loading data! \n{ex}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
关键修改点说明
- 实例化实体对象:先创建
Params_Rezervation的实例,完成属性赋值后再添加到字典,从根源避免空引用。 - 统一类名:确保字典泛型类型与实体类名称一致,解决编译阶段的类型不匹配问题。
- 跳过表头:用
Skip(1)跳过第一行表头,只处理数据行。 - 修正列标签查询:数据行的列使用
<td>标签,替换原有的<th>查询。 - 添加列数检查:避免因列数不足导致的索引越界异常。
- 添加等待机制:隐式等待确保页面元素加载完成后再执行查找操作。
内容的提问来源于stack exchange,提问作者TriXcze
相关产品推荐
相关产品推荐

