介绍

  本文将展示如何利用Python爬虫来实现诗歌接龙。

  该项目的思路如下:

  1. 利用爬虫爬取诗歌,制作诗歌语料库;
  2. 将诗歌分句,形成字典:键(key)为该句首字的拼音,值(value)为该拼音对应的诗句,并将字典保存为pickle文件;
  3. 读取pickle文件,编写程序,以exe文件形式运行该程序。

  该项目实现的诗歌接龙,规则为下一句的首字与上一句的尾字的拼音(包括声调)一致。下面将分步讲述该项目的实现过程。

诗歌语料库

  首先,我们利用Python爬虫来爬取诗歌,制作语料库。爬取的网址为:https://www.gushiwen.org,页面如下:

由于本文主要为试了展示该项目的思路,因此,只爬取了该页面中的唐诗三百首、古诗三百、宋词三百、宋词精选,一共大约1100多首诗歌。为了加速爬虫,采用并发实现爬虫,并保存到poem.txt文件。完整的Python程序如下:

import re
import requests
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED # 爬取的诗歌网址
urls = ['https://so.gushiwen.org/gushi/tangshi.aspx',
'https://so.gushiwen.org/gushi/sanbai.aspx',
'https://so.gushiwen.org/gushi/songsan.aspx',
'https://so.gushiwen.org/gushi/songci.aspx'
] poem_links = []
# 诗歌的网址
for url in urls:
# 请求头部
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}
req = requests.get(url, headers=headers) soup = BeautifulSoup(req.text, "lxml")
content = soup.find_all('div', class_="sons")[0]
links = content.find_all('a') for link in links:
poem_links.append('https://so.gushiwen.org'+link['href']) poem_list = []
# 爬取诗歌页面
def get_poem(url):
#url = 'https://so.gushiwen.org/shiwenv_45c396367f59.aspx'
# 请求头部
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}
req = requests.get(url, headers=headers)
soup = BeautifulSoup(req.text, "lxml")
poem = soup.find('div', class_='contson').text.strip()
poem = poem.replace(' ', '')
poem = re.sub(re.compile(r"\([\s\S]*?\)"), '', poem)
poem = re.sub(re.compile(r"([\s\S]*?)"), '', poem)
poem = re.sub(re.compile(r"。\([\s\S]*?)"), '', poem)
poem = poem.replace('!', '!').replace('?', '?')
poem_list.append(poem) # 利用并发爬取
executor = ThreadPoolExecutor(max_workers=10) # 可以自己调整max_workers,即线程的个数
# submit()的参数: 第一个为函数, 之后为该函数的传入参数,允许有多个
future_tasks = [executor.submit(get_poem, url) for url in poem_links]
# 等待所有的线程完成,才进入后续的执行
wait(future_tasks, return_when=ALL_COMPLETED) # 将爬取的诗句写入txt文件
poems = list(set(poem_list))
poems = sorted(poems, key=lambda x:len(x))
for poem in poems:
poem = poem.replace('《','').replace('》','') \
.replace(':', '').replace('“', '')
print(poem)
with open('F://poem.txt', 'a') as f:
f.write(poem)
f.write('\n')

该程序爬取了1100多首诗歌,并将诗歌保存至poem.txt文件,形成我们的诗歌语料库。当然,这些诗歌并不能直接使用,需要清理数据,比如有些诗歌标点不规范,有些并不是诗歌,只是诗歌的序等等,这个过程需要人工操作,虽然稍显麻烦,但为了后面的诗歌分句效果,也是值得的。

诗歌分句

  有了诗歌语料库,我们需要对诗歌进行分句,分句的标准为:按照结尾为。?!进行分句,这可以用正则表达式实现。之后,将分句好的诗歌写成字典:键(key)为该句首字的拼音,值(value)为该拼音对应的诗句,并将字典保存为pickle文件。完整的Python代码如下:

import re
import pickle
from xpinyin import Pinyin
from collections import defaultdict def main():
with open('F://poem.txt', 'r') as f:
poems = f.readlines() sents = []
for poem in poems:
parts = re.findall(r'[\s\S]*?[。?!]', poem.strip())
for part in parts:
if len(part) >= 5:
sents.append(part) poem_dict = defaultdict(list)
for sent in sents:
print(part)
head = Pinyin().get_pinyin(sent, tone_marks='marks', splitter=' ').split()[0]
poem_dict[head].append(sent) with open('./poemDict.pk', 'wb') as f:
pickle.dump(poem_dict, f) main()

我们可以看一下该pickle文件(poemDict.pk)的内容:

当然,一个拼音可以对应多个诗歌。

诗歌接龙

  读取pickle文件,编写程序,以exe文件形式运行该程序。

  为了能够在编译形成exe文件的时候不出错,我们需要改写xpinyin模块的_init_.py文件,将该文件的全部代码复制至mypinyin.py,并将代码中的下面这句代码

