觀察虎撲論壇步行街分區,請求地址為:
https://bbs.hupu.com/bxj
第一頁:https://bbs.hupu.com/bxj
第二頁:https://bbs.hupu.com/bxj-2
第三頁:https://bbs.hupu.com/bxj-3
不難發現,每增加一頁,只需要添加 -頁數 參數即可,最後一頁是第 50 頁,因此可以利用 for 循環依次爬取,定義一個 get_pages() 函數,返回初始化 Beautiful Soup 的對象 page_soup,方便後面的解析函數調用
雖然一共有 50 頁,但是當用戶訪問第 10 頁以後的頁面的時候,會要求登錄虎撲,不然就沒法查看,而且登錄時會出現智能驗證,所以程序只爬取前 10 頁的數據
def get_pages(page_url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
response = requests.get(url=page_url, headers=headers)
page_soup = BeautifulSoup(response.text, 'lxml')
return page_soup
if __name__ == '__main__':
for i in range(1, 11):
url = 'https://bbs.hupu.com/bxj-' + str(i)
soup = get_pages(url)
使用 Beautiful Soup 對網頁各個信息進行提取,最後將這些信息放進一個列表裡,然後調用列表的 .append() 方法,再將每條帖子的列表依次加到另一個新列表裡,最終返回的是類似於如下形式的列表:
[['帖子1', '作者1'], ['帖子2', '作者2'], ['帖子3', '作者3']]
這樣做的目的是:方便 MongoDB 依次儲存每一條帖子的信息
def parse_pages(page_soup):
data_list = []
all_list = page_soup.find('ul', class_='for-list')
post_list = all_list.find_all('li')
# print(result_list)
for post in post_list:
# 帖子名稱
post_title = post.find('a', class_='truetit').text
# print(post_title)
# 帖子連結
post_url = 'https://bbs.hupu.com' + post.find('a', class_='truetit')['href']
# print(post_url)
# 作者
author = post.select('.author > a')[0].text
# print(author)
# 作者主頁
author_url = post.select('.author > a')[0]['href']
# print(author_url)
# 發布日期
post_date = post.select('.author > a')[1].text
# print(post_date)
reply_view = post.find('span', class_='ansour').text
# 回複數
post_reply = reply_view.split('/')[0].strip()
# print(post_reply)
# 瀏覽量
post_view = reply_view.split('/')[1].strip()
# print(post_view)
# 最後回復時間
last_data = post.select('.endreply > a')[0].text
# print(last_data)
# 最後回復用戶
last_user = post.select('.endreply > span')[0].text
# print(last_user)
data_list.append([post_title, post_url, author, author_url, post_date, post_reply, post_view, last_data, last_user])
# print(data_list)
return data_list
首先使用 MongoClient() 方法,向其傳入地址參數 host 和 埠參數 port,指定資料庫為 hupu,集合為 bxj
將解析函數返回的列表傳入到儲存函數,依次循環該列表,對每一條帖子的信息進行提取並儲存
def mongodb(data_list):
client = MongoClient('localhost', 27017)
db = client.hupu
collection = db.bxj
for data in data_list:
bxj = {
'帖子名稱': data[0],
'帖子連結': data[1],
'作者': data[2],
'作者主頁': data[3],
'發布日期': str(data[4]),
'回複數': data[5],
'瀏覽量': data[6],
'最後回復時間': str(data[7]),
'最後回復用戶': data[8]
}
collection.insert_one(bxj)
# =============================================
# --*-- coding: utf-8 --*--
# @Time : 2019-10-12
# @Author : TRHX
# @Blog : www.itrhx.com
# @CSDN : https://blog.csdn.net/qq_36759224
# @FileName: hupu.py
# @Software: PyCharm
# =============================================
import requests
import time
import random
from pymongo import MongoClient
from bs4 import BeautifulSoup
def get_pages(page_url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
response = requests.get(url=page_url, headers=headers)
page_soup = BeautifulSoup(response.text, 'lxml')
return page_soup
def parse_pages(page_soup):
data_list = []
all_list = page_soup.find('ul', class_='for-list')
post_list = all_list.find_all('li')
# print(result_list)
for post in post_list:
# 帖子名稱
post_title = post.find('a', class_='truetit').text
# print(post_title)
# 帖子連結
post_url = 'https://bbs.hupu.com' + post.find('a', class_='truetit')['href']
# print(post_url)
# 作者
author = post.select('.author > a')[0].text
# print(author)
# 作者主頁
author_url = post.select('.author > a')[0]['href']
# print(author_url)
# 發布日期
post_date = post.select('.author > a')[1].text
# print(post_date)
reply_view = post.find('span', class_='ansour').text
# 回複數
post_reply = reply_view.split('/')[0].strip()
# print(post_reply)
# 瀏覽量
post_view = reply_view.split('/')[1].strip()
# print(post_view)
# 最後回復時間
last_data = post.select('.endreply > a')[0].text
# print(last_data)
# 最後回復用戶
last_user = post.select('.endreply > span')[0].text
# print(last_user)
data_list.append([post_title, post_url, author, author_url, post_date, post_reply, post_view, last_data, last_user])
# print(data_list)
return data_list
def mongodb(data_list):
client = MongoClient('localhost', 27017)
db = client.hupu
collection = db.bxj
for data in data_list:
bxj = {
'帖子名稱': data[0],
'帖子連結': data[1],
'作者': data[2],
'作者主頁': data[3],
'發布日期': str(data[4]),
'回複數': data[5],
'瀏覽量': data[6],
'最後回復時間': str(data[7]),
'最後回復用戶': data[8]
}
collection.insert_one(bxj)
if __name__ == '__main__':
for i in range(1, 11):
url = 'https://bbs.hupu.com/bxj-' + str(i)
soup = get_pages(url)
result_list = parse_pages(soup)
mongodb(result_list)
print('第', i, '頁數據爬取完畢!')
time.sleep(random.randint(3, 10))
print('前10頁所有數據爬取完畢!')
一共爬取到 1180 條數據:
程序只能爬取前 10 頁的數據,因為虎撲論壇要求從第 11 頁開始,必須登錄帳號才能查看,並且登錄時會有智能驗證,可以使用自動化測試工具 Selenium 模擬登錄帳號後再進行爬取。