基於BeautifulSoup簡單爬蟲

Python語法簡單、框架多、代碼少,用於爬蟲是一個不錯的選擇。爬蟲是模擬Http請求獲取靜態網頁,並解析網頁的html得到相應的信息的一種方法。文章針對糗事百科的段子做爬蟲練習,並用Pandas作簡單統計寫入到csv文件

請求網頁

通過urllib框架模擬http請求,獲取html,分析網頁html標籤,針對性地提取對應信息。

import urllib
import re
import pandas as pd
from urllib.request import urlopen
from bs4 import BeautifulSoup

page = 1
fetch_url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = { 'User-Agent' : user_agent }
# 構建Request對象
req = urllib.request.Request(fetch_url, headers=headers)
# urlopen打開Request對象
fetch_res = urlopen(req).read().decode('utf-8')
# print(fetch_res)
soup = BeautifulSoup(fetch_res, features='lxml')
# 頁面格式化輸出
print(soup.prettify())

頁面打印如下,基本可以看出網頁結構,一個div class=article block是一個段子組成,因此可以分析成一個div列表,然後再進行解析,提取信息。
網頁解析

解析html標籤

  • 通過每個div解析作者、內容及評論數,code片斷如下
articles = soup.findAll('div', class_=re.compile('article block'))
contents = []
authors = []
vote_nums = []
for article in articles:
    if article.children:
        contents.append(article.select('div[class="author clearfix"] h2'))
        authors.append(article.select('div[class="content"] span'))
        vote_nums.append(article.select('span[class="stats-vote"] i'))
print("{}, {}, {}".format(len(contents), len(authors), len(vote_nums)))

res_pd = pd.DataFrame({'作者': [txt[0].contents[0].strip() for txt in authors],
                       '內容': [txt[0].contents[0].strip() for txt in contents],
                      '評論數': [int(txt[0].contents[0].strip()) for txt in vote_nums]})

# 找出評論數最高的10位
res_pd.sort_values('評論數', ascending=False).head(10)
  • 結果
    結果02

python面向對象整合

  1. 根據頁數爬蟲當前頁,返回段子dataframe
  2. 將每頁段子append寫入到文件
import urllib
import re
import os
import pandas as pd
from urllib.request import urlopen
from bs4 import BeautifulSoup

class QsbkText:
    # 初始化,構造函數,主要用於初始化屬性
    def __init__(self):
        self.pageIndex = 1
        self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
        # 初始化agent
        self.headers = {'User-Agent': self.user_agent}
        # 存放是否運行
        self.enable = False

    # 獲取每頁的內容,返回DataFrame
    def getPage(self, pageIndex):
        try:
            fetch_url = 'http://www.qiushibaike.com/hot/page/' + str(pageIndex)
            req = urllib.request.Request(fetch_url, headers=self.headers)
            # 請求網頁獲取的結果
            fetch_html = urlopen(req).read().decode('utf-8')
            # print(fetch_html)
            soup = BeautifulSoup(fetch_html, features='lxml')
            articles = soup.findAll('div', class_=re.compile('article block'))
            contents = []
            authors = []
            vote_nums = []
            for article in articles:
                if article.children:
                    authors.append(article.select_one('div[class="author clearfix"] h2'))
                    contents.append(article.select_one('div[class="content"] span'))
                    vote_nums.append(article.select_one('span[class="stats-vote"] i'))
            res_pd = pd.DataFrame({'作者': [txt.contents[0].strip() for txt in authors],
                                   '內容': [txt.contents[0].strip() for txt in contents],
                                   '評論數': [int(txt.contents[0].strip()) for txt in vote_nums]})
            return res_pd
        except Exception as e:
            print('連接失敗錯誤原因', e)
            return None

    # 寫入本地文件
    def readCsv(self, pd_data, fileName):
        if not os.path.isfile(fileName):
            pd_data.to_csv(fileName, header=True, index=False)
        else:
            pd_data.to_csv(fileName, mode='a', header=False, index=False)

    # 讀取客戶端輸入
    def readFromClient(self):
        inputStr = input('please input, continue--"Enter"; exit--"Q" \n')
        if inputStr == "Q":
            self.enable = False

    def start(self):
        self.enable = True
        index_of_page = 1
        while self.enable:
            pageData = self.getPage(index_of_page)
            self.readCsv(pageData, '1.pachong_pract/qsbk_res.csv')
            index_of_page += 1
            self.readFromClient()

# 開始運行
QsbkText().start()
  • 運行過程,Enter表示繼續,Q表示退出,得到的CSV文件如下

csv結果

  • 讀取CSV文件,獲取評論數最多的20個段子
import pandas as pd
read_data = pd.read_csv('1.pachong_pract/qsbk_res.csv', encoding='gbk', delimiter=",")
read_data.sort_values('評論數', ascending=False).head(20)

前20名段子

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章