data_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
'Mandarin.dat')

改写为

data_path = os.path.join(os.getcwd(), 'Mandarin.dat')

这样我们就完成了mypinyin.py文件。

  接下来,我们需要编写诗歌接龙的代码(Poem_Jielong.py),完整代码如下:

import pickle
from mypinyin import Pinyin
import random
import ctypes STD_INPUT_HANDLE = -10
STD_OUTPUT_HANDLE = -11
STD_ERROR_HANDLE = -12 FOREGROUND_DARKWHITE = 0x07 # 暗白色
FOREGROUND_BLUE = 0x09 # 蓝色
FOREGROUND_GREEN = 0x0a # 绿色
FOREGROUND_SKYBLUE = 0x0b # 天蓝色
FOREGROUND_RED = 0x0c # 红色
FOREGROUND_PINK = 0x0d # 粉红色
FOREGROUND_YELLOW = 0x0e # 黄色
FOREGROUND_WHITE = 0x0f # 白色 std_out_handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) # 设置CMD文字颜色
def set_cmd_text_color(color, handle=std_out_handle):
Bool = ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)
return Bool # 重置文字颜色为暗白色
def resetColor():
set_cmd_text_color(FOREGROUND_DARKWHITE) # 在CMD中以指定颜色输出文字
def cprint(mess, color):
color_dict = {
'蓝色': FOREGROUND_BLUE,
'绿色': FOREGROUND_GREEN,
'天蓝色': FOREGROUND_SKYBLUE,
'红色': FOREGROUND_RED,
'粉红色': FOREGROUND_PINK,
'黄色': FOREGROUND_YELLOW,
'白色': FOREGROUND_WHITE
}
set_cmd_text_color(color_dict[color])
print(mess)
resetColor() color_list = ['蓝色','绿色','天蓝色','红色','粉红色','黄色','白色'] # 获取字典
with open('./poemDict.pk', 'rb') as f:
poem_dict = pickle.load(f) #for key, value in poem_dict.items():
#print(key, value) MODE = str(input('Choose MODE(1 for 人工接龙, 2 for 机器接龙): ')) while True:
try:
if MODE == '1':
enter = str(input('\n请输入一句诗或一个字开始:'))
while enter != 'exit':
test = Pinyin().get_pinyin(enter, tone_marks='marks', splitter=' ')
tail = test.split()[-1]
if tail not in poem_dict.keys():
cprint('无法接这句诗。\n', '红色')
MODE = 0
break
else:
cprint('\n机器回复:%s'%random.sample(poem_dict[tail], 1)[0], random.sample(color_list, 1)[0])
enter = str(input('你的回复:'))[:-1] MODE = 0 if MODE == '2':
enter = input('\n请输入一句诗或一个字开始:') for i in range(10):
test = Pinyin().get_pinyin(enter, tone_marks='marks', splitter=' ')
tail = test.split()[-1]
if tail not in poem_dict.keys():
cprint('------>无法接下去了啦...', '红色')
MODE = 0
break
else:
answer = random.sample(poem_dict[tail], 1)[0]
cprint('(%d)--> %s' % (i+1, answer), random.sample(color_list, 1)[0])
enter = answer[:-1] print('\n(*****最多展示前10回接龙。*****)')
MODE = 0 except Exception as err:
print(err)
finally:
if MODE not in ['1','2']:
MODE = str(input('\nChoose MODE(1 for 人工接龙, 2 for 机器接龙): '))

现在整个项目的结构如下(Mandarin.dat文件从xpinyin模块对应的文件夹下复制过来):

切换至该文件夹,输入以下命令即可生成exe文件:

pyinstaller -F Poem_jielong.py

生成的exe文件为Poem_jielong.exe,位于该文件夹的dist文件夹下。为了能够让exe成功运行,需要将poemDict.pk和Mandarin.dat文件复制到dist文件夹下。

测试运行

  运行Poem_jielong.exe文件,页面如下:

本项目的诗歌接龙有两种模式,一种为人工接龙,就是你先输入一句诗或一个字,然后就是计算机回复一句,你回复一句,负责诗歌接龙的规则;另一种模式为机器接龙,就是你先输入一句诗或一个字,机器会自动输出后面的接龙诗句(最多10个)。

  先测试人工接龙模式:

  再测试机器接龙模式:

总结

  该项目的Github地址为:https://github.com/percent4/Shicijielong

  感谢阅读,欢迎大家交流~~

注意:本人现已开通微信公众号: Python爬虫与算法(微信号为:easy_web_scrape), 欢迎大家关注哦~~

