python-3.x - 通过创建单独的函数来解决 try-except 以应用于单行中的许多语句
问题描述
我正在从https://www.dictionary.com/网站上抓取字典数据。目的是从字典页面中删除不需要的元素并将它们离线保存以供进一步处理。由于网页有些非结构化,因此可能存在也可能不存在以下代码中提到的要删除的元素;缺少元素会产生异常(在片段 2 中)。而且由于在实际代码中,有许多元素要删除,它们可能存在或不存在,如果我们将 应用于每个这样的语句,代码行数将急剧增加。try - except
因此,我正在通过为try - except
(在代码片段 3 中)创建一个单独的函数来解决这个问题,这是我从这里得到的想法。但是我无法让代码片段 3 中的代码像命令一样工作,例如soup.find_all('style')
返回None
应该返回style
类似于片段 2 的所有标签列表的位置。我无法直接应用引用的解决方案,因为有时我必须达到预期通过引用其parent
或sibling
等间接删除元素soup.find('h2',{'class':'css-1iltn77 e17deyx90'}).parent
Snippet 1 用于设置代码执行的环境。
如果您能提供一些建议以使代码段 3 正常工作,那就太好了。
片段1(设置执行代码的环境):
import urllib.request
import requests
from bs4 import BeautifulSoup
import re
headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',}
folder = "dictionary_com"
片段2(工作):
def makedefinition(url):
success = False
while success==False:
try:
request=urllib.request.Request(url,headers=headers)
final_url = urllib.request.urlopen(request, timeout=5).geturl()
r = requests.get(final_url, headers=headers, timeout=5)
success=True
except:
success=False
soup = BeautifulSoup(r.text, 'lxml')
soup = soup.find("section",{'class':'css-1f2po4u e1hj943x0'})
# there are many more elements to remove. mentioned only 2 for shortness
remove = soup.find_all("style") # style tags
remove.extend(safe_execute(soup.find('h2',{'class':'css-1iltn77 e17deyx90'}).parent)) # related content in the page
for x in remove: x.decompose()
return(soup)
# testing code on multiple urls
#url = "https://www.dictionary.com/browse/a"
#url = "https://www.dictionary.com/browse/a--christmas--carol"
#url = "https://www.dictionary.com/brdivowse/affection"
#url = "https://www.dictionary.com/browse/hot"
#url = "https://www.dictionary.com/browse/move--on"
url = "https://www.dictionary.com/browse/cuckold"
#url = "https://www.dictionary.com/browse/fear"
maggi = makedefinition(url)
with open(folder+"/demo.html", "w") as file:
file.write(str(maggi))
片段3(不工作):
soup = None
def safe_execute(command):
global soup
try:
print(soup) # correct soup is printed
print(exec(command)) # this should print the list of style tags but printing None, and for related content this should throw some exception
return exec(command) # None is being returned for style
except Exception:
print(Exception.with_traceback())
return []
def makedefinition(url):
global soup
success = False
while success==False:
try:
request=urllib.request.Request(url,headers=headers)
final_url = urllib.request.urlopen(request, timeout=5).geturl()
r = requests.get(final_url, headers=headers, timeout=5)
success=True
except:
success=False
soup = BeautifulSoup(r.text, 'lxml')
soup = soup.find("section",{'class':'css-1f2po4u e1hj943x0'})
# there are many more elements to remove. mentioned only 2 for shortness
remove = safe_execute("soup.find_all('style')") # style tags
remove.extend(safe_execute("soup.find('h2',{'class':'css-1iltn77 e17deyx90'}).parent")) # related content in the page
for x in remove: x.decompose()
return(soup)
# testing code on multiple urls
#url = "https://www.dictionary.com/browse/a"
#url = "https://www.dictionary.com/browse/a--christmas--carol"
#url = "https://www.dictionary.com/brdivowse/affection"
#url = "https://www.dictionary.com/browse/hot"
#url = "https://www.dictionary.com/browse/move--on"
url = "https://www.dictionary.com/browse/cuckold"
#url = "https://www.dictionary.com/browse/fear"
maggi = makedefinition(url)
with open(folder+"/demo.html", "w") as file:
file.write(str(maggi))
解决方案
在代码段 3 中的代码中,您使用exec
内置方法,None
无论它使用其参数做什么,它都会返回。有关详细信息,请参阅此SO 线程。
补救措施:
用于exec
修改变量并返回它,而不是返回其exec
自身的输出。
def safe_execute(command):
d = {}
try:
exec(command, d)
return d['output']
except Exception:
print(Exception.with_traceback())
return []
然后像这样调用它:
remove = safe_execute("output = soup.find_all('style')")
编辑:
执行此代码后,再次None
返回。然而,在调试时,try
如果我们打印print(soup)
了正确的soup
值,则在部分内部,但exec(command,d)
给出NameError: name 'soup' is not defined
.
这种差异已通过使用eval()
代替来克服exec()
。定义的函数是:
def safe_execute(command):
global soup
try:
output = eval(command)
return(output)
except Exception:
return []
电话看起来像:
remove = safe_execute("soup.find_all('style')")
remove.extend(safe_execute("soup.find('h2',{'class':'css-1iltn77 e17deyx90'}).parent"))
推荐阅读
- mysql - 使用 MySQL 测试数据库的 Github 操作
- algorithm - 此 Word Break DFS + 记忆解决方案的时间复杂度
- python - 如何在python中用正斜杠替换方括号中的数字
- react-native - react-native init MyProject --version 0.58.6 但每次我这样做时,都会出现如下错误
- python - (discord.py) 冒充另一个用户
- ruby-on-rails - ROR - 如何将 rubygem 更新到特定版本?
- c# - 短跑、跳跃和主菜单不起作用
- javascript - 未捕获的 ReferenceError:未定义控制器
- python-3.x - PermissionError:[Errno 13] 权限被拒绝:无法保存 csv 文件
- php - 将值从 AJAx 传递到 PHP