用BS4爬取贴吧文章的作者信息时,如何兼顾爬取高亮的作者信息?

百度贴吧上的文章信息中,一般的作者信息代码,如下所示:

<a data-field="{&quot;un&quot;:&quot;\u522b\u8ba9\u4f9d\u9760\u6210&quot;}" class="frs-author-name j_user_card " href="/home/main/?un=%E5%88%AB%E8%AE%A9%E4%BE%9D%E9%9D%A0%E6%88%90&amp;ie=utf-8&amp;fr=frs" target="_blank">别让依靠成</a>

而有部分作者信息是橙色的。如下所示:

<a data-field="{&quot;un&quot;:&quot;\u51b0\u7f18\u745e\u96ea\u4f3c\u6d41\u5e74&quot;}" title="该用户已经连续签到62天了,连续30天一举“橙”名" class="frs-author-name sign_highlight j_user_card " href="/home/main/?un=%E5%86%B0%E7%BC%98%E7%91%9E%E9%9B%AA%E4%BC%BC%E6%B5%81%E5%B9%B4&amp;ie=utf-8&amp;fr=frs" target="_blank">冰缘瑞雪...</a>

以上两者标签的class值不同,在使用以下的代码爬取时无法同时爬取一般的作者信息和橙色的作者信息。

# -*-coding:utf-8-*-

"""
获取百度贴吧:生活大爆炸吧的基本内容
爬虫线路:requests - bs4
Python版本:3.5
1. 从网上爬下特定页码的网页
2. 对于爬下的页面内容进行简单的筛选分析
3. 找到每一篇帖子的 标题、发帖人、日期、楼层、以及跳转链接
4. 将结果保存到文本
"""

import requests
import time
from bs4 import BeautifulSoup


# 抓取网页的函数
def get_html(url):
    try:
        r = requests.get(url, timeout=30)
        # 判断网络连接状态,出现错误时抛出异常
        r.raise_for_status()
        # r.encoding = r.apparent_encoding.
        r.encoding = 'utf-8'
        return r.text
    except:
        return '网络连接异常'


# 分析贴吧的网页文件,整理信息,保存在列表变量中
def get_content(url):
    # 保存所有帖子信息
    comments = []
    # 获取网址
    html = get_html(url)

    # 熬汤
    soup = BeautifulSoup(html, 'lxml')
    # 获取li标签的列表
    liTags = soup.find_all('li', attrs={'class': ' j_thread_list clearfix'})
    # 遍历帖子中需要的信息
    for li in liTags:
        # 保存文章信息到字典
        comment = {}
        # 当爬虫找不到信息时抛出异常
        try:
            # 保存信息到字典
            comment['title'] = li.find('a', attrs={'class': 'j_th_tit '})['title']
            comment['link'] = "http://tieba.baidu.com/" + \
                              li.find('a', attrs={'class': 'j_th_tit '})['href']
            comment['name'] = li.find('a', attrs={'class': 'frs-author-name j_user_card '}).string
            comment['time'] = li.find('span', attrs={'class': 'pull-right is_show_create_time'}).string
            comment['replyNum'] = li.find(
                'span', attrs={'class': 'threadlist_rep_num center_text'}).string
            comments.append(comment)
        except:
            print('找不到相关文章信息')
    return comments


# 将结果保存到本地
def Out2File(dict):
    # 打开文件,使用追加模式
    with open('D:\BDTB.txt', 'a+', encoding='utf-8') as f:
        for comment in dict:
            f.write('标题: {} \t 链接:{} \t 发帖人:{} \t 发帖时间:{} \t 回复数量: {} \n'.format(
                comment['title'], comment['link'], comment['name'], comment['time'], comment['replyNum']))
        print('当前页面爬取完成')


def main(base_url, deep):
    url_list = []
    # 将需要爬取的url存入列表
    for i in range(0, deep):
        url_list.append(base_url + '&pn=' + str(50 * i))
    print('所有网址下载完毕,开始筛选信息...')

    # 遍历分析所有数据,并保存到本地
    for url in url_list:
        content = get_content(url)
        Out2File(content)
    print('所有文章信息保存完毕!')

base_url = 'http://tieba.baidu.com/f?ie=utf-8&kw=%E7%94%9F%E6%B4%BB%E5%A4%A7%E7%88%86%E7%82%B8&fr=search'
# 设置需要爬取的页码数量
deep = 3

if __name__ == '__main__':
    main(base_url, deep)
阅读 3.3k
2 个回答

在贴吧这个情况下,我们可以直接先找它的父节点再提取它的信息。签到信息不同虽然会影响该节点class,
但是无论是橙名还是白名,父节点都是class为frs-author-name-wrap的span节点

<span class="frs-author-name-wrap"><a data-field="{&quot;un&quot;:&quot;\u827e\u8fea\u662f\u6211\u7684\u592a\u9633&quot;}" title="该用户已经连续签到241天了,连续30天一举“橙”名" class="frs-author-name sign_highlight j_user_card " href="/home/main/?un=%E8%89%BE%E8%BF%AA%E6%98%AF%E6%88%91%E7%9A%84%E5%A4%AA%E9%98%B3&amp;ie=utf-8&amp;fr=frs" target="_blank">艾迪是我...</a></span>

因此我们可以

comment['name'] = li.find("span",attrs={"class":"frs-author-name-wrap"}).a.string

tips:

当节点的信息不足以完全分辨该节点时,我们完全可以不断找它的父节点,直到找到具有充分特征的节点为止。

最简单的 加一个if判断语句,如果查找你现在找的这个类名结果为空 ,则查找那一个类名。
或者使用cssSelector

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题