python對(duì)對(duì)聯(lián)

        網(wǎng)絡(luò) 分享 時(shí)間: 收藏本文

        python對(duì)對(duì)聯(lián)

        1.項(xiàng)目目的

        編寫(xiě)一段能夠根據(jù)輸入的上聯(lián)對(duì)出下聯(lián)的對(duì)對(duì)聯(lián)程序。輸入上聯(lián)后,能隨機(jī)生成下聯(lián),最終達(dá)到:

        (1) 程序的智能性高,功能完善。希望生成的對(duì)聯(lián)滿足平仄、韻腳、詞性等要求,并具有一定語(yǔ)義。

        (2) 在實(shí)踐項(xiàng)目的過(guò)程中提高同學(xué)的代碼編寫(xiě)能力。具體能力包括:程序設(shè)計(jì)知識(shí)的綜合運(yùn)用能力;自主學(xué)習(xí)、錯(cuò)誤調(diào)試的能力;規(guī)范書(shū)寫(xiě)代碼及報(bào)告的意識(shí)和能力;閱讀代碼、改寫(xiě)代碼的能力等。

        2.項(xiàng)目?jī)?nèi)容

        這是一個(gè)運(yùn)用從網(wǎng)上爬取的對(duì)聯(lián)、通過(guò)隨機(jī)的算法生成一段符合押韻、平仄規(guī)則的對(duì)聯(lián)的程序。大體過(guò)程為:

        (1) 運(yùn)用、、Re模塊等從網(wǎng)站上爬取對(duì)聯(lián),并對(duì)對(duì)聯(lián)進(jìn)行文本格式處理;

        (2) 運(yùn)用模塊對(duì)對(duì)聯(lián)進(jìn)行詞性分析,運(yùn)用模塊對(duì)對(duì)聯(lián)進(jìn)行平仄校準(zhǔn);

        (3) 根據(jù)詞頻隨機(jī)做出符合押韻、平仄規(guī)則的下聯(lián)。

        3.輸入輸出

        輸入:任意一副對(duì)聯(lián)的某一聯(lián)

        輸出:判斷該聯(lián)為上聯(lián)或下聯(lián)并隨機(jī)生成滿足平仄、韻腳的另一聯(lián)

        程序流程圖

        爬蟲(chóng)分析&數(shù)據(jù)分析 1.爬蟲(chóng)整體思路

        (1)爬取網(wǎng)頁(yè)

        選擇想要爬取的網(wǎng)址,并模擬頭部瀏覽器訪問(wèn)該網(wǎng)站。創(chuàng)建一個(gè)dict,將頭部信息以鍵值對(duì)的形式存入到dict對(duì)象中。本次項(xiàng)目爬取的網(wǎng)址為:

        然后調(diào)用..()函數(shù)創(chuàng)建一個(gè)對(duì)象,該函數(shù)第一個(gè)參數(shù)傳入url,第二個(gè)參數(shù)可以傳入數(shù)據(jù),默認(rèn)是傳入0數(shù)據(jù),第三個(gè)參數(shù)是傳入頭部,該參數(shù)也是有默認(rèn)值的,默認(rèn)是不傳任何頭部。將dict對(duì)象傳入..()函數(shù)第三個(gè)參數(shù)。

        此時(shí),已經(jīng)成功設(shè)置好報(bào)頭,然后使用()打開(kāi)該對(duì)象即可打開(kāi)對(duì)應(yīng)的網(wǎng)址。然后使用.read() 接收 json 數(shù)據(jù), 數(shù)據(jù)格式為UTF-8

        (2) 逐一獲取需要的標(biāo)簽并解析數(shù)據(jù)

        可以看到在網(wǎng)頁(yè)中我們需要的對(duì)聯(lián)內(nèi)容在p標(biāo)簽內(nèi),因此從html中獲取p標(biāo)簽內(nèi)容, 再利用正則表達(dá)式匹配符合要求的內(nèi)容, 并將其寫(xiě)入數(shù)據(jù)庫(kù)

        (3)保存內(nèi)容

        主要涉及文件的讀寫(xiě)。

        代碼如下:

        # 取消服務(wù)器證書(shū)驗(yàn)證功能
        ssl._create_default_https_context = ssl._create_unverified_context
        database = []  # 列表記錄數(shù)據(jù)
        def askUrl(i):  # 得到指定一個(gè)URL的網(wǎng)頁(yè)內(nèi)容
            global database
            # 爬取對(duì)聯(lián)大全網(wǎng)站
            url = "http://duilian.haoshiwen.org/view.php?aid=" + str(i)
            head = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54"
            }  # 模擬頭部瀏覽器
            try:  # 用try except進(jìn)行異常處理
                request = urllib.request.Request(url, headers=head)
                response = urllib.request.urlopen(request)
                html = response.read().decode("UTF-8")
                selector = etree.HTML(html)  # 將源碼轉(zhuǎn)化為能被XPath匹配的格式
                result = selector.xpath('//p/text()')  # 返回所有p標(biāo)簽
                for html in result:
                    findCouplet = re.compile(r'[\u4e00-\u9fff]{7}')  # 使用正則表達(dá)式查找符合格式的內(nèi)容
                    couplet = re.findall(findCouplet, html)
                    if couplet:
                        database.append(couplet)  # 寫(xiě)入數(shù)據(jù)庫(kù)
            except urllib.error.URLError as e:
                if hasattr(e, "code"):
                    print(e.code)
                if hasattr(e, "reason"):
                    print(e.reason)
        

        因?yàn)樵摼W(wǎng)站的數(shù)據(jù)格式多樣, 我自己爬到的數(shù)據(jù)比較少,所以我下載了網(wǎng)上的數(shù)據(jù)庫(kù)來(lái)作為擴(kuò)充(包含約70萬(wàn)條對(duì)聯(lián)),下載地址如下:

        中國(guó)對(duì)聯(lián)數(shù)據(jù)集 -

        .txt(上聯(lián))和.txt(下聯(lián))兩個(gè)文件

        2. 算法分析 模塊是通過(guò)學(xué)習(xí),記錄詞頻

        這部分是逐個(gè)分析上聯(lián)中的詞語(yǔ),如獲得一個(gè)詞語(yǔ)后,在下聯(lián)中找到這個(gè)詞語(yǔ)可以匹配的詞,并根據(jù)該詞語(yǔ)匹配的次數(shù)用公式計(jì)算詞頻概率(對(duì)應(yīng)概率越大說(shuō)明該詞最有可能與上聯(lián)中的對(duì)應(yīng)詞匹配)。計(jì)算公式是多次試驗(yàn)后發(fā)現(xiàn)的比較能反映詞頻的算法,不一定是最優(yōu)。

        代碼如下:

        # 對(duì)聯(lián)學(xué)習(xí)
        def learns():
           global infile, outfile, zishi
           size = len(infile)  # infile為上聯(lián)庫(kù)中的內(nèi)容
           for i in range(size):
               cut = jieba.lcut(infile[i])  # 對(duì)上聯(lián)庫(kù)中對(duì)聯(lián)逐一分詞
               for j in range(len(cut)):
                   position = infile[i].find(cut[j])  # 找到該詞位置
                   learn(cut[j], outfile[i][position: position + len(cut[j])])  # 學(xué)習(xí)該詞
               for j in range(len(infile[i])):
                   learn(infile[i][j], outfile[i][j])  # 學(xué)習(xí)對(duì)聯(lián)中每個(gè)字
        # 單個(gè)的詞語(yǔ)學(xué)習(xí)
        def learn(word, nword):
           global zishi
           zikey = zishi.keys()
           if word in zikey:  # 如果該詞語(yǔ)已被學(xué)習(xí)過(guò)
               zishikey = zishi[word].keys()  # 獲取所有可以匹配該詞的詞語(yǔ)
               if nword in zishikey:  # 如果下聯(lián)對(duì)應(yīng)詞在可匹配詞語(yǔ)中
                   for j in zishikey:
                       if j != '$':
                           if j != nword:  # 可匹配詞語(yǔ)中的其他詞對(duì)應(yīng)概率減小
                               zishi[word][j] = zishi[word][j] / (1 + 1 / zishi[word]['$'])
                   zishi[word][nword] = (zishi[word][nword] + 1 / zishi[word]['$']) / (1 + 1 / zishi[word]['$'])
                   # 該對(duì)應(yīng)詞的概率增大
                   zishi[word]['$'] = zishi[word]['$'] + 1  # 可匹配詞語(yǔ)總數(shù)+1
               else:  # 如果該詞語(yǔ)未被學(xué)習(xí)過(guò)(以下步驟同上)
                   for j in zishikey:
                       if j != '$':
                           zishi[word][j] = zishi[word][j] / (1 + 1 / zishi[word]['$'])
                   zishi[word][nword] = (1 / zishi[word]['$']) / (1 + 1 / zishi[word]['$'])
                   zishi[word]['$'] = zishi[word]['$'] + 1
           else:
               zishi[word] = {'$': 1, nword: 1}
        

        這是學(xué)習(xí)后生成的文件:

        意思為:“上聯(lián)”:{“$”+匹配的總字?jǐn)?shù),“下聯(lián)1”:對(duì)應(yīng)概率,“下聯(lián)2”:對(duì)應(yīng)概率……}

        平仄方法區(qū)分

        看對(duì)聯(lián)的最后一個(gè)字,上聯(lián)最后一個(gè)字是三聲和四聲(仄聲),下聯(lián)的最后一個(gè)字是一聲和二聲(平聲),如下聯(lián):興xīng 一聲 是上聯(lián),旺wàng四聲是下聯(lián)。

        def is_down(content):  # 判斷是否是下聯(lián), 如果是返回true
           s = list(content)
           a = pinyin.get(s[-1], format="numerical")[-1]
           return a == '1' or a == '2'
        

        main模塊講解:

        首先如果用戶輸入1, 進(jìn)行對(duì)聯(lián)自動(dòng)生成的話,打開(kāi)學(xué)習(xí)生成的文件, 用和ran函數(shù)實(shí)現(xiàn)匹配并生成下聯(lián):在函數(shù)中,用隨機(jī)為上聯(lián)分配一個(gè)權(quán)重/概率(達(dá)到隨機(jī)匹配目的),對(duì)上聯(lián)分詞后的詞語(yǔ)一一使用ran函數(shù),然后再組合成上聯(lián)。在ran函數(shù)中,將上聯(lián)分配到的概率r與所有能配對(duì)的詞語(yǔ)一一比較,如果比較到某個(gè)詞的概率大于r,就返回該詞i。否則使r減少后再重復(fù)以上步驟。然后進(jìn)行輸出,輸出時(shí)進(jìn)行平仄校驗(yàn),平仄正確率大于80%后直接輸出,否則再次隨機(jī)生成下聯(lián),直到平仄符合。

        以下介紹模塊,主要是自定義的jy函數(shù):

        方法比較簡(jiǎn)單,就是獲取每個(gè)字的音調(diào)后一一比對(duì), 如果平仄不對(duì)則記錄下來(lái), 最后拿正確數(shù)除以總的字?jǐn)?shù)獲得正確率。

        代碼如下:

        import pinyin
        def is_down(content):  # 判斷是否是下聯(lián), 如果是返回true
            s = list(content)
            a = pinyin.get(s[-1], format="numerical")[-1]
            return a == '1' or a == '2'
        def jy(s, x):
            s = list(s)
            x = list(x)
            yin1 = []
            yin2 = []
            for i in s:  # 獲取對(duì)聯(lián)中每個(gè)字的拼音聲調(diào)
                a = pinyin.get(i, format="numerical")
                yin1.append(a[-1])
            for i in x:
                b = pinyin.get(i, format="numerical")
                yin2.append(b[-1])
            error = 0
            length = len(yin1)
            for i in range(length):  # 比對(duì)平仄
                if (yin1[i] == '1' or yin1[i] == '2') and (yin2[i] == '1' or yin2[i] == '2'):
                    error += 1
                if (yin1[i] == '3' or yin1[i] == '4') and (yin2[i] == '3' or yin2[i] == '4'):
                    error += 1
            # 平仄正確率輸出
            return (length - error * 1.0) / length
        

        如果用戶輸入2, 則調(diào)用jy函數(shù)輸出平仄的評(píng)分。

        代碼如下:

        import jieba
        import random
        import json
        from verify import jy, is_down
        def couplet(s):  # 生成另一聯(lián)
            R = 0
            x = []
            for i in range(len(s)):
                x.append(ran(s[i], random.random()))
                # 用random隨機(jī)生成一個(gè)0到1之間的數(shù)后,用ran函數(shù)進(jìn)行權(quán)重比較、隨機(jī)輸出
            return "".join(x)
        def ran(w, r):
            # 根據(jù)隨機(jī)賦予字詞的權(quán)重進(jìn)行比較
            global zishi, writemode, R
            R = 0
            zikey = zishi.keys()  ##返回字典中所有鍵
            if w != '' and w in zikey:  # 當(dāng)所輸上聯(lián)在對(duì)聯(lián)庫(kù)中,根據(jù)庫(kù)得出下聯(lián)
                zishikey = zishi[w].keys()
                max = ["", 0.0]
                for i in zishikey:
                    if i != '$':
                        if r < float(zishi[w][i]):  # 當(dāng)該權(quán)重小于匹配到的字詞對(duì)應(yīng)概率,返回該字詞
                            R += r
                            return i
                        else:  # 減小權(quán)重,再次比較
                            r = r - float(zishi[w][i])
                return max[0]
            else:  # 如果該上聯(lián)不在數(shù)據(jù)庫(kù)中,劃分字詞后逐詞匹配
                return "".join([ran(i, random.random()) for i in w])
        if __name__ == '__main__':
            # 引入校驗(yàn)函數(shù)
            global infile, outfile, zishi, writemode, R
            try:
                with open("zknow.txt", "r", encoding='utf-8') as zishi_file:
                    # 打開(kāi)學(xué)習(xí)后生成的文件
                    zishi = json.loads(zishi_file.read().replace("'", '"'))
                    # 將json格式數(shù)據(jù)解碼為python對(duì)象,構(gòu)建字典
            except IOError:
                zishi = {}
            while True:
                choice = input("1. 自動(dòng)對(duì)對(duì)聯(lián) 2. 對(duì)聯(lián)評(píng)分")
                if choice == "1":
                    s = input("輸入對(duì)聯(lián):")
                    s = jieba.lcut(s)  # 對(duì)聯(lián)切詞
                    x = couplet(s)  # 生成另一聯(lián)
                    s = "".join(s)
                    for i in range(1000):
                        # 檢驗(yàn)平仄,平仄正確率大于百分之80后直接輸出,否則再次隨機(jī)生成下聯(lián),直到平仄符合
                        pz = jy(s, x)
                        if pz >= 0.8:
                            print("-----------------------------------")
                            if is_down(s):
                                print("上聯(lián):" + x)
                                print("下聯(lián):" + s)
                            else:
                                print("上聯(lián):" + s)
                                print("下聯(lián):" + x)
                            print("-----------------------------------")
                            print("評(píng)分:")
                            print("平仄: " + str(round(pz * 100, 2)) + "分")
                            print("對(duì)仗: " + str(round(R * 10000, 2)) + "分")
                            break
                        else:
                            x = couplet(s)
                else:
                    s = input("輸入上聯(lián):")
                    x = input("輸入下聯(lián):")
                    pz = jy(s, x)
                    print("評(píng)分:")
                    print("平仄: " + str(round(pz * 100, 2)) + "分")
        

        實(shí)驗(yàn)結(jié)果&對(duì)比分析

        1.實(shí)驗(yàn)結(jié)果

        運(yùn)行結(jié)果:

        周易 易經(jīng) 代理招生 二手車(chē) 網(wǎng)絡(luò)營(yíng)銷(xiāo) 旅游攻略 非物質(zhì)文化遺產(chǎn) 查字典 精雕圖 戲曲下載 抖音代運(yùn)營(yíng) 易學(xué)網(wǎng) 互聯(lián)網(wǎng)資訊 成語(yǔ) 詩(shī)詞 工商注冊(cè) 抖音帶貨 云南旅游網(wǎng) 網(wǎng)絡(luò)游戲 代理記賬 短視頻運(yùn)營(yíng) 在線題庫(kù) 國(guó)學(xué)網(wǎng) 抖音運(yùn)營(yíng) 雕龍客 雕塑 奇石 散文 常用文書(shū) 河北生活網(wǎng) 好書(shū)推薦 游戲攻略 心理測(cè)試 石家莊人才網(wǎng) 考研真題 漢語(yǔ)知識(shí) 心理咨詢 手游安卓版下載 興趣愛(ài)好 網(wǎng)絡(luò)知識(shí) 十大品牌排行榜 商標(biāo)交易 單機(jī)游戲下載 短視頻代運(yùn)營(yíng) 寶寶起名 范文網(wǎng) 電商設(shè)計(jì) 免費(fèi)發(fā)布信息 服裝服飾 律師咨詢 搜救犬 Chat GPT中文版 經(jīng)典范文 優(yōu)質(zhì)范文 工作總結(jié) 二手車(chē)估價(jià) 實(shí)用范文 石家莊點(diǎn)痣 養(yǎng)花 名酒回收 石家莊代理記賬 女士發(fā)型 搜搜作文 鋼琴入門(mén)指法教程 詞典 讀后感 玄機(jī)派 企業(yè)服務(wù) 法律咨詢 chatGPT國(guó)內(nèi)版 chatGPT官網(wǎng) 勵(lì)志名言 文玩 語(yǔ)料庫(kù) 游戲推薦 男士發(fā)型 高考作文 PS修圖 兒童文學(xué) 工作計(jì)劃 舟舟培訓(xùn) IT教程 手機(jī)游戲推薦排行榜 暖通,電地暖, 女性健康 苗木供應(yīng) ps素材庫(kù) 短視頻培訓(xùn) 優(yōu)秀個(gè)人博客 包裝網(wǎng) 創(chuàng)業(yè)賺錢(qián) 養(yǎng)生 民間借貸律師 綠色軟件 安卓手機(jī)游戲 手機(jī)軟件下載 手機(jī)游戲下載 單機(jī)游戲大全 石家莊論壇 網(wǎng)賺 職業(yè)培訓(xùn) 資格考試 成語(yǔ)大全 英語(yǔ)培訓(xùn) 藝術(shù)培訓(xùn) 少兒培訓(xùn) 苗木網(wǎng) 雕塑網(wǎng) 好玩的手機(jī)游戲推薦 漢語(yǔ)詞典 中國(guó)機(jī)械網(wǎng) 美文欣賞 紅樓夢(mèng) 道德經(jīng) 標(biāo)準(zhǔn)件 電地暖 鮮花 書(shū)包網(wǎng) 英語(yǔ)培訓(xùn)機(jī)構(gòu) 電商運(yùn)營(yíng)
        亚洲狠狠婷婷综合久久| 亚洲午夜日韩高清一区| 狠狠综合亚洲综合亚洲色| 国产成人精品日本亚洲18图| 亚洲麻豆精品果冻传媒| 亚洲国产高清在线| 亚洲成色WWW久久网站| 亚洲熟妇av一区二区三区漫画| 亚洲成人影院在线观看| 自拍偷自拍亚洲精品播放| 亚洲av无码成人影院一区| 亚洲精品无码国产片| 亚洲狠狠婷婷综合久久蜜芽| 亚洲AV日韩AV永久无码色欲| 青青青亚洲精品国产| 自拍偷自拍亚洲精品偷一| 国产亚洲漂亮白嫩美女在线| 亚洲第一永久AV网站久久精品男人的天堂AV| 自拍偷自拍亚洲精品播放| 亚洲精品视频在线看| 亚洲最大av无码网址| 中文字幕精品亚洲无线码二区| 国产亚洲成人在线播放va| 伊人久久精品亚洲午夜| 亚洲日韩国产精品第一页一区| 国产精品亚洲а∨无码播放| 亚洲av无码av制服另类专区| 亚洲第一精品福利| 亚洲欧洲日产国码二区首页 | 亚洲国产韩国一区二区| 亚洲jjzzjjzz在线播放| 中文字幕亚洲男人的天堂网络| 亚洲一区二区三区在线网站| 亚洲一久久久久久久久| 久久无码av亚洲精品色午夜 | 在线a亚洲v天堂网2018| 亚洲一区视频在线播放| 亚洲精品无码永久在线观看你懂的 | 最新亚洲成av人免费看| 亚洲AV无码久久精品色欲| 亚洲欧洲在线观看|