Python爬虫之诗歌接龙的更多相关文章

  1. Python爬虫之PyQuery使用(六)

    Python爬虫之PyQuery使用 PyQuery简介 pyquery能够通过选择器精确定位 DOM 树中的目标并进行操作.pyquery相当于jQuery的python实现,可以用于解析HTML网 ...

  2. Python爬虫简单实现CSDN博客文章标题列表

    Python爬虫简单实现CSDN博客文章标题列表 操作步骤: 分析接口,怎么获取数据? 模拟接口,尝试提取数据 封装接口函数,实现函数调用. 1.分析接口 打开Chrome浏览器,开启开发者工具(F1 ...

  3. Python 爬虫模拟登陆知乎

    在之前写过一篇使用python爬虫爬取电影天堂资源的博客,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...

  4. python爬虫成长之路(一):抓取证券之星的股票数据

    获取数据是数据分析中必不可少的一部分,而网络爬虫是是获取数据的一个重要渠道之一.鉴于此,我拾起了Python这把利器,开启了网络爬虫之路. 本篇使用的版本为python3.5,意在抓取证券之星上当天所 ...

  5. python爬虫学习(7) —— 爬取你的AC代码

    上一篇文章中,我们介绍了python爬虫利器--requests,并且拿HDU做了小测试. 这篇文章,我们来爬取一下自己AC的代码. 1 确定ac代码对应的页面 如下图所示,我们一般情况可以通过该顺序 ...

  6. python爬虫学习(6) —— 神器 Requests

    Requests 是使用 Apache2 Licensed 许可证的 HTTP 库.用 Python 编写,真正的为人类着想. Python 标准库中的 urllib2 模块提供了你所需要的大多数 H ...

  7. 批量下载小说网站上的小说(python爬虫)

    随便说点什么 因为在学python,所有自然而然的就掉进了爬虫这个坑里,好吧,主要是因为我觉得爬虫比较酷,才入坑的. 想想看,你可以批量自动的采集互联网上海量的资料数据,是多么令人激动啊! 所以我就被 ...

  8. python 爬虫(二)

    python 爬虫 Advanced HTML Parsing 1. 通过属性查找标签:基本上在每一个网站上都有stylesheets,针对于不同的标签会有不同的css类于之向对应在我们看到的标签可能 ...

  9. Python 爬虫1——爬虫简述

    Python除了可以用来开发Python Web之后,其实还可以用来编写一些爬虫小工具,可能还有人不知道什么是爬虫的. 一.爬虫的定义: 爬虫——网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区 ...

随机推荐

  1. stm32f10x_it.c、stm32f10x_it.h和stm32f10x_conf.h文件作用

    如上图,在STM32的Keil工程文件(Project)中一般都包含stm32f10x_it.c.stm32f10x_it.h和stm32f10x_conf.h这三个文件,但是在ST官方提供的标准库“ ...

  2. python 队列结合线程的使用

    from queue import Queue from threading import Thread import time q = Queue() def add_to_queue(): for ...

  3. 《笔记篇》非JS方法跳转到一个新页面,主要防止客户端禁止浏览器JS以后的跳转异常

    用非JS方法打开一个新页面,主要防止客户端禁止浏览器JS以后的跳转失效 <meta http-equiv="refresh" content="0; url=htt ...

  4. 命令行方式登录PostgreSQL

    目录: 一.在默认配置条件下,本机访问PostgreSQL 二.创建新用户来访问PostgreSQL 三.最简单的做法 四.开启远程访问 一.在默认配置条件下,本机访问PostgreSQL 切换到Li ...

  5. Codeforces Round #425 (Div. 2)

    A 题意:给你n根棍子,两个人每次拿m根你,你先拿,如果该谁拿的时候棍子数<m,这人就输,对手就赢,问你第一个拿的人能赢吗 代码: #include<stdio.h>#define ...

  6. lua-01

    ctrl + shift + L 多行编辑 ctrl + D 继续向下选中下一个相同的文本 Alt + F3 选中所有相同所选中德文本 =>Lua的快捷键 回调代码: function fact ...

  7. BI项目记(二):给我接套数据

    这次故事的主角还是小D,小D工作在一家传统公司的信息部门,负责数据仓库系统的运维和开发. 话说有一天,小D被教导老板的office,老板给布置了一个任务,让小D在现有数据仓库里接入刚上线的两个系统的数 ...

  8. FFmpeg 学习(一):FFmpeg 简介

    一.FFmpeg 介绍 FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.采用LGPL或GPL许可证.它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先 ...

  9. vue组件推荐

    Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可.在公司的Web前端项目开发中,多个项目采用基于Vue的UI组件框架开发,并投入正 ...

  10. C++ Opencv split()通道分离函数 merge()通道合并函数 使用操作详解

    一. split()通道分离函数 split()函数的C++版本有两个原型,他们分别是: C++: void split(const Mat& src, Mat*mvbegin);//& ...