1. 程式人生 > >Python爬蟲實戰專案之小說資訊爬取

Python爬蟲實戰專案之小說資訊爬取

我們以奇書網為例進行爬取

網址:https://www.qisuu.la

一,先新建一個新的資料夾,名字自取,用於存放py檔案和爬取的資料

二,找到要爬取的網站的ur和你自己瀏覽器的請求頭,(因為我是以奇書網為例,瀏覽器為火狐瀏覽器)

        url= ‘https://www.qisuu.la/soft/sort01/’

      請求頭:‘User_Anger’: 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0'

(  找不到請求頭的可以直接拿去用)

三,開始爬取

1建立一個類,並.定義初始化函式,在初始化函式中定義好url和請求頭,由於下面要用到的資料較多,所以我定義的比較多,程式碼如下:

class NovelSpider(object):
    def __init__(self):
      self.url = 'https://www.qisuu.la/soft/sort01/'
      self.html = ''
      self.herders = {
            'User_Anger': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0'
        }
      self.total = 0
      self.count = 0
      self.retry_count = 0
        #建立Excel表格,用於儲存爬取的資料
      self.workbook = xlwt.Workbook(encoding='utf-8')
      self.sheet = self.workbook.add_sheet('novel_data')
      self.create_excel()

 2,建立Excel表,用於儲存爬取的資料

    def create_excel(self):
        self.sheet.write(0, 0, '小說名稱')
        self.sheet.write(0, 1, '點選次數')
        self.sheet.write(0, 2, '文字大小')
        self.sheet.write(0, 3, '書籍型別')
        self.sheet.write(0, 4, '更新日期')
        self.sheet.write(0, 5, '連載狀態')
        self.sheet.write(0, 6, '書籍作者')
        self.sheet.write(0, 7, '執行環境')
        self.sheet.write(0, 8, '小說簡介')
        self.sheet.write(0, 9, '下載地址')

3.模擬瀏覽器傳送請求,並接受返回的網頁原始碼,程式碼如下:

        def get_html(self, url):

        # 1.建立request物件,設定隨機請求頭
            req = request.Request(url=url, headers={
            'User-Agent': choice(self.ua_list)
        })
        try:
            self.retry_count += 1
            # 2.發起請求
            response = request.urlopen(req)
            # 3.接收資料
            self.html = response.read().decode('utf-8')
        except Exception as e:
            # 請求重試次數大於3,放棄該請求
            if self.retry_count > 3:
                print('請求失敗,地址:{}'.format(url))
                return
            # 重新發送請求
            print('請求資料失敗,正在嘗試重新連線...')
            self.get_html(url)
        else:
            # 歸0
            self.retry_count = 0

4.用正則表示式來解析網頁原始碼,並獲取小說詳情頁的連結,程式碼如下:

    def get_story_link(self):
        """獲取小說頁面連結"""
         #用正則從網頁原始碼中匹配小說頁面的連結
        pattern = re.compile(r'<li>.*?<div class="s.*?<a href="(.*?)">.*?"',re.S)
        res = re.findall(pattern,self.html)
        if res:
            """遍歷小說連結"""
            for x in res:
                #拼接新的連結,並傳入請求函式中
                url =self.url2 + x
                self.get_html(url)
                # #解析小說網頁資料
                self.parse_story()

5.解析小說網頁的資料,拿到自己想要的資料,程式碼如下:

(我們在這裡找了小說資訊的部分資料)

    def parse_story(self):
        """解析小說頁面的資料"""
        #運用正則來匹配自己想要的資料
        pattern = re.compile(r'.*?detail_right".*?h1>(.*?)</h1.*?ul>.*?<li.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?showInfo".*?p>(.*?)</p.*?', re.S)
        res = re.findall(pattern, self.html)
        # for x in res:
        # print(res)
        #提取資料
        title = res[0][0]
        click_num = res[0][1]
        size = res[0][2]
        novel_type =res[0][3]
        datetime =res[0][4]
        status =res[0][5]
        author =res[0][6]
        run_sys =res[0][7]
        content =res[0][8]
        #儲存資料 

