前言
Python是一種跨平台的計算機程式設計語言。是一種面向對象的動态類型語言,最初被設計用于編寫自動化腳本(shell),随着版本的不斷更新和語言新功能的添加,越來越多被用于獨立的、大型項目的開發。
日前,在學習中思考,如何整理一份貼吧曆史資料出來,從中找尋當年玩貼吧的回憶呢。
于是就有了想從貼吧爬取資料的想法,此代碼的由來就是如此。
事前準備
應先安裝pycharm,此處使用的是社群版用于個人學習。如商業行為請支援正版pycharm套件。
檢查需求
擷取貼吧清單的真實連結
分析鎖定回複量為篩選值,篩選出指定回複量以上的文章
将指定文章的URL導出為表格形式儲存
通過URL讀取文章資料,儲存一樓資料并存為word檔案命名為文章名(前5個字元).docx
開工
特别注意本文使用的是python3.7,無法直接從pycharm中add進docx包,否則會報錯,請務必使用手動下載下傳安裝,原因及解決方法如下
解決方法:
1.指令行 解除安裝docx,pip uninstall docx
2.下載下傳 python_docx-0.8.10-py2.py3-none-any.whl 下載下傳位址
3. 指令行輸入pip install python_docx-0.8.10-py2.py3-none-any.whl使用新的docx包
檔案名應與下載下傳的時候一緻,也許之後會再進行更新
代碼部分
擷取連結模闆及輸出貼吧清單
打開浏覽器,按下F12,打開貼吧,搜尋一個貼吧,這邊以"希靈帝國"為例
打開後可以看到,該帖吧首頁的位址是:https://tieba.baidu.com/f?ie=utf-8&kw=%E5%B8%8C%E7%81%B5%E5%B8%9D%E5%9B%BD&fr=search
通過浏覽器的翻譯,我們可以得知:希靈帝國被浏覽器翻譯成%E5%B8%8C%E7%81%B5%E5%B8%9D%E5%9B%BD,是以這串其實就是希靈帝國四個字的unicode顯示,是以得出了貼吧名字在貼吧連結裡占用的子產品。
該貼吧第四頁的位址是:https://tieba.baidu.com/f?kw=%E5%B8%8C%E7%81%B5%E5%B8%9D%E5%9B%BD&ie=utf-8&pn=150
重新點回第一頁:https://tieba.baidu.com/f?kw=%E5%B8%8C%E7%81%B5%E5%B8%9D%E5%9B%BD&ie=utf-8&pn=0
點第二頁:https://tieba.baidu.com/f?kw=%E5%B8%8C%E7%81%B5%E5%B8%9D%E5%9B%BD&ie=utf-8&pn=50
得出規律:https://tieba.baidu.com/f?kw=貼吧名字&ie=utf-8&pn=頁碼
并且頁碼是0開始,50為一跳
是以這邊可以定義讀取的URL模闆是:"https://tieba.baidu.com/f?kw=" + 貼吧名字 + "&ie=utf-8&pn={}"
{}是代表占位符,後續讀取不同頁面的時候就占用該占位符位置
然後我們就可以進行爬取頁面資料的函數編寫了
此處這個函數,主要功能是用來擷取到貼吧清單頁面的資料# -*- coding:UTF-8 -*-
#設定間隔的
import time
#抓資料的
import requests
from bs4 import BeautifulSoup
#把資料弄能看的
import numpy as np
import pandas as pd
import docx
import xlrd
#上述是後面會用到的所有包,後續代碼中不再另外列出
tiebaname = str(input("請輸入貼吧名:")) #定義貼吧名字,使用者直接輸入
template_url = "https://tieba.baidu.com/f?kw=" + tiebaname + "&ie=utf-8&pn={}" #生成get請求的URL模闆
def search_n_pages(n):
#爬取n頁的資料,确認爬取頁數
target = []
#發起n次的get請求
for i in range(n):
#跟蹤進度
print('頁數:',i+1)
#按照浏覽貼吧的自然行為,每一頁50條
target_url = template_url.format(50*(i))
res = requests.get(target_url)
#轉為bs對象
soup = BeautifulSoup(res.text,'html.parser')
#擷取該頁文章清單
page_lst = soup.find_all(class_='j_thread_list clearfix')
#該頁資訊儲存到target裡
target.extend(extra_from_one_page(page_lst))
#休息2秒再通路
time.sleep(2)
return target
分析篩選關鍵詞及生成表單
然後有了貼吧頁面的資料以後,就需要對頁面資料進行篩選,篩選出需要的資料。
對應需求,篩選的關鍵詞應是:回複量
是以這邊,打開一個貼吧清單頁面,對着回複量進行右鍵--審查元素可以找到對應的
塊
找到class值 這邊看到class值是 class="threadlist_rep_num center_text" 記錄下來備用,待會抓取資料的時候就要使用到這個
再然後,要抓取對應的标題和URL,右鍵文章标題,審查元素,就顯示出了具體的細節
其中可以看到class值為class="j_th_tit ",而悄咪咪打開文章對比一下,你會發現,文章位址其實就是貼吧字首+href的值 如圖打開就是https://tieba.baidu.com/p/6297714220,其實就是https://tieba.baidu.com + a['href']
于是,回複量、标題、URL都擷取到了,接下來就是将他們的資料爬取下來儲存了
則這一段大概可以這麼寫:# 設定回複量門檻值 判斷輸入的回複量是否為int類型,不是的話重新要求輸入
while True:
try:
clicknum = int(input("請輸入要爬取的回複數(超過該回複數的才會被爬取):"))
break
except ValueError:
print("請輸入數字!")
M = clicknum
def extra_from_one_page(page_lst):
'''從一頁中提取 文章'''
# 臨時清單儲存字典資料,每一個文章都是一個字典資料
tmp = []
for i in page_lst:
#判斷是否超過門檻值(這邊的“threadlist_rep_num”實際上是頁面上顯示的回複量)
if int(i.find(class_='threadlist_rep_num center_text').text) > M:
dic = {}
#點選量
dic['num'] = int(i.find(class_='col2_left j_threadlist_li_left').text)
#文章名稱
dic['name'] = i.find(class_='j_th_tit').text
#文章位址
dic['address'] = 'https://tieba.baidu.com' + i.find(class_='j_th_tit').a['href']
tmp.append(dic)
return tmp
#爬取貼吧前n頁資料 如果輸入的不是int類型 則要求重新輸入
while True:
try:
num = int(input("請輸入要爬取的頁數:"))
break
except ValueError:
print("請輸入數字!")
d = search_n_pages(num)
# 轉化為pandas.DataFrame對象
data = pd.DataFrame(d)
# 導出到excel表格
xlsxname = tiebaname + '.xlsx'
data.to_excel(xlsxname)
這樣就是生成了表格檔案了
從表單中讀取URL并生成儲存為WORD文檔
接下來是要從表格中讀取URL,然後去列印到word裡并儲存檔案
首先先讀取上一步驟生成的表單'xlsxname',從中篩選出關鍵列'address',然後讀取整列,并儲存為清單(execl_list)#從生成的表格中讀取url清單,使url_write_word函數可以有讀取用的url_list
def execl_read_url(execl_list):
#打開指定表格
rbook = xlrd.open_workbook(execl_list)
rbook.sheets()
rsheet = rbook.sheet_by_index(0)
tmp = []
#周遊表格每一行
for row in rsheet.get_rows():
#保留指定的列數資料
product_column = row[3]
product_value = product_column.value
#去掉标題欄,将剩下的url儲存為一個清單
if product_value != 'address':
r = str(row[3])
r1 = r[6:-1]
tmp.append(r1)
return tmp
#讀取表格,生成url清單
execl_list = xlsxname
#将url清單儲存到url_list
url_list = execl_read_url(execl_list)
手中有一批的URL可以直接讀取了,那接着要怎麼去擷取他們的頁面裡的資料呢?
當然是通過通路他們來獲得資料。
打開随便一個文章,對着标題進行審查元素,如下圖
可以看到
塊的class值是class="core_title_txt pull-left text-overflow " 留存備用,後續可以用作文檔标題和記錄
而抓取資料的話,就先抓取一樓就好,對着一樓進行審查元素,如下圖
抓取到的class值是class="d_post_content j_d_post_content " 留存備用
接着有了這兩個值,就可以将網頁資料中想要的部分篩選出來并儲存了
調取之前生成的url清單,然後周遊清單的每個URL,逐一通路篩選出要儲存的資料,通過docx庫進行建立word文檔并寫入儲存,這部分就完成了#周遊url清單,通路并讀取資料儲存為word
def url_write_word(url_list):
tmp = '檔案生成完成'
s = 1
#周遊URL清單
for i in url_list:
tmp1 = []
print('生成檔案',s)
s += 1
i = str(i)
#讀取網頁
res = requests.get(i)
soup = BeautifulSoup(res.text,'html.parser')
url_title = soup.find(class_='core_title_txt pull-left text-overflow').text
t1 = url_title
t1 = t1[0:7] + '.docx'
#建立一個word文檔
doc = docx.Document()
url_word = soup.find(class_='d_post_content j_d_post_content').text
t2 = url_word
#将資料寫入word
doc.add_paragraph(i)
doc.add_paragraph(t2)
#儲存文檔
doc.save(t1)
return tmp
#生成word文檔
url_write_word(url_list)
小結
本文使用了如下幾個知識點:使用time子產品進行程式間隔循環
使用requests包進行get網頁資料
使用BeautifulSoup庫進行整理篩選網頁資料
使用pandas包進行整理資料
使用xlrd子產品進行讀取表格
使用docx包進行建立儲存文檔
參考資料