1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 身为Python程序员的你 有了这个 再也不怕“成语接龙红包“抢不到了

身为Python程序员的你 有了这个 再也不怕“成语接龙红包“抢不到了

时间:2020-07-01 16:22:11

相关推荐

身为Python程序员的你 有了这个 再也不怕“成语接龙红包“抢不到了

成语接龙是中华民族传统的文字游戏,它有着悠久的历史,也有广泛的社会基础,是老少皆宜的民间文化娱乐活动!一般聚会时会玩这个游戏做互动,还有就是QQ有一个成语接龙红包,有时会因为自己的成语储备量不够,而接不下去。

那么大家有没有想过自己去实现一个成语接龙的程序呢?接下来,我就用Python来实现一个成语接龙小程序,废话不多说,开始~~~~

成语准备

说到成语接龙,首先就得保证拥有足够多的成语,这个条件就不满足,我没有成语哎,散会~

开玩笑,身为一个Python码农,爬个数据还是没啥子问题的,没有成语不要紧,有办法,

我发现了一个网站:/list/A_1.ht…, 这个网站上有很多的成语及解释啥的,废话不多说,我都给它爬下来。

分析爬取思路:

通过网页抓包,分析出以下特点:每次请求都会发出:/list/{A-Z}_{页码}.html这个请求,如下图,是首字母为A的第一页。

解析网页有“下一页”时,循环翻页,例如从/list/A_1.ht…翻页至/list/A_2.ht…, 当解析网页解析不到“下一页”时,就要请求拼音首字母的下一个/list/B_1.ht…, 依次循环下去,直至爬完。

这样就是有两层循环,第一层循环A-Z,第二层循环页码,然后拼成/list/{A-Z}_{页码}.html去请求,没有下一页时,就跳出第二层循环,循环下一个拼音首字母。

如下标记的内容即为成语具体信息的跳转链接,去发请求该链接的话,返回来的是该成语的释意等具体信息。也是我们需要的,需要爬下来。

代码如下:

import requestsfrom bs4 import BeautifulSoupclass Idiom:def __init__(self):self.num = 0self.url = '/list/{}_{}.html'self.url_info = '/{}'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': '/'}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 = 1while 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的divlistw = 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: # 如果没有下一页的超链接标签,breakbreakpage += 1idiom = Idiom()idiom.idiom_spider()

运行过程图:

可以按照自己的需求把成语存为指定格式,我是把所有成语存到了sqlite3数据库,因为Python就内置了sqlite3数据库,所以,在Python中使用sqlite3,不需要安装任何东西,可以方便直接使用,总共爬取成语30880条,可能不全,但是也够用了。

成语接龙程序

实现原理其实不说,大家也可能已经想到了,就是根据刚才爬取的成语,与指定成语进行字符串首尾条件匹配,如果拼音可以匹配上,就是接龙成功了。

判断拼音是否相同,在Python中有一个第三方库pypinyin,可以使用pip install pypinyin进行安装。 使用下面代码可以获取指定汉字的拼音:

from pypinyin import lazy_pinyinprint(lazy_pinyin("全菜工程师"))

结果为:['quan', 'cai', 'gong', 'cheng', 'shi'],是一个列表。 下面我将成语接龙程序分解:

判断是否为成语

逻辑很简单,就是查询指定字符串是否在爬取的成语库里,在则为成语,不在则不是:

说到查询成语库,刚才爬取的成语我是放在了sqlite3数据库之中,那下面为Python连接sqlite3代码,为了方便使用,提取出来:

import sqlite3def sqlite_conn():try:conn = sqlite3.connect('meta.db')return connexcept 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 Truereturn 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, Nonereturn 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 Truereturn False

至此,成语接龙核心代码,已经完成,为了交互友好,写了一个交互函数,由于代码篇幅过长,这里只贴截图:

在交互函数中,加入了先后手选择,可以选择先手或者后手,以及记忆集合,用于判断成语是否被重复使用,还加了能接龙10次就成功的机制。

下面展示运行截图:

可以看出,程序可能没有特别完美,单已经很好的实现了预期,对战了几把,由于我的成语储备量不高,统统以失败告终,感兴趣的同学可以试一下,看看你能不能行,哈哈哈。

总结

之前的文章总是以知识点的形式输出,我发现,写多了往往就成了知识点总结,自己看来都没有什么趣味性,提不起阅读兴趣,以后尽量在自己的文章中加入一些趣味性的东西,也算是提升自己的写作能力了,加油!!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。