self.save_date(title,click_num,size,novel_type,datetime,status,author,run_sys,content)



6,儲存資料,儲存到Excel表中,程式碼如下:

    def write_to_excel(self, idx, data):
        #封裝寫入表格的函式
        print(idx, data)
        self.sheet.write(self.count, idx, data)

    def save_data(self, *args):
        self.count += 1
        print('正在儲存第{}本小說:{}'.format(self.count, args[0]))
        # 1.基礎寫法
        self.sheet.write(self.count, 0, args[0])
        self.sheet.write(self.count, 1, args[1])
        self.sheet.write(self.count, 2, args[2])
        self.sheet.write(self.count, 3, args[3])
        self.sheet.write(self.count, 4, args[4])
        self.sheet.write(self.count, 5, args[5])
        self.sheet.write(self.count, 6, args[6])
        self.sheet.write(self.count, 7, args[7])
        self.sheet.write(self.count, 8, args[8])
        self.sheet.write(self.count, 9, args[9])

        # 2.進階寫法
        # *args 將元組看做一個容器,進行列舉
        # for idx, data in enumerate(args):
        #     if idx == 8:
        #         data = data.replace('&#12288;', ' ')
        #
        #     self.write_to_excel(idx, data)

        # 3.終極寫法
        # rs = map(lambda idx, data: self.sheet.write(self.count, idx, data), range(10), args)
        # for x in rs:
        #     pass
        self.workbook.save('小說資料.xls')

7.執行函式:

def run(self):            
            #想獲取多少頁的資料 就把range函式裡面的後面的數字改一下
          for x in range(1, 11):
                print(''.center(50,'*'))
                print('正在獲取第%s頁資料,請稍後....' % (x))

                # 拼接完整的url地址
                url = t_info[0] + 'index_{}.html'.format(x)
                # 獲取該頁原始碼
                self.get_html(url)
                # 解析原始碼,提取資料
                self.parse_index()
                break

        self.workbook.save('小說資料.xls')

以上就是爬取小說的全部步驟,全部程式碼如下:

# -*- coding: utf-8 -*-
__author__ = 'wj'
__date__ = '2018/8/10 9:08'
import re
from random import choice
from urllib import request

import xlwt


