1. 程式人生 > >利用python爬蟲獲取豆瓣讀書資料建立書單

利用python爬蟲獲取豆瓣讀書資料建立書單

封面

0. 寫在前面

網路爬蟲:

A Web crawler, sometimes called a spider, is an Internet bot that systematically browses the World Wide Web, typically for the purpose of Web indexing (web spidering)

本文參考了網上教程、資料、程式碼,寫了一個小爬蟲,爬取豆瓣讀書上的書籍資訊,最終目的是建立一個基於標籤資訊的書單

1. 前期準備

1.1 依賴工具

python 3.6
以及python第三方庫:
    requests
    urllib
    re

1.2 網頁分析

1.2.1 抓取站點

目標網站:豆瓣讀書
豆瓣讀書首頁

https://book.douban.com/tag/小說?start=20&type=S

可知,tag代表圖書標籤型別,Type=S代表按照評分對圖書排序,而start=20代表該頁面第一本書的序號
則村上春樹標籤下圖書第三頁的url為:

https://book.douban.com/tag/村上春樹?start=40&type=S

1.2.2 Robots協議

開始寫爬蟲前,先確定目標網頁是否允許爬取相關頁面
呼叫urllib庫的robotparser模組,訪問https://book.douban.com/robots.txt

獲取豆瓣讀書的robots協議

from urllib.robotparser import RobotFileParser

UrlRobots = 'https://book.douban.com/robots.txt'

def GetRobotsTxt(url) :
    rp = RobotFileParser()
    rp.set_url(url)
    rp.read()
    print(rp.can_fetch('*', 'https://book.douban.com/tag/?view=type&icn=index-sorttags-all'))
    print(rp.can_fetch('*'
, 'https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4')) print(rp.can_fetch('*', 'https://book.douban.com/')) GetRobotsTxt(UrlRobots)

Robots協議為:

User-agent: *
Disallow: /subject_search
Disallow: /search
Disallow: /new_subject
Disallow: /service/iframe
Disallow: /j/
Sitemap: http://www.douban.com/sitemap_index.xml
Sitemap: http://www.douban.com/sitemap_updated_index.xml

User-agent: Wandoujia Spider
Disallow: /

程式返回結果為:

ture
ture
ture

則上述網站皆在可爬範圍內

1.2.3 分析程式碼

先從要抓取資料的網站程式碼裡提取需要的程式碼塊如下所示:

<li class="subject-item">
    <div class="pic">
      <a class="nbg" href="https://book.douban.com/subject/1057244/" 
  onclick="moreurl(this,{i:'0',query:'',subject_id:'1057244',from:'book_subject_search'})">
        <img class="" src="https://img1.doubanio.com/mpic/s1595557.jpg"
          width="90">
      </a>
    </div>
    <div class="info">
      <h2 class="">

  <a href="https://book.douban.com/subject/1057244/" title="邊城" 
  onclick="moreurl(this,{i:'0',query:'',subject_id:'1057244',from:'book_subject_search'})">
    邊城
  </a>

      </h2>
      <div class="pub">

  沈從文、黃永玉 卓雅 插圖. / 北嶽文藝出版社 / 2002-4 / 12.00元

      </div>

  <div class="star clearfix">
        <span class="allstar45"></span>
        <span class="rating_nums">8.6</span>

    <span class="pl">
        (73914人評價)
    </span>
  </div>

    <p>《邊城》是沈從文的代表作,寫於一九三三年至一九三四年初。這篇作品如沈從文的其他湘西作品,著眼於普通人、善良人的命運變遷,描摹了湘女翠翠陰差陽錯的生活悲劇,誠... </p>

      <div class="ft">
  <div class="collect-info">
  </div>
        <div class="cart-actions">
    <span class="buy-info">
      <a href="https://book.douban.com/subject/1057244/buylinks">
        紙質版 7.80 元起
      </a>
    </span>
          </div>
      </div>
    </div>
  </li>

其中我們可以提取到的資訊包含:

程式碼開始位置:<li class="subject-item">
程式碼結束位置:</li>
書籍相關資訊:圖書豆瓣網頁地址,圖書封面地址,書名,作者、譯者資訊,出版資訊,價格,評分,評價數目,內容簡介

由此可以寫出對應的正則表示式,從而提取出需要資料:

class="nbg" href="(.*?)".*?src="(.*?)".*?title="(.*?)".*?<div class="pub">\s*(.*?)\/.*?nums">(.*?)</span>.*?<p>(.*?)</p>

