社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

手把手教你用20行Python代码制作飞花令小程序!

菜鸟学Python • 4 年前 • 568 次点击  

飞花令是古时候人们经常玩一种“行酒令”的游戏,是中国古代酒令之一,属雅令。“飞花”一词则出自唐代诗人韩翃《寒食》中 春城无处不飞花 一句。行飞花令时选用诗和词,也可用曲,但选择的句子一般不超过7个字。

在《中国诗词大会》中改良了“飞花令”,不再仅用 字,而是增加了 云、 春、月、夜 等诗词中的高频字,轮流背诵含有关键字的诗句,直至决出胜负。

今天,我们就利用 Python 定制一款“飞花令”小程序:给定一个关键字或者关键词,就能够返回许多含有这个关键字的诗句,跟朋友玩再也不怕输了!

网页分析

要利用爬虫完成这项工作需要先选择一个合适的网站,这里我们选择了 古诗文网https://www.gushiwen.cn/

在右上角的方框中输入关键词,如,就能够返回相应的结果:

我们注意到,返回的结果是一整首诗或词,关键字所在的句子仅为其中一句。后面我们爬取信息时也需要做到过滤。

往下翻页后会发现只能获取前 2 页内容,到第 3 页会出现以下提示:

也就是说要完整获取全部诗文需要下载 App,本文简化问题只爬取前 2 页的内容,后续有机会再分享 App 相关爬虫推文。在翻页的过程中我们注意一下 URL 的改变:

第 1 页:https://so.gushiwen.cn/search.aspx?value=酒

第 2 页:https://so.gushiwen.cn/search.aspx?type=title&page=2&value=酒

其中经过测试 type=title 可以去除,而page=2 显然是页码,那么 page=1 能否获取到第 1 页呢?

答案是可以的,因此不需要用 requestspost 请求,直接 get 下面的 URL 就可到达指定页面:https://so.gushiwen.cn/search.aspx?page=页码&value=关键字

大致分析完就可以写代码了

代码实现

首先导入库,设置请求头

import requests
from lxml import html

headers = {'user-agent''Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'}

以关键字为例,尝试获取第一页全部内容:

import requests
from lxml import html

headers = {'user-agent''Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'}
html_data = requests.get('https://so.gushiwen.cn/search.aspx?page=1&value=酒', headers=headers).text
print(html_data)

返回的文本中有我们需要的内容,说明组合而成的请求是没有问题的。接下来就可以解析文本获取具体内容了,本文采用 Xpath

selector = html.fromstring(html_data)
poets = selector.xpath("/html/body/div[2]/div[1]/div[@class='sons']")
for poet in poets:
    title = ''.join(poet.xpath("div[1]/p[1]/a/b//text()")).strip()
    print(title)

诗人和朝代被分隔至两行,说明之间存在换行符及空格,可以用包含.strip()的列表推导式去除:

for poet in poets:
    title = ''.join(poet.xpath("div[1]/p[1]/a/b//text()")).strip()
    source = ''.join(poet.xpath('div[1]/p[2]//text()'))
    source = ''.join([i.strip() for i in source])
    print(title, source)

最后是对诗句的解析。为了获取关键字真正在的句子,我们要通过句号或者问号将整首诗断开成多个完整句

for poet in poets:
    title = ''.join(poet.xpath("div[1]/p[1]/a/b//text()")).strip()
    source = ''.join(poet.xpath('div[1]/p[2]//text()'))
    source = ''.join([i.strip() for i in source])
    contents = ''.join(poet.xpath('div[1]/div[@class="contson"]//text()')).strip().replace('\n''。').replace('?''。').split('。')
    print(title, source, contents)

对每一首诗逐渐判断是否包含关键字:

for poet in poets:
    title = ''.join(poet.xpath("div[1]/p[1]/a/b//text()")).strip()
    source = ''.join(poet.xpath('div[1]/p[2]//text()'))
    source = ''.join([i.strip() for i in source])
    contents = ''.join(poet.xpath('div[1]/div[@class="contson"]//text()')).strip().replace('\n''。').replace('?''。').split('。')
    content_lst = []
    for i in contents:
        if '酒' in i:
            content = i.strip() + '。'
            content_lst.append(content)
            # 有的诗可能有两句都包含关键字,这两句诗就都是需求
    if not content_lst: # 有可能只有题目中含有关键词,这种诗就跳过
        continue
    for j in list(set(content_lst)): # 有可能有的诗虽然有两句都包含关键字,但这两句是一样的,需要去重
        print(j, title, source)

大部分需求已经满足,最后只需要利用循环结构组装 URL 达到范围多页的目的,同时关键字可以修改为 input 交互输入,代码如下:

import requests
from lxml import html

headers = {'user-agent''Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'}

def poet_content(keyword,num,url):
    html_data = requests.get(url, headers=headers).text
    selector = html.fromstring(html_data)
    poets = selector.xpath("/html/body/div[2]/div[1]/div[@class='sons']")
    for poet in poets:
        title = ''.join(poet.xpath("div[1]/p[1]/a/b//text()")).strip()
        source = ''.join(poet.xpath('div[1]/p[2]//text()'))
        source = ''.join([i.strip() for i in source])
        contents = ''.join(poet.xpath('div[1]/div[@class="contson"]//text()')).strip().replace('\n''。').replace('?','。').split('。')
        content_lst = []
        for i in contents:
            if keyword in i:
                content = i.strip() + '。'
                content_lst.append(content)
        if not content_lst:
            continue
        for j in list(set(content_lst)):
            print(num, j)
            print(f'<{title}>', source)
            print('')
            num += 1
    return num

if __name__ == '__main__':
    keyword = input('> 请输入关键词: ')
    print('')
    num = 1
    for i in range(13):
        url = f'https://so.gushiwen.org/search.aspx?page={i}&value={keyword}'
        num = poet_content(keyword, num, url)

至此,我们就通过 Python 爬虫就成功制作了一款“飞花令”小工具,感兴趣的读者可以自己尝试一下!

文末福利

小编收藏了 2 张Python 数据分析速查表,每一张都是非常实用 ~

怎么获取呢?


扫码公众号后台输入, "速查表"  获取

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/109939