400字范文,内容丰富有趣,生活中的好帮手!
400字范文 > 记录Request + BeautifulSoup爬取中国现代诗歌大全网站上的4000+现代诗的过程

记录Request + BeautifulSoup爬取中国现代诗歌大全网站上的4000+现代诗的过程

时间:2022-08-30 18:28:52

相关推荐

记录Request + BeautifulSoup爬取中国现代诗歌大全网站上的4000+现代诗的过程

原文在我的博客:Anywheredoor也可以找到

欢迎来玩呀!

最近想做一个和现代诗有关的小项目,第一步就是要考虑数据的问题。经过搜索,发现网上已经有大神开源了现代诗数据库。但是我没有借用,还是选择自己去爬。主要是由于,难得有想做的东西,自己从头做才能学到东西。更何况亲手爬的数据才可以为所欲为。

在做这件事情之前,我在中国大学MOOC听了北京理工大学嵩天老师的课程。也顺便学了下Python。所以这次也算是学习过后给自己交的作业。

然后一个派桑菜就这样出发了。

第一步 明确需要的数据

我的需求很简单,就是想要诗人姓名,诗歌标题,诗歌内容。也不需要id什么的,所以设想的数据格式就是这样的:

[{poetName:poemTitle:poemText:[“第一句”,”第二句”….]},{…….},….]

第二步 寻找合适的目标网站

网站介绍:

我找到的网站是:

中国现代诗歌大全

这个网站收藏有500多位诗人的5174首现当代诗。并且是一个公益站点,网站内容只要是非营利非商业就可以任意转载,无需授权。虽然网站曾经应该是提供过源码或者数据库的下载(因为有这个link),但是现在已经是404了。这正好让爬虫有了用武之地。

网站url

网站中对诗歌的展示是采用每位诗人一个网页的形式。而且网页的url用诗人姓名的拼音命名,如诗人阿斐的url就是:

/xlib/xd/sgdq/afei.htm

再比如林徽因的url就是:

/xlib/xd/sgdq/linhuiyin.htm

这就帮了大忙了,这样就可以只是通过拼接url地址去遍历网页。

只要暴力从首页复制所有诗人的姓名,随便用什么工具一键转换成拼音,

再用word里的查找替换把分割的逗号左右两端加上双引号。

这样就拥有了一个供拼接url使用的数组。

但是这样做也会有漏洞,就是有时候转换拼音的工具转换出来的,并不一定就是实际url中使用的。如遇见“柏”这种字,工具会转换成bai,而实际url中使用的是bo。

不过这个也好解决,后面我就单独写了个程序,实际遍历一下访问一下url,遇见报错就手动改掉就可以了。毕竟工作量也不大,也就改了几个人的拼音。

诗歌页面分析

诗歌的展示是这样的:

可以检查一下源码:

这个网站的布局非常简单,我发现重要标签(诗名、诗人名字)的align属性都是center。这样就可以通过指定这个特征筛选出需要的p标签。

而具体每一句诗歌内容,则可以通过br标签去定位。

第三步 编写代码

写了两个函数,第一个获取text文本属于通用的框架了,第二个是解析爬来的网页内容,详细的获取自己需要的信息。代码注释很详细所以直接贴:

# =======函数功能:用request库获取目标页面的text文本def getHTMLText(url):try:kv = {'user-agent':'Mozilla/5.0'} r = requests.get(url, timeout=30) r.raise_for_status() # 如果返回值不是200触发HTTP异常r.encoding = r.apparent_encoding # 改变爬取的网页编码,使得print结果不是乱码return r.text # 获取网页的所有信息except:return "Error!"# =======函数功能:解析并将爬来的网页文本内容储存成json# 要获得指定网页中作者,诗名,诗的内容def fillPoemList(htmlTxt):soup = BeautifulSoup(htmlTxt, "html.parser")poemResult = [] #用来储存本网页爬取结果的数组poemList = soup.find_all('p',align="center")#获取作者(正则表达式把开头的诗选剔除掉)poetName = re.sub(r'诗选', "", poemList[0].text)#获取每首诗的内容并存进数组a = 1 #list中的第0个元素是网页标题诗人介绍,并不需要所以从1开始while(a < len(poemList)):nowPoem = poemList[a]poemContent = [] #用来装每首诗的内容#每首诗的标题poemTitle = re.sub(r'\s',"",nowPoem.text)#剔除多余的空白字符#每首诗下面的诗歌内容,需要循环按句子存,以br标签后面的内容为一句话for sentencesTag in nowPoem.next_sibling.next_element.find_all('br'):sentence = sentencesTag.next_siblingif sentence is None:passelse: poemContent.append(re.sub(r'\s',"",sentence)) #剔除多余的空白字符poemResult.append({'poetName': poetName, 'poemTitle': poemTitle, 'poemContent': poemContent})a += 1return poemResult

一开始犯了个小错误,在获取每一句诗的时候,用了br标签的previous_sibling.就会导致每首诗都少爬了最后一句。我竟然都没发现,有的现代诗真是太抽象了啊!少一句真的都发现不了。后来改成next就好了。

第四步 测试代码

虽然写好了程序,但是不想中途各种卡死处理报错。所以还是要先测试一下。包括上文提到的排查错误的url,以及一些不适用于已定义函数规则的网页。

我测试的时候直接把爬取内容print出来看,总之最后晒出来大概五六个人吧,没办法按照已经写好的网页去爬。要么就是网页标签搞特殊,要么就是原网页本来就是乱码。本来就是乱码的页面就没办法了,直接T出url名单,那些标签搞特殊的人,可以踢掉之后把他们的名字记录好,后面可以手动再为他们定制爬虫规则等等。

第五步 正式运行爬虫程序

然后写个main函数,再写两行输出成json的代码就可以了。

build一下等几分钟就爬好了。文件夹中出现了10个json文件。

最后逐一打开json文件,prettify一下代码。拖动滚动条大概浏览一下有没有严重的乱码。这一块我做的不太好,写代码的时候没有注意到一些细节:

有一些诗歌末尾会有一两个乱码。只要删掉就行的那种。应该在写代码的时候就把它们筛除掉。但是我是最后才发现,也懒得再爬一次。就人工逐一浏览一下这10个文件,看到的就手动删掉了。边听歌边删,还能顺便读读诗,也蛮开心的。

还有一些诗人喜欢写组诗,组诗的标题会有一个单独的p标签,也会被我的程序识别为一个诗歌,这样的话存下来在json中就是一个空白对象。遇到这种也手动删除。

有的诗歌名称下面还有诗歌的简短的介绍,也会被我的程序识别为标题。就会导致存进去的标题很长,这个不符合我后面项目的需求,只能手动删。

还好在prettify之后,乱码、空白、过长的标题都是相对来说比较容易看到的。只是一些人工的问题了。大概半个小时搞定。

第六步 结束

然后load一下这10个json文件,计算一下最终爬了来了多少诗。发现是4286首。

四千首已经足够满足我做项目的需求啦。

开心!

欢迎交流!欢迎指出我写的不好的地方!欢迎夸我!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。