前言
谁能想到一个我写这玩意只是为了应付语文作业,写下这篇博文主要是记录一下我的艰难的探索过程(哭)
正文
爬虫啊,用Python写真是再舒♂服不过了
在coding之前,我们先来了解一下selenium与BeautifulSoup
selenium
selenium是一个用于Web应用程序测试的工具,它可以像真正的用户操作一样,直接运行浏览器。我们将用它来获取百度古文的网页
Q:直接用requests不就行了吗?
A:百度古文是动态网页,你发http请求的时候,古诗文还没加载出来呢!,所以我们得用selenium的WebDriverWait去等待网页加载好。
BeautifulSoup
这个名字应该出自于《爱丽丝梦游仙境》,毕竟其官网的插图于测试文本都是来自于《爱丽丝梦游仙境》,你可以叫它“美丽的汤”(笑),它可以用来解析网页,用起来比正则容易得多。
网页分析
先在百度汉语中搜索
看到url的变化了没?不难看出,我们只需要改变wd的值就可以得到相应的网页了
Code
def getpoem(title):
url = r'https://hanyu.baidu.com/s?wd=' + parse.quote(title)
#要提前安装好Chrome,Chrome会跳出来,听前辈说,有个无头的chrome,不过遗憾的是我没找到
brower = webdriver.Chrome()
brower.get()
wait = WebDriverWait(brower, 10)
wait.until(expected_conditions.presence_of_element_located((By.ID, 'main')))
soup = BeautifulSoup(brower.page_source, 'html.parser')
brower.close()
F12直接上网页源码
可以看到,正文全都在id为body_p的p标签中
所以我们可以
text = soup.findAll(id='body_p')
Bpoem = ''
for sentence in text:
Bpoem += sentence
return Bpoem
这样就得到了我们的爬虫1.0了,测试一下
issue
貌似很顺利,但是,古诗文的题目可不像身份证号一样独一无二,当你搜索《晓出》时
你会发现,html文档根本没有id为body_p的p标签,取而代之的是一个列表,古诗文在class为poem-list-item-body的div中
debug
现在,我们需要用“作者”来筛选数据了。不难发现,作者与古诗文是一一对应的,只要我们获取到作者所在列表的index,就能通过该index定位古诗文了。
code
由于这个古诗爬虫被我运用到了QQBot,所以我在这里做了消息分割处理,你完全可以设置两个参数
def getpoem( msg ):
arg = msg.split('#')
title = arg[0]
author = ''
if '#' in msg:
author = arg[1]
接下来是debug部分,在获取到text后对数据进行检验
if text == []:
if author == '':
return '无法获取,试试加上作者吧!PS:题目与作者要用#隔开哦~'
authors = soup.findAll(name="div", attrs={"class" :"poem-list-item-info"})
poems = soup.findAll(name='div',attrs={'class':'poem-list-item-body'})
for index,tauthor in enumerate(authors):
if author in tauthor.get_text():
Bpoem = poems[index].get_text()
看看效果
现在我们就有了爬虫2.0了
又见issue
害!Bug这个东西,比女朋友还粘人
我们发现,古诗文后面有省略,这是这么回事呢?看看网页,走你(PS:为什么网页暗了呢?因为我写到这的时候已经是凌晨一点多了,眼睛重要,阿巴阿巴阿巴阿巴阿巴)
我们发现,因为古诗文篇幅太长,所以在列表中简略显示了,所以我们获取到的古诗文数据自然不完整了,这下怎么办呢?
网页源码分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-34siX3Gn-1593673362075)(https://i.loli.net/2020/06/29/IPsHytzJ2FnhUQx.png)]
按照用户的操作,ta在选择之后会点击相应的标题链接(即对应的a标签),那么就会跳转到相应的网页,所以,我们要做的就是找到与作者相匹配的a链接的href属性值,然后接下来的操作就像我们的爬虫1.0一样了
debug
首先定义一个获取网页的函数getsoup()
def getsoup(url):
brower = webdriver.Chrome()
brower.get(url)
wait = WebDriverWait(brower, 10)
wait.until(EC.presence_of_element_located((By.ID, 'main')))
soup = BeautifulSoup(brower.page_source, 'html.parser')
brower.close()
return soup
然后,把url分成base和参数,base后面要用
base_url = r'https://hanyu.baidu.com'
url = base_url + '/s?wd=' + parse.quote(title)
soup = getsoup(url)
text = soup.findAll(id='body_p')
重头戏来了,从网页源代码可以看出,作者所在的div与a标签是兄弟关系,与poem-list-item的div是父子关系
遍历poem-list-item,如果author在poem-list-item-info的text中,就去获取它的兄弟标签,即a标签的href,再getsoup,像爬虫1.0一样查找body_p
items = soup.findAll(name='div', attrs={'class': 'poem-list-item'})
for item in items:
for child in item.children:
# 不知为啥会匹配到element.NavigableString的child,这里得先过滤一下
if type(child) is element.Tag and author in child.get_text():
link = item.a['href']
text = getsoup(base_url + link).findAll(id='body_p')
break
if text != [] :
break
测试一下
Github
源代码尽在
Github