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

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

作者:互联网

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

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

成语准备

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

image.png

开玩笑,身为一个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