class NovelSpider(object):

    def __init__(self):

        self.url = 'https://www.qisuu.la/soft/sort01/'
        self.html = ''
        self.ua_list = [
            'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2',
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36'
        ]
        self.total = 0
        self.count = 0
        self.retry_count = 0
        self.workbook = xlwt.Workbook(encoding='utf-8')
        self.sheet = self.workbook.add_sheet('novel_data')
        self.create_excel()

    def create_excel(self):
        self.sheet.write(0, 0, '小說名稱')
        self.sheet.write(0, 1, '點選次數')
        self.sheet.write(0, 2, '文字大小')
        self.sheet.write(0, 3, '書籍型別')
        self.sheet.write(0, 4, '更新日期')
        self.sheet.write(0, 5, '連載狀態')
        self.sheet.write(0, 6, '書籍作者')
        self.sheet.write(0, 7, '執行環境')
        self.sheet.write(0, 8, '小說簡介')
        self.sheet.write(0, 9, '下載地址')

    def get_html(self, url):

        # 1.建立request物件,設定隨機請求頭
        req = request.Request(url=url, headers={
            'User-Agent': choice(self.ua_list)
        })
        try:
            self.retry_count += 1
            # 2.發起請求
            response = request.urlopen(req)
            # 3.接收資料
            self.html = response.read().decode('utf-8')
        except Exception as e:
            # 請求重試次數大於3,放棄該請求
            if self.retry_count > 3:
                print('請求失敗,地址:{}'.format(url))
                return
            # 重新發送請求
            print('請求資料失敗,正在嘗試重新連線...')
            self.get_html(url)
        else:
            # 歸0
            self.retry_count = 0

    def get_total(self):
        # 1.獲取原始碼
        self.get_html(self.url)
        # 2.準備正則
        pattern = re.compile(r'<div class="tspage.*?/(.*?)&nbsp;', re.S)
        # 3.搜尋
        rs = re.search(pattern, self.html)

        if rs:
            self.total = int(rs.group(1))
            print(self.total)

    def parse_index(self):
        # 1.準備正則
        pattern = re.compile(r'<li.*?<div.*?class="s".*?<a href="(.*?)"', re.S)
        # 2.搜尋資料
        results = re.findall(pattern, self.html)
        # 3.迴圈遍歷每一個小連結
        for link in results:
            url = 'https://www.qisuu.la' + link
            # 4.獲取詳情頁面的原始碼
            self.get_html(url)
            # 5.解析詳情頁面資料
            self.parse_detail()

    def parse_detail(self):

        #1 準備正則
        pattern = re.compile(r"""<div class="detail_right.*?<h1>(.*?)</h1.*?<li.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?:(.*?)<.*?<div class="showInfo".*?<p.*?>(.*?)</p.*?get_down_url.*?,'(.*?)'""", re.S)

        results = re.findall(pattern, self.html)

        # 1.提取資料
        title = results[0][0]
        click_num = results[0][1]
        file_size = results[0][2]
        novel_type = results[0][3]
        datetime = results[0][4]
        status = results[0][5]
        author = results[0][6]
        run_sys = results[0][7]
        description = results[0][8].replace('&#12288;',' ')
        download = results[0][9]
        # 儲存資料
        self.save_data(title, click_num, file_size, novel_type, datetime, status, author, run_sys, description, download)

    # 封裝寫入excel表格的函式
    def write_to_excel(self, idx, data):
        print(idx, data)
        self.sheet.write(self.count, idx, data)

    def save_data(self, *args):
        self.count += 1
        print('正在儲存第{}本小說:{}'.format(self.count, args[0]))
        # 1.基礎寫法
        self.sheet.write(self.count, 0, args[0])
        self.sheet.write(self.count, 1, args[1])
        self.sheet.write(self.count, 2, args[2])
        self.sheet.write(self.count, 3, args[3])
        self.sheet.write(self.count, 4, args[4])
        self.sheet.write(self.count, 5, args[5])
        self.sheet.write(self.count, 6, args[6])
        self.sheet.write(self.count, 7, args[7])
        self.sheet.write(self.count, 8, args[8])
        self.sheet.write(self.count, 9, args[9])

        # 2.進階寫法
        # *args 將元組看做一個容器,進行列舉
        # for idx, data in enumerate(args):
        #     if idx == 8:
        #         data = data.replace('&#12288;', ' ')
        #
        #     self.write_to_excel(idx, data)

        # 3.終極寫法
        # rs = map(lambda idx, data: self.sheet.write(self.count, idx, data), range(10), args)
        # for x in rs:
        #     pass
        self.workbook.save('小說資料.xls')

    def parse_type(self):

        pattern = re.compile(r'<div class="nav">(.*?)</div>', re.S)
        res = re.search(pattern, self.html)

        if res:
            html = res.group(1)
            results = re.findall(re.compile(r'<a.*? href="(.*?)".*?>(.*?)</a>',re.S), html)

            # 返回所有分類地址
            # x是一個小元組
            return map(lambda x: ('https://www.qisuu.la'+x[0],x[1]), results[1:])

    def run(self):
        # 獲取總頁碼
        self.get_total()
        # 獲取所有分類地址
        types = self.parse_type()

        for t_info in types:
            # print(t_info)
            print('正在爬取{}下的小說.....'.format(t_info[1]))
            for x in range(1, self.total + 1):
                print(''.center(50,'*'))
                print('正在獲取%s下的第%s頁資料,請稍後....' % (t_info[1], x))

                # 拼接完整的url地址
                url = t_info[0] + 'index_{}.html'.format(x)
                # 獲取該頁原始碼
                self.get_html(url)
                # 解析原始碼,提取資料
                self.parse_index()
                break

        self.workbook.save('小說資料.xls')


if __name__ == '__main__':

    novel = NovelSpider()
    novel.run()