前言
昨天投简历时遇到了这样的一个笔试。本以为会是数据结构算法之类的没想到直接发了一个word直接提需求,感觉挺有意思就写了这篇文章,感兴趣的朋友可以看看。
1. 网页内容解析
首先,我们通过请求网页获取到日本常用汉字的链接列表。然后,针对每个汉字链接,我们提取网页中相应部分的 HTML 内容。
首先分析页面结构
发现这些汉字有着相同的规律,先将.parts_box类标签拿到之后再用css选择器拿到对应的汉字标签.
url = 'https://kanji.jitenon.jp/cat/joyo.html'
response = requests.get(url)
response.encoding = 'utf-8'
html_content = response.text
css_selector = '#content > div.bushu_wrap > div > .parts_box '
parsed_elements = parse_css(html_content, css_selector)
urllist = []
for element in parsed_elements:
chineslinks = element.select(".search_parts > li > a")
for chineslink in chineslinks:
chines = {}
chines['link'] = chineslink['href']
chines['name'] = chineslink.text
urllist.append(chines)
首先,我用了Python的requests库发送了一个HTTP请求,抓取了目标网站的内容。然后,用了BeautifulSoup库进行HTML解析,找到了我需要的信息。通过一个简单的CSS选择器,我成功地定位到了汉字链接的位置。
接着,我遍历了这些链接,将它们逐个存储在了一个名为urllist的列表中。每个链接都包含着汉字的名称和对应的链接地址。
2.详情页解析
通过对比前两字可以发现每个字的介绍里的属性都有可能不一样,因此这里的思路是先拿到这部分标签的整体text,然后通过正则去进行筛选匹配。在进行字符拼接时加上分隔符,为之后的对转成列表形式时的字符分割做准备。
def get_detailed(chines):
url = chines['link']
response = requests.get(url)
response.encoding = 'utf-8'
html_content = response.text
css_selector = '#content > article > div.search_data > div > div.kanji_wrap > div.kanji_right > div > section > table >tbody > tr '
parsed_elements = parse_css(html_content, css_selector)
text = ''
separator = '%' # 定义分隔符
for element in parsed_elements:
# print(element.text)
text =text+ ' '.join(element.stripped_strings)+ separator
font = {}
font['name'] = chines['name']
#
# fontkey = element.select(".ruby_switch")[0].text
# fontvaule = element.select(".ruby_switch > span")
# print(fontkey)
# print(text)
def extract_text_between_patterns(text, start_patterns, end_patterns):
"""
从文本中提取两个模式之间的文本。
参数:
text (str): 待提取文本。
start_patterns (list): 匹配文本起始的模式列表。
end_patterns (list): 匹配文本结束的模式列表。
返回:
list: 匹配的文本列表,如果没有匹配项则返回None。
"""
matches = [] # 存储匹配结果的列表
for start_pattern in start_patterns:
for end_pattern in end_patterns:
# 查找所有起始模式的位置
start_matches = [match.end() for match in re.finditer(start_pattern, text)]
# 查找所有结束模式的位置
end_matches = [match.start() for match in re.finditer(end_pattern, text)]
# 遍历每个起始位置和结束位置的组合
for start_match in start_matches:
for end_match in end_matches:
if start_match < end_match: # 确保结束位置在起始位置之后
subtext = text[start_match:end_match] # 提取子文本
# 检查子文本中是否包含其他模式
if not any(pattern in subtext for pattern in start_patterns[1:] + end_patterns):
# 添加匹配的子文本到结果列表中,并保留第一个关键词
matches.append(text[text.find(start_pattern):end_match].strip())
break # 找到一个匹配后退出当前循环
return matches if matches else None # 返回匹配结果列表,如果列表为空则返回None
# 定义关键字列表
start_patterns = ['部首', '画数', '音 読 み', '訓 読 み', '意味', '成 り 立 ち', '種別', '分類', '学年', '漢字 検定', 'JIS 水準']
end_patterns = ['画数', '音 読 み', '訓 読 み', '意味', '成 り 立 ち', '種別', '分類', '学年', '漢字 検定', 'JIS 水準']
# 调用函数进行提取
results = extract_text_between_patterns(text, start_patterns, end_patterns)
# print(results)
# for i in range(len(results)):
# print(results[i])
def create_dict(data, patterns):
hanzi_dict = {}
for item in data:
for pattern in patterns:
if pattern in item:
key, value = item.split(pattern, 1)
hanzi_dict[pattern.strip()] = value.strip()
break
return hanzi_dict
# 测试
patterns = ['部首', '画数', '音 読 み', '訓 読 み', '意味', '成 り 立 ち', '種別', '分類', '学年', '漢字 検定', 'JIS 水準']
# 解析数据
hanzi_dict = create_dict(results, patterns)
# 遍历hanzi_dict
for key, value in hanzi_dict.items():
parts = hanzi_dict[key].split('%')
parts.pop() # 移除最后一个空字符串
if len(parts) == 1:
hanzi_dict[key] = str(parts[0])
continue
hanzi_dict[key] = parts
return hanzi_dict
汉字详情页解析函数 get_detailed
该函数的主要目的是解析汉字的详情页,从中提取出部首、画数、音读み等关键信息,并以字典的形式返回。
-
输入参数:
-
chines
:一个包含汉字链接和名称的字典,包括键'link'
和'name'
。
-
-
功能:
- 通过给定的链接获取汉字的详情页HTML内容。
- 使用CSS选择器定位到包含关键信息的元素。
- 提取目标信息并整理成字典格式。
-
详细步骤:
- 发送HTTP请求以获取详情页HTML内容,并将其编码为UTF-8格式。
- 使用预定义的CSS选择器来定位页面上包含关键信息的元素。
- 将解析得到的HTML元素提取出文本信息,并按照指定的分隔符连接成一个长字符串。
- 使用自定义的函数
extract_text_between_patterns
从长字符串中提取出具体信息,并整理成字典格式。 - 最后,返回包含关键信息的字典。
-
关键函数:
-
extract_text_between_patterns
:从长字符串中提取出具体信息的函数,它根据指定的起始和结束模式来匹配文本,并返回匹配的结果列表。
-
-
返回值:
- 一个字典,包含部首、画数、音读み等关键信息。
3.保存JSON
通过循环遍历urllist
中的每个汉字链接,然后调用get_detailed
函数来获取每个汉字的详细信息。获取到的信息被打印输出,并且添加到了名为ans
的列表中。
接着,将整个ans
列表保存为一个JSON文件,以便将获取到的汉字详细信息持久化存储下来。JSON文件的保存路径为当前目录下的ans.json
文件,并且使用UTF-8编码格式,以确保能够正确地保存包含非ASCII字符的内容。
ans = []
for chines in urllist:
chines = get_detailed(chines)
print(chines)
ans.append(chines)
# 将ans保存为json文件
with open('ans.json', 'w', encoding='utf-8') as f:
json.dump(ans, f, ensure_ascii=False, indent=4)