2. 程式碼

2.1 獲取網頁

在這個專案中,我人為地設定了每個標籤抓取5頁圖書內容,即100本書,並將每頁程式碼儲存至HtmlCode.txt中

def GetOneType(UrlLabel,Headers,Num):
    for i in range(5):
        print('正在抓取' + labels[Num] +'類的第' + str(i+1) + '頁')
        url = UrlLabel + '?start=' + str(i*20) + '&type=S'

        rp = requests.get(url, headers = Headers)

        with open("HtmlCode.txt", 'w', encoding = 'utf-8') as f:
            f.write(rp.text)
        ReEx(Num)
        time.sleep(3 + random.random())

2.2 正則表示式

獲取網頁程式碼後,進行正則表示式匹配分析,提取出有效資料,並儲存至對應txt文件中

def ReEx(Num):
    FileName = 'result' + str(Num) + '.txt'
    with open('HtmlCode.txt', 'r', encoding = 'utf-8') as file_re:
        content = file_re.read()
        STR = r'class="nbg" href="(.*?)".*?src="(.*?)".*?title="(.*?)".*?<div class="pub">\s*(.*?)\/.*?nums">(.*?)</span>.*?<p>(.*?)</p>'

        result = re.findall(STR, content, re.S|re.M)
        #print(result)

        with open(FileName, 'a', encoding = 'utf-8') as file_result:
            file_result.write(str(result))

2.3 main

分標籤爬取所有資料

#標籤內容可根據豆瓣標籤頁更改資料
labels = ['小說', '外國文學', '文學', '隨筆', '中國文學', '經典', '日本文學', '散文', '村上春樹']

def GetAllPages():
    for i in range(len(labels)):
        UrlLabel = 'https://book.douban.com/tag/' + labels[i]
        GetOneType(UrlLabel,Headers,i)
    print('抓取完成')

2.4 爬取結果

結果

小說.txt檔案裡部分資料:

    *   ('https://book.douban.com/subject/1770782/', 'https://img3.doubanio.com/mpic/s1727290.jpg', '追風箏的人', '[美] 卡勒德·胡賽尼 ', '8.9', '12歲的阿富汗富家少爺阿米爾與僕人哈桑情同手足。然而,在一場風箏比賽後,發生了一件悲慘不堪的事,阿米爾為自己的懦弱感到自責和痛苦,逼走了哈桑,不久,自己也跟... '),
    *   ('https://book.douban.com/subject/1008145/', 'https://img3.doubanio.com/mpic/s1070222.jpg', '圍城', '錢鍾書 ', '8.9', '《圍城》是錢鍾書所著的長篇小說。第一版於1947年由上海晨光出版公司出版。1949年之後,由於政治等方面的原因,本書長期無法在中國大陸和臺灣重印,僅在香港出... ')
    *   ('https://book.douban.com/subject/1082154/', 'https://img3.doubanio.com/mpic/s23836852.jpg', '活著', '餘華 ', '9.1', '地主少爺福貴嗜賭成性,終於賭光了家業一貧如洗,窮困之中的福貴因為母親生病前去求醫,沒想到半路上被國民黨部隊抓了壯丁,後被解放軍所俘虜,回到家鄉他才知道母親已... ')
    *   ('https://book.douban.com/subject/1200840/', 'https://img3.doubanio.com/mpic/s2335693.jpg', '平凡的世界(全三部)', '路遙 ', '9.0', '《平凡的世界》是一部現實主義小說,也是一部小說形式的家族史。作者濃縮了中國西北農村的歷史變遷過程,在小說中全景式地表現了中國當代城鄉的社會生活。在近十年的廣... ')
    *   ('https://book.douban.com/subject/25862578/', 'https://img3.doubanio.com/mpic/s27264181.jpg', '解憂雜貨店', '[日] 東野圭吾 ', '8.6', '現代人內心流失的東西,這家雜貨店能幫你找回——\n僻靜的街道旁有一家雜貨店,只要寫下煩惱投進捲簾門的投信口,第二天就會在店後的牛奶箱裡得到回答。\n因男友身患絕... ')

3. 總結

本文只是使用了爬蟲技術中的一些最基本操作,完成提取並存儲豆瓣讀書的資料
但是不足的地方在於未使用IP代理、cookie等反“反爬蟲”措施,僅使用延時手段,避免ip地址被封
且只提取出了資料,未進行資料視覺化。這些都是亟待完善的地方