解决configparser读取的BeautifulSoup规则为字符串导致find失效的问题
解决从配置文件读取BeautifulSoup find规则(元组+字典)的问题
我懂你遇到的问题了——从config.ini里读出来的规则是字符串格式的'h1', {'class': 'title'},但BeautifulSoup的find()需要的是实打实的Python元组(包含字符串和字典对象),不是字符串字面量。下面给你几个靠谱的解决办法:
方法1:用ast.literal_eval()安全解析字符串为Python对象
这是最推荐的方式,它专门用来解析字符串形式的Python字面量(元组、字典、列表等),而且比eval()安全得多,不会执行恶意代码。
修改你的get_rule()方法:
import ast import configparser def get_rule(self): config = configparser.ConfigParser() config.read(path) title_rule_str = config.get(self.site_name, "title") # 把字符串解析成实际的元组 self.title_rule = ast.literal_eval(title_rule_str) return self.title_rule
配置文件config.ini保持不变:
[pravda.ru] title = 'h1', {'class': 'title'}
解析完成后,self.title_rule就会变成真正的元组('h1', {'class': 'title'}),调用find()时记得用*解包元组(把元组拆成find()需要的两个参数):
def get_title(self): title = self.get_page.find(*self.title_rule).text return textwrap.fill(title, width=79)
方法2:拆分配置项为单独的标签和属性字段
如果你觉得用ast.literal_eval()有点“黑魔法”,可以把配置拆成两个独立字段,分别存储标签名和属性字典,更直观易懂:
修改config.ini:
[pravda.ru] title_tag = h1 title_attrs = {"class": "title"}
对应修改get_rule()方法:
import ast import configparser def get_rule(self): config = configparser.ConfigParser() config.read(path) tag = config.get(self.site_name, "title_tag") attrs_str = config.get(self.site_name, "title_attrs") attrs = ast.literal_eval(attrs_str) self.title_rule = (tag, attrs) return self.title_rule
同样调用时用*self.title_rule解包参数即可。
方法3:手动解析字符串(不推荐,易出错)
如果你不想用ast模块,也可以手动拆分字符串,但这种方法要处理很多边缘情况(比如字符串里包含逗号、引号的场景),很容易出bug,仅作参考:
def get_rule(self): config = configparser.ConfigParser() config.read(path) title_rule_str = config.get(self.site_name, "title").strip() # 拆分标签和属性部分(仅按第一个逗号拆分) tag_part, attrs_part = title_rule_str.split(',', 1) # 清理标签字符串的引号和空格 tag = tag_part.strip().strip("'\"") # 解析属性字符串为字典(依然建议用ast.literal_eval代替eval) attrs = ast.literal_eval(attrs_part.strip()) self.title_rule = (tag, attrs) return self.title_rule
⚠️ 注意:绝对不要用eval()替代ast.literal_eval(),eval()会执行任何传入的代码,若配置文件内容不可信,会有安全风险。
内容的提问来源于stack exchange,提问作者Pavel Shturm
相关产品推荐
相关产品推荐

