先說下我寫這個爬蟲的思路吧:首先是利用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模擬瀏覽器,根據返回的結果判斷搜索的貼吧是否存在。
二、顯示貼吧首頁的帖子
在搜索到貼吧之後,我們要進入該貼吧並查看該貼吧首頁上的帖子,這部分實現起來不算難。
首先是獲取網頁源碼,用requests.get()方法請求網頁,然後列印出text內容,可以找到如下部分。
要提取發帖人的名字和帖子主題,我選擇用正則表達式來實現,具體代碼如下:
titles = re.findall('<a rel="noreferrer" href="/p/(\w+)" title="(.*?)"', res.text)
authors = re.findall('title="主題作者: (.*?)"', res.text)
這樣我們就能成功獲取首頁上的帖子信息了。
三、查看某一個帖子
要查看一個帖子里的內容,第一步是和上面的步驟一樣的,用get方法請求網頁,然後列印text,再用正則表達式提取回覆人的名字和回覆內容。
接下來的步驟花了我不少時間,因為很多人在評論的時候會發表情,而這些表情我們是無法將它顯示出來的,因此我選擇將表情對應的鏈接顯示出來,如果要看別人發的是什麼表情,直接點鏈接進去就能看到了。對於評論中的圖片,我也是這麼處理的,將圖片的鏈接顯示出來。
這一步還有一個坑,就是因為有些人的回覆是帶有回覆框的,也就是說這些人的評論是包裹在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()