欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【Python3爬虫】百度贴吧爬虫

程序员文章站 2022-05-04 13:52:44
先说下我写这个爬虫的思路吧:首先是利用selenium模拟浏览器,然后搜索贴吧名,如果不存在就提示“没有找到该贴吧”,然后重新输入,如果搜到了这个贴吧,就进入该贴吧并且显示该贴吧首页上的所有帖子,然后我们可以选择查看哪一个帖子,程序就会返回该帖子的内容,对于评论较多的帖子,还可以查看下一页,如果想看 ......

先说下我写这个爬虫的思路吧:首先是利用selenium模拟浏览器,然后搜索贴吧名,如果不存在就提示“没有找到该贴吧”,然后重新输入,如果搜到了这个贴吧,就进入该贴吧并且显示该贴吧首页上的所有帖子,然后我们可以选择查看哪一个帖子,程序就会返回该帖子的内容,对于评论较多的帖子,还可以查看下一页,如果想看别的帖子,可以退回到首页重新选择。

 

环境:windows7,python3.5,pycharm

使用到的库:requests,re,selenium,time

 

具体步骤:

一、搜索贴吧

先搜索一个存在的贴吧(比如python),得到的网页链接是http://tieba.baidu.com/f?ie=utf-8&kw=python&fr=search&red_tag=q3127125854

然后搜索一个不存在的贴吧(比如sad213),得到的网页链接是http://tieba.baidu.com/f/search/res?qw=sad213&sm=2&cf=1&ie=utf-8&red_tag=r3419770693

对比两个链接可知,如果返回的链接里包含tieba.baidu.com/f?ie=utf-8,则该贴吧存在。所以我利用selenium模拟浏览器,根据返回的结果判断搜索的贴吧是否存在。

【Python3爬虫】百度贴吧爬虫

 

二、显示贴吧首页的帖子

在搜索到贴吧之后,我们要进入该贴吧并查看该贴吧首页上的帖子,这部分实现起来不算难。

首先是获取网页源码,用requests.get()方法请求网页,然后打印出text内容,可以找到如下部分。

【Python3爬虫】百度贴吧爬虫

要提取发帖人的名字和帖子主题,我选择用正则表达式来实现,具体代码如下:

titles = re.findall('<a rel="noreferrer" href="/p/(\w+)" title="(.*?)"', res.text)
authors = re.findall('title="主题作者: (.*?)"', res.text)

 这样我们就能成功获取首页上的帖子信息了。

 

三、查看某一个帖子

要查看一个帖子里的内容,第一步是和上面的步骤一样的,用get方法请求网页,然后打印text,再用正则表达式提取回复人的名字和回复内容。

【Python3爬虫】百度贴吧爬虫

接下来的步骤花了我不少时间,因为很多人在评论的时候会发表情,而这些表情我们是无法将它显示出来的,因此我选择将表情对应的链接显示出来,如果要看别人发的是什么表情,直接点链接进去就能看到了。对于评论中的图片,我也是这么处理的,将图片的链接显示出来。

 【Python3爬虫】百度贴吧爬虫

这一步还有一个坑,就是因为有些人的回复是带有回复框的,也就是说这些人的评论是包裹在div里的,用上面的方法是无法得到他们的回复的。

通过观察网页源码,我发现可以用正则表达式匹配到这部分回复,然后对于这些回复,也要进行处理后再显示出来。

 

comment_list2 = re.findall('post_bubble_middle_inner">(.*?)<div', res.text, re.dotall)
comment = comment_list2[num].replace('<br>', ' ').replace('</div>', ' ')

 

 

 

这样我们就能够搜索贴吧并且进入贴吧查看我们想看的帖子了==

 

