python對對聯(lián)

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

        python對對聯(lián)

        1.項目目的

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

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

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

        2.項目內(nèi)容

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

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

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

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

        3.輸入輸出

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

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

        程序流程圖

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

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

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

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

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

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

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

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

        主要涉及文件的讀寫。

        代碼如下:

        # 取消服務(wù)器證書驗證功能
        ssl._create_default_https_context = ssl._create_unverified_context
        database = []  # 列表記錄數(shù)據(jù)
        def askUrl(i):  # 得到指定一個URL的網(wǎng)頁內(nèi)容
            global database
            # 爬取對聯(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)  # 寫入數(shù)據(jù)庫
            except urllib.error.URLError as e:
                if hasattr(e, "code"):
                    print(e.code)
                if hasattr(e, "reason"):
                    print(e.reason)
        

        因為該網(wǎng)站的數(shù)據(jù)格式多樣, 我自己爬到的數(shù)據(jù)比較少,所以我下載了網(wǎng)上的數(shù)據(jù)庫來作為擴充(包含約70萬條對聯(lián)),下載地址如下:

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

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

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

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

        代碼如下:

        # 對聯(lián)學(xué)習(xí)
        def learns():
           global infile, outfile, zishi
           size = len(infile)  # infile為上聯(lián)庫中的內(nèi)容
           for i in range(size):
               cut = jieba.lcut(infile[i])  # 對上聯(lián)庫中對聯(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í)對聯(lián)中每個字
        # 單個的詞語學(xué)習(xí)
        def learn(word, nword):
           global zishi
           zikey = zishi.keys()
           if word in zikey:  # 如果該詞語已被學(xué)習(xí)過
               zishikey = zishi[word].keys()  # 獲取所有可以匹配該詞的詞語
               if nword in zishikey:  # 如果下聯(lián)對應(yīng)詞在可匹配詞語中
                   for j in zishikey:
                       if j != '$':
                           if j != nword:  # 可匹配詞語中的其他詞對應(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]['$'])
                   # 該對應(yīng)詞的概率增大
                   zishi[word]['$'] = zishi[word]['$'] + 1  # 可匹配詞語總數(shù)+1
               else:  # 如果該詞語未被學(xué)習(xí)過(以下步驟同上)
                   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”:對應(yīng)概率,“下聯(lián)2”:對應(yīng)概率……}

        平仄方法區(qū)分

        看對聯(lián)的最后一個字,上聯(lián)最后一個字是三聲和四聲(仄聲),下聯(lián)的最后一個字是一聲和二聲(平聲),如下聯(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)行對聯(lián)自動生成的話,打開學(xué)習(xí)生成的文件, 用和ran函數(shù)實現(xiàn)匹配并生成下聯(lián):在函數(shù)中,用隨機為上聯(lián)分配一個權(quán)重/概率(達(dá)到隨機匹配目的),對上聯(lián)分詞后的詞語一一使用ran函數(shù),然后再組合成上聯(lián)。在ran函數(shù)中,將上聯(lián)分配到的概率r與所有能配對的詞語一一比較,如果比較到某個詞的概率大于r,就返回該詞i。否則使r減少后再重復(fù)以上步驟。然后進(jìn)行輸出,輸出時進(jìn)行平仄校驗,平仄正確率大于80%后直接輸出,否則再次隨機生成下聯(lián),直到平仄符合。

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

        方法比較簡單,就是獲取每個字的音調(diào)后一一比對, 如果平仄不對則記錄下來, 最后拿正確數(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:  # 獲取對聯(lián)中每個字的拼音聲調(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):  # 比對平仄
                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ù)輸出平仄的評分。

        代碼如下:

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

        實驗結(jié)果&對比分析

        1.實驗結(jié)果

        運行結(jié)果:

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