for循环中urlopen重复调用异常:仅爬取初始页面未跳转下一页
嘿,你遇到的重复爬取初始页面的问题,和urlopen本身完全无关,是代码里的语法错误和逻辑漏洞导致的!我帮你拆解一下问题根源,再给你修正后的解决方案:
问题出在哪?
错误的
finally块位置
在Python里,finally必须紧紧跟在try-except或try-else结构后面,不能在中间插入其他代码。你现在在try块结束后写了NumOfCrawledPages +=1和Url= URL_Next,才加finally,这会直接触发语法错误(如果你的代码真的运行无报错,大概率是粘贴时格式乱了)。就算侥幸运行,也会打乱执行顺序,导致Url的赋值逻辑失效。混乱的URL赋值逻辑
你在循环里既用if-else分支设置Url,又在循环末尾手动给Url赋值,这种重复操作很容易导致逻辑冲突。如果下一页链接提取失败,URL_Next没被正确更新,下一次循环就会继续用初始URL。脆弱的下一页链接提取
你用page_soup.findAll("li", {"class": "next"})[0].contents[0].get("href")提取下一页链接,太依赖固定的DOM层级了——只要页面里多了个空格、换行或者嵌套标签,这行代码就会出问题,导致URL_Next无法更新。
修正后的代码
import re from math import ceil from urllib.request import urlopen as uReq, Request from bs4 import BeautifulSoup as soup InitUrl = "https://mtgsingles.gr/search?q=" NumOfCrawledPages = 0 current_url = InitUrl # 用单一变量跟踪当前要爬的URL,避免混淆 NumOfPages = 5 for i in range(NumOfPages): print(f"正在爬取第 {i+1} 页...") try: # 发起请求并解析页面 UClient = uReq(current_url) page_html = UClient.read() UClient.close() page_soup = soup(page_html, "html.parser") cards = page_soup.findAll("div", {"class": ["iso-item", "item-row-view"]}) # 提取卡片信息,增加异常处理避免中断 for card in cards: # 提取卡片名称 try: card_name = card.div.div.strong.span.contents[3].contents[0].replace("\xa0 ", "") except (IndexError, AttributeError): card_name = "无法获取卡片名称" # 提取P/T信息 cardP_T = "Does not exist" if len(card.div.contents) > 3: try: cardP_T = card.div.contents[3].contents[1].text.replace("\n", "").strip() except (IndexError, AttributeError): pass # 提取卡片类型 try: cardType = card.contents[3].text except (IndexError, AttributeError): cardType = "无法获取卡片类型" print(f"{card_name}\n{cardP_T}\n{cardType}\n") # 优化下一页链接提取,更健壮 next_li = page_soup.find("li", {"class": "next"}) if next_li and next_li.a: current_url = "https://mtgsingles.gr" + next_li.a.get("href") print(f"下一页URL: {current_url}\n") else: print("没有更多页面了,提前结束爬取\n") break # 没有下一页就跳出循环,避免无效循环 except Exception as e: print(f"爬取第 {i+1} 页时出错: {str(e)}\n") break NumOfCrawledPages += 1 print(f"准备爬取第 {NumOfCrawledPages + 1} 页\n") print(f"爬取完成,共爬取 {NumOfCrawledPages} 页")
关键改进点
- 移除了错误的
finally结构,改用更清晰的异常处理,避免语法错误。 - 用
current_url单一变量跟踪当前爬取地址,彻底解决URL赋值混乱的问题。 - 给卡片信息提取增加了异常捕获,就算页面结构有小变化,程序也不会直接崩溃。
- 优化了下一页链接的提取逻辑,用
find替代findAll,并检查标签是否存在,更健壮。 - 增加了提前终止循环的逻辑,当没有下一页时直接跳出,避免无效的循环次数。
内容的提问来源于stack exchange,提问作者Petris
相关产品推荐
相关产品推荐

