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

来源:早起Python
作者:刘早起

飞花令是古时候人们经常玩一种“行酒令”的游戏,是中国古代酒令之一,属雅令。“飞花”一词则出自唐代诗人韩翃《寒食》中 春城无处不飞花 一句。行飞花令时选用诗和词,也可用曲,但选择的句子一般不超过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 requestsfrom 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).textprint(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(1, 3):
        url = f'https://so.gushiwen.org/search.aspx?page={i}&value={keyword}'
        num = poet_content(keyword, num, url)

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

(0)

相关推荐

  • (3条消息) Python爬取全国高校信息并写入csv

    2021-03-23更新 原来的页面有一些小的改变, 原来的院校特效一列变成了现在的 一流大学建设高校 和一流学科建设高校 两列, 所以代码需要有一些改变,总的代码已经更新了,至于思路那部分就不改了. ...

  • 超详细 | 手把手教你如何锁边、如何更换压脚、如何锁扣眼

    缝纫零基础 の小窍门 缝纫小窍门>> 如何锁边 如何更换压脚 如何锁扣眼 01  小编有话说  对于刚买缝纫机的小白来说, 缝纫机如何使用并且该怎么用都是一大难题, 今天小编围绕 如何锁边 ...

  • 网络爬虫有什么用?怎么爬?手把手教你爬网页(Python代码)

    导读:本文主要分为两个部分:一部分是网络爬虫的概述,帮助大家详细了解网络爬虫:另一部分是HTTP请求的Python实现,帮助大家了解Python中实现HTTP请求的各种方式,以便具备编写HTTP网络程 ...

  • 20 行 Python 代码即可制作精美证件照

    无论是我们上学时还之后的工作中,基本都需要用到电子证件照片,这类照片基本都对照片尺寸.背景色有要求,本文我们来看一下如何只用不到 20 行 Python 代码完成证件照片的制作. 简介 制作证件照我们 ...

  • 高昂收费?你距离免费PDF编辑工具只差20行Python代码

    PDF(Portable Document Format,可携带文档格式)是一种以PostScript语言图像模型为基础,在不同电脑.打印机上都能够保持固定的格式.正是因为它这一特性,让PDF备受欢迎 ...

  • 手把手教你!20个妙招让你的厕所干净如新!

    厕所是家里最容易弄脏同时也最难清理的地方 赶紧看看厕所该怎么清洗 让你家的厕所干净如新!! 水龙头清洁 ▼ 白醋和小苏打粉混合均匀,将卫生纸放进去完全浸湿,然后盖住水龙头30~60分钟,揭开后用清水冲 ...

  • 最是性感小黑裙!超详细教程 教你钩假两件连衣裙(高清图解)

    这个裙子一折三波,从去年开始钩的,可能是选的花样不对,有点斜,用了3团就停了,今年重新选花样,开始想钩个下面是A字裙型,后来看到雪花老师钩的半裙很漂亮,就把它改成了大摆裙,腰间的双层看着不太明显就在里 ...

  • 超详细步骤 教你从零开始写小说

    小说是虚构的.有一定深度的叙事性文字.一部好的小说既源于生活,又高于生活,让读者从虚构的世界中也能发现真理及人性.无论你想要写什么类型的小说--文学或商业,言情或科幻,战争史诗或家庭剧,你都需要具备无 ...

  • 超详细!教你读懂门诊收费票据

    ┃来源:医保北京 就医.报销都离不开门诊发票,最近,很多朋友跟小编反映,每次去看病开的各种收费票据,上面写的密密麻麻各项费用,具体交了什么钱?医保报销了多少?既看不明白,也问不清楚.今天,小保就以北京 ...

  • 收藏贴 | 超详尽手把手教你办理OFII、CVEC、行政注册、教学注册

    又是一年开学季,相信又有不少新同学要在法兰西这片土地,开启一段全新的旅途.初到法国,除了租房以外,最重要的可以说是办理OFII和学校注册了,而往往初来乍到的我们,对当地环境还不太了解,语言也不是那么熟 ...