Python爬取成语接龙类网站


Posted in Python onOctober 19, 2018

介绍

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

该项目的思路如下:

利用爬虫爬取诗歌,制作诗歌语料库;

将诗歌分句,形成字典:键(key)为该句首字的拼音,值(value)为该拼音对应的诗句,并将字典保存为pickle文件;
读取pickle文件,编写程序,以exe文件形式运行该程序。

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

诗歌语料库

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

Python爬取成语接龙类网站

由于本文主要为试了展示该项目的思路,因此,只爬取了该页面中的唐诗三百首、古诗三百、宋词三百、宋词精选,一共大约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)的内容:

Python爬取成语接龙类网站

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

诗歌接龙

读取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模块对应的文件夹下复制过来):

Python爬取成语接龙类网站

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

pyinstaller -F Poem_jielong.py

Python爬取成语接龙类网站

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

先测试人工接龙模式:

Python爬取成语接龙类网站

再测试机器接龙模式:

Python爬取成语接龙类网站

总结

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

Python 相关文章推荐
python处理中文编码和判断编码示例
Feb 26 Python
零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers
Nov 05 Python
使用Node.js和Socket.IO扩展Django的实时处理功能
Apr 20 Python
Python3 实现随机生成一组不重复数并按行写入文件
Apr 09 Python
完美解决安装完tensorflow后pip无法使用的问题
Jun 11 Python
使用Python写一个量化股票提醒系统
Aug 22 Python
详解Django项目中模板标签及模板的继承与引用(网站中快速布置广告)
Mar 27 Python
详解Python用三种方式统计词频的方法
Jul 29 Python
python之生成多层json结构的实现
Feb 27 Python
python 已知一个字符,在一个list中找出近似值或相似值实现模糊匹配
Feb 29 Python
如何利用python之wxpy模块玩转微信
Aug 17 Python
总结Python连接CS2000的详细步骤
Jun 23 Python
将Django项目部署到CentOs服务器中
Oct 18 #Python
python中将zip压缩包转为gz.tar的方法
Oct 18 #Python
Python 忽略warning的输出方法
Oct 18 #Python
解决python通过cx_Oracle模块连接Oracle乱码的问题
Oct 18 #Python
解决python3捕获cx_oracle抛出的异常错误问题
Oct 18 #Python
python 自定义异常和异常捕捉的方法
Oct 18 #Python
详解Python发送email的三种方式
Oct 18 #Python
You might like
ThinkPHP框架实现数据增删改
2017/05/07 PHP
Laravel jwt 多表(多用户端)验证隔离的实现
2019/12/18 PHP
JQUERY 浏览器判断实现函数
2009/08/20 Javascript
js切换光标示例代码
2013/10/10 Javascript
原生JS可拖动弹窗效果实例代码
2013/11/09 Javascript
jquery实现邮箱自动补全功能示例分享
2014/02/17 Javascript
jquery禁止输入数字以外的字符的示例(纯数字验证码)
2014/04/10 Javascript
JavaScript通过字典进行字符串翻译转换的方法
2015/03/19 Javascript
BootStrap智能表单实战系列(八)表单配置json详解
2016/06/13 Javascript
JavaScript实现经典排序算法之冒泡排序
2016/12/28 Javascript
jQuery Validation Engine验证控件调用外部函数验证的方法
2017/01/18 Javascript
JS点击缩略图整屏居中放大图片效果
2017/07/04 Javascript
JS实现图片上传多次上传同一张不生效的处理方法
2018/08/06 Javascript
vue-router路由懒加载的实现(解决vue项目首次加载慢)
2018/08/28 Javascript
详解在vue-test-utils中mock全局对象
2018/11/07 Javascript
Vue使用localStorage存储数据的方法
2019/05/27 Javascript
vue学习笔记之slot插槽基本用法实例分析
2020/02/01 Javascript
js实现星星海特效的示例
2020/09/28 Javascript
python使用PIL模块实现给图片打水印的方法
2015/05/22 Python
简要讲解Python编程中线程的创建与锁的使用
2016/02/28 Python
jupyter notebook 中输出pyecharts图实例
2020/04/23 Python
PyQt5使用QTimer实现电子时钟
2019/07/29 Python
python实现的接收邮件功能示例【基于网易POP3服务器】
2019/09/11 Python
Django实现CAS+OAuth2的方法示例
2019/10/30 Python
Python数据可视化:饼状图的实例讲解
2019/12/07 Python
Python通过VGG16模型实现图像风格转换操作详解
2020/01/16 Python
Python numpy多维数组实现原理详解
2020/03/10 Python
德国玩具商店:Planet Happy DE
2021/01/16 全球购物
最新远光软件笔试题面试题内容
2013/11/08 面试题
计算机应用职专应届生求职信
2013/11/12 职场文书
单位人事专员介绍信
2014/01/11 职场文书
成人继续教育实施方案
2014/03/01 职场文书
委托书格式范文
2015/01/28 职场文书
《角的度量》教学反思
2016/02/18 职场文书
使用tensorflow 实现反向传播求导
2021/05/26 Python
python 爬取哔哩哔哩up主信息和投稿视频
2021/06/07 Python