Python爬虫爬取百度汉语的古诗词

    技术2022-07-16  69

    前言

    谁能想到一个我写这玩意只是为了应付语文作业,写下这篇博文主要是记录一下我的艰难的探索过程(哭)

    正文

    爬虫啊,用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

    Processed: 0.009, SQL: 9