具体源码如下:

  1 import requests
  2 import time
  3 import re
  4 from selenium import webdriver
  5 
  6 headers = {
  7     "user-agent": "mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/"
  8                   "53.0.2785.89 safari/537.36"
  9 }
 10 
 11 
 12 class tieba:
 13     def __init__(self, name, url):
 14         self.name = name  # 贴吧名
 15         self.url = url  # 贴吧首页的url
 16 
 17     # 显示首页上的帖子作者和标题
 18     def get_homepage(self):
 19         print("\n\t\t\t\t\t\t{}吧".format(self.name))
 20         res = requests.get(self.url, headers=headers)
 21         titles = re.findall('<a rel="noreferrer" href="/p/(\w+)" title="(.*?)"', res.text)
 22         authors = re.findall('title="主题作者: (.*?)"', res.text)
 23         for title, author in zip(titles, authors):
 24             print(str(titles.index(title) + 1) + "--" + author + ":" + title[1])
 25         print("\n****************************")
 26         n = int(input("请输入您想要查看的帖子序号:"))
 27         print("****************************\n")
 28         self.get_page("http://tieba.baidu.com/p/" + titles[n - 1][0])
 29 
 30     # 显示帖子的具体内容
 31     def get_page(self, page_url):
 32         res = requests.get(page_url, headers=headers)
 33         author_list = re.findall('p_author_name j_user_card.*?>(.*?)<', res.text)
 34         comment_list = re.findall('content  clearfix">(.*?)</div>', res.text, re.dotall)
 35         if len(comment_list) == 0:
 36             comment_list = re.findall('d_post_content j_d_post_content ">(.*?)</div>', res.text, re.dotall)
 37 
 38         # 带回复框的单独考虑
 39         comment_list2 = re.findall('post_bubble_middle_inner">(.*?)<div', res.text, re.dotall)
 40         num = 0
 41 
 42         # 处理图片和表情,显示对应的链接
 43         for author, comment in zip(author_list, comment_list):
 44             print(author.strip(), end=" : ")
 45             comment = comment.strip().replace('<br>', ' ')
 46             if "<div" in comment:  # 解析有评论框的评论
 47                 comment = comment_list2[num].replace('<br>', ' ').replace('</div>', ' ')
 48                 num += 1
 49             if "src" in comment:  # 处理图片信息
 50                 src_list = re.findall('src="(.*?)"', comment)
 51                 pattern_list = re.findall('(<img.*?>)', comment)
 52                 for s, p in zip(src_list, pattern_list):
 53                     comment = comment.replace(p, ' ' + s)
 54             if "href" in comment:  # 处理表情信息
 55                 pattern_list = re.findall('(<a .*? >)', comment)
 56                 for p in pattern_list:
 57                     comment = comment.replace(p, ' ').replace("</a>", '')
 58             print(comment)
 59 
 60         while true:
 61             x = int(input("\n输入1查看下一页,输入0回到首页,输入-1退出程序:"))
 62             if x == -1:
 63                 exit()
 64             if x == 0:
 65                 self.get_homepage()
 66             if x == 1:
 67                 next_page = re.findall('<a href="(.*?)">下一页', res.text)
 68                 if len(next_page)>0:
 69                     self.get_page("http://tieba.baidu.com" + next_page[0])
 70                 else:
 71                     print("已经是最后一页了!")
 72 
 73 
 74 # 利用selenium模拟浏览器查找贴吧
 75 def search():
 76     chrome_options = webdriver.chromeoptions()
 77     chrome_options.add_argument('--headless')
 78     browser = webdriver.chrome(chrome_options=chrome_options)
 79 
 80     browser.get("https://tieba.baidu.com/")
 81     name = input("请输入想要进入的贴吧名字:")
 82     browser.find_element_by_xpath('//*[@id="wd1"]').send_keys(name)
 83     browser.find_element_by_xpath('//*[@id="tb_header_search_form"]/span[1]/a').click()
 84     url = browser.current_url
 85     if "tieba.baidu.com/f?ie=utf-8" in url:  # 搜索的贴吧存在
 86         print("正在进入{}吧,请稍等...".format(name))
 87         time.sleep(2)
 88         t = tieba(name, url)
 89         t.get_homepage()
 90     else:
 91         print("没有找到{}吧\n".format(name))
 92         main()
 93 
 94 
 95 def main():
 96     x = int(input("输入1搜索进入贴吧,输入-1退出程序:"))
 97     if x == 1:
 98         search()
 99     else:
100         exit()
101 
102 
103 if __name__ == '__main__':
104     main()