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 获取 Linux 系统信息的代码
Jul 13 Python
使用IronPython把Python脚本集成到.NET程序中的教程
Mar 31 Python
Python使用xlrd模块操作Excel数据导入的方法
May 26 Python
Python实现的简单模板引擎功能示例
Sep 02 Python
Python使用PIL模块生成随机验证码
Nov 21 Python
Python简直是万能的,这5大主要用途你一定要知道!(推荐)
Apr 03 Python
深入浅析python 协程与go协程的区别
May 09 Python
一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念
May 13 Python
Python字典常见操作实例小结【定义、添加、删除、遍历】
Oct 25 Python
django 解决model中类写不到数据库中,数据库无此字段的问题
May 20 Python
详解Python中下划线的5种含义
Jul 15 Python
python pandas 解析(读取、写入)CSV 文件的操作方法
Dec 24 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
Yii调试SQL的常用方法
2014/07/09 PHP
PHP5.5新特性之yield理解与用法实例分析
2019/01/11 PHP
PHP添加PNG图片背景透明水印操作类定义与用法示例
2019/03/12 PHP
使用jquery动态加载javascript以减少服务器压力
2012/10/29 Javascript
纯JS实现五子棋游戏兼容各浏览器(附源码)
2013/04/24 Javascript
js日期、星座的级联显示代码
2014/01/23 Javascript
jQuery及JS实现循环中暂停的方法
2015/02/02 Javascript
JS实现图片放大镜效果的方法
2015/02/27 Javascript
浅谈jQuery中Ajax事件beforesend及各参数含义
2016/12/03 Javascript
浅谈nodejs中的类定义和继承的套路
2017/07/26 NodeJs
JS实现验证码倒计时的注册页面
2018/01/02 Javascript
JS中Map和ForEach的区别
2018/02/05 Javascript
详解Vue SPA项目优化小记
2018/07/03 Javascript
vue watch深度监听对象实现数据联动效果
2018/08/16 Javascript
jquery分页优化操作实例分析
2019/08/23 jQuery
Python是编译运行的验证方法
2015/01/30 Python
Python函数的周期性执行实现方法
2016/08/13 Python
Python Subprocess模块原理及实例
2019/08/26 Python
python实现二分类的卡方分箱示例
2019/11/22 Python
Python库skimage绘制二值图像代码实例
2020/04/10 Python
详解pyqt5的UI中嵌入matplotlib图形并实时刷新(挖坑和填坑)
2020/08/07 Python
纯CSS打造(无图像无js)的非常流行的讲话(语音)气泡效果
2012/12/28 HTML / CSS
Canvas与Image互相转换示例代码
2013/08/09 HTML / CSS
美国在线购买内衣网站:HerRoom
2020/02/22 全球购物
MAC彩妆澳洲官网:M·A·C AU
2021/01/17 全球购物
2013年高中生自我评价
2013/10/23 职场文书
党员批评与自我批评(5篇)
2014/09/23 职场文书
2014年残联工作总结
2014/11/21 职场文书
2014年乡镇工会工作总结
2014/12/02 职场文书
特岗教师个人总结
2015/02/10 职场文书
淮海战役观后感
2015/06/11 职场文书
个人收入证明格式
2015/06/24 职场文书
分家协议书范本
2016/03/22 职场文书
深度学习tensorflow基础mnist
2021/04/14 Python
原生Javascript+HTML5一步步实现拖拽排序
2021/06/12 Javascript
Python 数据可视化工具 Pyecharts 安装及应用
2022/04/20 Python