身为Python程序员的你,有了这个,再也不怕“成语接龙红包“抢不到了
作者:互联网
成语接龙是中华民族传统的文字游戏,它有着悠久的历史,也有广泛的社会基础,是老少皆宜的民间文化娱乐活动!一般聚会时会玩这个游戏做互动,还有就是QQ有一个成语接龙红包,有时会因为自己的成语储备量不够,而接不下去。
那么大家有没有想过自己去实现一个成语接龙的程序呢?接下来,我就用Python来实现一个成语接龙小程序,废话不多说,开始~~~~
成语准备
说到成语接龙,首先就得保证拥有足够多的成语,这个条件就不满足,我没有成语哎,散会~
开玩笑,身为一个Python码农,爬个数据还是没啥子问题的,没有成语不要紧,有办法,
我发现了一个网站:chengyu.t086.com/list/A_1.ht…, 这个网站上有很多的成语及解释啥的,废话不多说,我都给它爬下来。
分析爬取思路:
通过网页抓包,分析出以下特点:每次请求都会发出:http://chengyu.t086.com/list/{A-Z}_{页码}.html
这个请求,如下图,是首字母为A的第一页。
解析网页有“下一页”时,循环翻页,例如从 chengyu.t086.com/list/A_1.ht… 翻页至 chengyu.t086.com/list/A_2.ht…, 当解析网页解析不到“下一页”时,就要请求拼音首字母的下一个chengyu.t086.com/list/B_1.ht…, 依次循环下去,直至爬完。
这样就是有两层循环,第一层循环A-Z,第二层循环页码,然后拼成http://chengyu.t086.com/list/{A-Z}_{页码}.html
去请求,没有下一页时,就跳出第二层循环,循环下一个拼音首字母。
如下标记的内容即为成语具体信息的跳转链接,去发请求该链接的话,返回来的是该成语的释意等具体信息。也是我们需要的,需要爬下来。
代码如下:
import requests
from bs4 import BeautifulSoup
class Idiom:
def __init__(self):
self.num = 0
self.url = 'http://chengyu.t086.com/list/{}_{}.html'
self.url_info = 'http://chengyu.t086.com/{}'
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/81.0.4044.43 Safari/537.36',
'Referer': 'http://chengyu.t086.com/'
}
self.all_idiom = {}
self.pinyin_initials = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S'
, 'T', 'W', 'X', 'Y', 'Z']
def idiom_spider(self):
"""
爬取所有成语
"""
idiom_list = []
for initial in self.pinyin_initials:
page = 1
while True:
url = self.url.format(initial, page)
print(url)
start_html = requests.get(url, headers=self.headers)
start_html.encoding = 'gb18030'
soup = BeautifulSoup(start_html.text, "html.parser")
# 查找所有class=listw的div
listw = soup.find('div', class_='listw')
a2 = soup.find("div", class_="a2")
# 查找所有的a标签
lista = listw.find_all('a')
lastpage = a2.find_all('a')
for p in lista:
print("词语", p.text)
print((p["href"]))
info_url = self.url_info.format(p["href"])
print("infourl", info_url)
info_html = requests.get(info_url, headers=self.headers)
info_html.encoding = 'gb18030'
soup = BeautifulSoup(info_html.text, "html.parser")
# 查找所有td标签
td_list = soup.findAll('td')
# 成语释意
print("含义:", td_list[5].text)
new_idiom = {"idiom": p.text, "paraphrase": td_list[5].text, "first_pinxin":initial}
idiom_list.append(new_idiom)
if not lastpage or str(lastpage[-1]).find("下一页") == -1: # 如果没有下一页的超链接标签,break
break
page += 1
idiom = Idiom()
idiom.idiom_spider()
运行过程图:
可以按照自己的需求把成语存为指定格式,我是把所有成语存到了sqlite3
数据库,因为Python就内置了sqlite3
数据库,所以,在Python中使用sqlite3
,不需要安装任何东西,可以方便直接使用,总共爬取成语30880条,可能不全,但是也够用了。
成语接龙程序
实现原理其实不说,大家也可能已经想到了,就是根据刚才爬取的成语,与指定成语进行字符串首尾条件匹配,如果拼音可以匹配上,就是接龙成功了。
判断拼音是否相同,在Python中有一个第三方库pypinyin
,可以使用pip install pypinyin
进行安装。 使用下面代码可以获取指定汉字的拼音:
from pypinyin import lazy_pinyin
print(lazy_pinyin("全菜工程师"))
结果为:['quan', 'cai', 'gong', 'cheng', 'shi']
,是一个列表。 下面我将成语接龙程序分解:
判断是否为成语
逻辑很简单,就是查询指定字符串是否在爬取的成语库里,在则为成语,不在则不是:
说到查询成语库,刚才爬取的成语我是放在了sqlite3
数据库之中,那下面为Python连接sqlite3
代码,为了方便使用,提取出来:
import sqlite3
def sqlite_conn():
try:
conn = sqlite3.connect('meta.db')
return conn
except Exception as e:
print(e)
那么,判断是否为成语的代码如下:
def idiom_exist(user_idiom):
"""
查询指定成语是否在成语库中
:param user_idiom: string
:return: bool
"""
cursor = sqlite_conn().cursor()
db_res = cursor.execute("SELECT id, idiom, paraphrase, first_pinxin from idiom where idiom='{}'".format(user_idiom))
for idiom in db_res:
if idiom[1]:
return True
return False
接龙
接龙也很简单,根据用户输入成语,获取该成语尾字拼音首字母,根据拼音首字母查询成语库中符合条件的成语,在判定这些成语的首字拼音是否和用户输入的尾字拼音相同,在符合条件的成语中,随机返回一个即可:
def solitaire(user_idiom):
"""
返回成语及含义
:param user_idiom: 用户输入的成语
:return: 返回成语及含义
"""
cursor = sqlite_conn().cursor()
# 如果没有指定需要接龙的成语,则随机挑选一个返回即可
if not user_idiom:
random_num = random.randint(1, 30880)
random_idiom = cursor.execute("SELECT id, idiom, paraphrase, first_pinxin from idiom where id={}".format(random_num))
for idiom in random_idiom:
return idiom[1], idiom[2]
player = lazy_pinyin(user_idiom)[-1][0].upper() # 获取玩家输入的最后一个拼音首字母
db_idiom = cursor.execute(
"SELECT id, idiom, paraphrase, first_pinxin from idiom where first_pinxin='{}'".format(player))
chioce_idiom = [] # 可供选择的成语
for idiom in db_idiom:
if lazy_pinyin(user_idiom)[-1] == lazy_pinyin(idiom[1])[0]:
chioce_idiom.append([idiom[1], idiom[2]])
if not chioce_idiom:
return None, None
return random.choice(chioce_idiom)[0], random.choice(chioce_idiom)[1]
判断用户接龙是否正确
逻辑是先查询用户输入是否为成语,如果是,再判断其是否符合接龙规则,比较简单:
def judge(bot_idiom, user_idiom):
if lazy_pinyin(user_idiom)[0] == lazy_pinyin(bot_idiom)[-1]:
return True
return False
至此,成语接龙核心代码,已经完成,为了交互友好,写了一个交互函数,由于代码篇幅过长,这里只贴截图:
在交互函数中,加入了先后手选择,可以选择先手或者后手,以及记忆集合,用于判断成语是否被重复使用,还加了能接龙10次就成功的机制。
下面展示运行截图:
可以看出,程序可能没有特别完美,单已经很好的实现了预期,对战了几把,由于我的成语储备量不高,统统以失败告终,感兴趣的同学可以试一下,看看你能不能行,哈哈哈。
总结
之前的文章总是以知识点
的形式输出,我发现,写多了往往就成了知识点总结,自己看来都没有什么趣味性,提不起阅读兴趣,以后尽量在自己的文章中加入一些趣味性的东西,也算是提升自己的写作能力了,加油!!
标签:idiom,Python,self,list,程序员,html,接龙,成语 来源: https://blog.csdn.net/weixin_50097774/article/details/121405472