Python爬蟲實戰(zhàn):爬取全站小說排行榜

喜歡看小說的騷年們都知道梧宫,總是有一些小說讓人耳目一新,不管是仙俠還是玄幻蛇尚,前面更了幾十章就成功圈了一大波粉絲芽唇,成功攀上飆升榜,熱門榜等各種榜取劫,扔幾個栗子出來:

作為一個開發(fā)者披摄,有一個學習的氛圍跟一個交流圈子特別重要這是一個我的python交流群:984632579,不管你是小白還是大牛歡迎入駐 勇凭,討論技術疚膊, 大家一起交流學習成長!

新筆趣閣是廣大書友最值得收藏的網(wǎng)絡小說閱讀網(wǎng),網(wǎng)站收錄了當前......我就不打廣告了(其他滿足下文條件的網(wǎng)站也行虾标,之前已經(jīng)有做過簡單爬取章節(jié)的先例了寓盗,但效果不太理想,有很多不需要的成分被留下了璧函,來鏈接:http://www.bxquge.com/傀蚌。我們本文就爬取這個網(wǎng)站的上千本小說。重點在和大家一起分享一些爬蟲的思路和一些很常遇到的坑蘸吓。

本文的行文脈絡:

1善炫、先構造一個單本的小爬蟲練練手;

2库继、簡要分享一下安裝MongoBD數(shù)據(jù)庫時的幾個易錯問題箩艺;

3、運用Scrapy框架爬取新筆趣閣全站排行榜宪萄。

全部代碼可以在公眾號后臺回復“小說”獲取艺谆。

一、爬取單本小說

爬取該網(wǎng)站相對來講還是很容易的拜英,打開編輯器(推薦使用PyCharm静汤,功能強大),首先引入模塊urllib.request(Python2.x的引入urllib和urllib2即可,待會我把2.x的也寫出來給大家看看)虫给,給出網(wǎng)站URL藤抡,寫下請求,再添加請求頭(雖然這個網(wǎng)站不封號抹估,但作者建議還是要養(yǎng)成每次都寫請求頭的習慣杰捂,萬一那天碰到像豆瓣似的網(wǎng)站,一不留神就把你封了)話不多說棋蚌,直接上代碼:

#coding:utf-8import urllib.requesturl = "http://www.bxquge.com/3_3619/10826.html"headers = {'User-Agent':? ? ? ? ? ? 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 \? ? ? ? ? ? (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'}request = urllib.request.Request(url,headers=headers)

然后再將請求發(fā)送出去嫁佳,定義變量response,用read()方法觀察谷暮,注意將符號解碼成utf-8的形式蒿往,省的亂碼:

#coding:utf-8import urllib.requesturl ="http://www.bxquge.com/3_3619/10826.html"headers = {'User-Agent':? ? ? ? ? ? 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 \? ? ? ? ? ? (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'}request = urllib.request.Request(url,headers=headers)response = urllib.request.urlopen(request)html = response.read()html = html.decode("utf-8")print(html)

打印一下看結果:

看到這么一大條就對嘍,對比一下網(wǎng)頁源碼湿弦,發(fā)現(xiàn)是一致的瓤漏。

這步觀察很重要,因為這就說明該網(wǎng)站沒有使用AJAX異步加載颊埃,否則就要開始抓包的工作了蔬充,這個我們留著分析動態(tài)網(wǎng)站時候再說。建議大家在沒有更好的方法時使用班利。之前記得確實有直接判斷的方法饥漫,然而一不小心忘記了,有知道的讀者還請發(fā)給我哦罗标。

我們現(xiàn)在得到了網(wǎng)站的response庸队,接下來就是對我們想要獲取的數(shù)據(jù)進行解析、提取闯割,但等等彻消,考慮到我們要爬取大量小說,不搞一個數(shù)據(jù)庫存儲真是太失敗了宙拉,作者推薦MongoDB數(shù)據(jù)庫宾尚,屬于NOSQL類型數(shù)據(jù)庫,以文檔存儲為主谢澈,這里用來爬小說真是太適合不過了煌贴。但安裝起來需要一定的程序,想要試著做做的騷年可以參考一下下載和安裝教程澳化,參考鏈接:http://blog.csdn.net/u011262253/article/details/74858211崔步,在安裝好后為方便啟動,可以添加環(huán)境變量缎谷,但這里有個坑,你要先打開mongod(注意是mongodb,別一上來就打開mongo)列林,然后需要準確添加dbpath路徑瑞你,不然打開很容易就會失敗,上圖上圖:

失敗狀態(tài)

成功狀態(tài)

添加路徑后成功連接希痴,出現(xiàn)waiting for connections on port 27017者甲,則表示數(shù)據(jù)庫連接成功,而后就不要關掉這個終端了砌创,只有保持數(shù)據(jù)庫是連接的虏缸,才可運行MongoDB數(shù)據(jù)庫(不然報錯你都不知道自己是怎么死的)

好了,連接好數(shù)據(jù)庫后嫩实,我們將數(shù)據(jù)庫與編輯器進行交互鏈接刽辙,位置很隱秘,在File>>Settings>>Plugins下添加組件Mongo Plugin甲献,沒有就下載一個:

盜個圖

我們在編輯器內編寫代碼宰缤,引入Python專門用來與MongoDB交互的模塊pymongo,然后在最上面鏈接MongoDB數(shù)據(jù)庫的端口晃洒,默認是27017慨灭,我們先創(chuàng)建一個叫做reading的數(shù)據(jù)庫,然后在reading內新建一個叫做sheet_words的數(shù)據(jù)表球及,代碼如下:

#coding:utf-8import pymongoimport urllib.requestclient = pymongo.MongoClient('localhost',27017)reading = client['reading']sheet_words = reading['sheet_words']

我們先找一個叫做《修羅武神》的小說來練練手氧骤,個人來講,我很討厭看小說時來回的翻頁吃引,有時候還跳出廣告语淘,這時候我還得返回去重新翻頁,作為一名懶得不行的懶人际歼,我想到要是把整部小說放進一個文檔里再看不就好了么惶翻,但要是一章一章的復制粘貼我想還是算了吧,這時候你就知道爬蟲是有多么便捷了鹅心。好吕粗,現(xiàn)在我們要做的是把《修羅武神》這部小說完整的爬取下來,并在數(shù)據(jù)庫中備份旭愧。我們回到剛才停留的地方颅筋,在得到response后,我們應該選用一種方法來解析網(wǎng)頁输枯,一般的方法有re,xpath,selector(css),建議新手使用xpath而不是re,一是因為re用不好很容易導致錯誤议泵,“當你決定用正則表達式解決問題時,你有了兩個問題桃熄∠瓤冢”,相比較xpath才是步驟明確,十分穩(wěn)妥碉京;二是在Firefox厢汹,Chrome等瀏覽器中可以直接復制xpath路徑,大大的減少了我們的工作量谐宙,上圖:

如果你決定使用xpath之后烫葬,我們需要從lxml中引入etree模塊,然后就可以用etree中的HTML()方法來解析網(wǎng)頁了,從網(wǎng)頁>檢察元素(F12)中復制下來我們所需數(shù)據(jù)的路徑凡蜻,我選擇的是小說每章的標題和內容搭综,上圖,上圖:

路徑//div[@class="readAreaBox content"]/h1/text()

路徑/html/body/div[4]/div[2]/div[2]/div[1]/div[2]/text()

注意注意划栓,又來一個坑兑巾,當你復制xpath時得到的是這個東東:

//div[@class="readAreaBox content"]/h1

和這個東東;

/html/body/div[4]/div[2]/div[2]/div[1]/div[2]

但你需要的是這個路徑里的文本text,故我們需要另外添加具體文本:/text()茅姜,然后就像上面那樣啦闪朱。上代碼,查數(shù)據(jù):

url ='http://www.17k.com/list/493239.html'response = urllib.request.urlopen(url)html = response.read().decode("utf-8")tree = etree.HTML(html)dom = tree.xpath('//a[@target="_blank"][@title]/@href')foriindom:data = {'words':"http://www.17k.com"+ i? ? }? ? sheet_words.insert_one(data)# $lt/$lte/$gt/$gte/$ne钻洒,依次等價于/>=/!=奋姿。(l表示less g表示greater e表示equal n表示not? )try:? ? os.mkdir("修羅武神小說")except FileExistsError:? ? passos.chdir("修羅武神小說")for item in sheet_words.find():? ? filename = "修羅武神"? ? with open( filename,"a+") as f:? ? ? ? contents = urllib.request.urlopen(item["words"])? ? ? ? responses = contents.read().decode("utf-8")? ? ? ? trees = etree.HTML(responses)? ? ? ? title = trees.xpath('//div[@class="readAreaBox content"]/h1/text()')? ? ? ? word = trees.xpath("/html/body/div[4]/div[2]/div[2]/div[1]/div[2]/text()")? ? ? ? a = ''.join(title)? ? ? ? b = ''.join(word)? ? ? ? f.write(a)? ? ? ? f.write(b)? ? ? ? #print(''.join(title))

小說有點大,一共是三千五百章素标,等個大約4-7分鐘吧称诗,打開文件夾《修羅武神小說》,就可以看到我們下載好的無需翻頁的一整部小說头遭,數(shù)據(jù)庫內頁備份好了每章的鏈接寓免,它自動從零開始排的,就是說你要看第30章就得打開序號為29的鏈接计维,這個調一下下載時的順序就好了袜香,作者很懶,想要嘗試下的讀者可以自行更改鲫惶。

小說文本

數(shù)據(jù)庫連接

看看蜈首,感覺還不錯吧,好的小例子講完了欠母,接下來我們準備進入正題欢策。

我們要像上面的例子那樣爬取整個網(wǎng)站,當然這里就不再建議使用普通的編輯器來來執(zhí)行了赏淌,聰明的讀者已經(jīng)發(fā)現(xiàn)踩寇,一部小說爬了4分鐘,那么上千本不說六水,單單是一組排行榜里的100本就夠爬好一會了俺孙,這就顯示出Scripy框架的作用辣卒,用專門的Scripy框架寫工程類爬蟲絕對快速省力,是居家寫蟲的必備良藥哇鼠冕。

二添寺、爬取小說榜所有小說

首先安裝Scrapy的所有組件胯盯,建議除pywin32以外都用pip安裝,不會的話度娘吧懈费,很簡單的,pywin32需要下載與你所用Python版本相同的安裝文件博脑。

來連接:https://sourceforge.net/projects/pywin32/

Scrapy插件安裝成功

然后還是老規(guī)矩憎乙,不想每次終端運行都一點一點找路徑的話,就將根目錄添加到環(huán)境變量叉趣,然后打開終端泞边,我們測試一下是否安裝成功:

Scrapy安裝成功

好,安裝完畢后疗杉,打開終端阵谚,新建一個Scrapy工程,這里你可以根據(jù)索引烟具,選擇使用Scrapy的各種功能梢什,這里不一一詳解了,D盤內已經(jīng)出現(xiàn)了我們建立好的Scrapy工程文件夾:

打開文件夾朝聋,我們會看到Scrapy框架已經(jīng)自動在reading文件夾中放置了我們所需的一切原材料:

打開內部reading文件夾嗡午,就可以在spiders文件夾中添加爬蟲py代碼文件了:

我們這里定向爬小說排行榜,除了我們寫的spider文件冀痕,還要在items.py中定義我們要爬取的內容集荔睹,有點像詞典一樣,名字可以隨便取言蛇,但已有的繼承類scrapy.Item可不能改僻他,這是Scrapy內部自定義的類,改了它可找不到腊尚,spider就用我們上面抓取單本再加一個for循環(huán)就OK了吨拗,十分簡單,一言不合就上圖:

# -*- coding: utf-8 -*-import scrapyimport urllib2from lxml import etreeimport osfrom reading.items import ReadingSpiderItemimport sysreload(sys)sys.setdefaultencoding('utf-8')class ReadingspiderSpider(scrapy.Spider):? ? name = 'bigreadingSpider'#爬蟲名? ? allowed_domains = ['http://www.xinbiquge.com/']#總域? ? start_urls = ['http://www.bxquge.com/paihangbang/']#起始頁? ? def parse(self, response):? ? ? ? sel = scrapy.selector.Selector(response)#解析域? ? ? ? for i in range(2,10):? ? ? ? ? ? path = '//*[@id="main"]/table[' +str(i)+ ']/tbody/tr[1]/td[2]/span'#排行榜路徑? ? ? ? ? ? sites = sel.xpath(path)? ? ? ? ? ? items = []? ? ? ? ? ? for site in sites:#按9個排行榜爬取? ? ? ? ? ? ? ? item = ReadingSpiderItem()? ? ? ? ? ? ? ? path_list_name = '//*[@id="main"]/table[' +str(i)+ ']/tbody/tr[1]/td[2]/span/text()'? ? ? ? ? ? ? ? item['list_name'] = site.xpath(path_list_name).extract()#排行榜名稱? ? ? ? ? ? ? ? try:? ? ? ? ? ? ? ? ? ? os.mkdir(item['list_name'][0])? ? ? ? ? ? ? ? except IOError:? ? ? ? ? ? ? ? ? ? pass? ? ? ? ? ? ? ? os.chdir(item['list_name'][0])? ? ? ? ? ? ? ? for li in range(1,21):? ? ? ? ? ? ? ? ? ? title = '//*[@id="tb' + str(i-1) + '-1"]/ul/li['+str(li)+']/a/text()'? ? ? ? ? ? ? ? ? ? item['name'] = site.xpath(title).extract()#書名? ? ? ? ? ? ? ? ? ? url = 'http://www.bxquge.com/'? ? ? ? ? ? ? ? ? ? path_link = '//*[@id="tb'+ str(i-1) +'-1"]/ul/li[' + str(li) + ']/a/@href'#書目鏈接? ? ? ? ? ? ? ? ? ? item['link'] = site.xpath(path_link).extract()? ? ? ? ? ? ? ? ? ? full_url = url + item['link'][0]? ? ? ? ? ? ? ? ? ? headers = {'User-Agent':? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 \? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'}? ? ? ? ? ? ? ? ? ? ? ? #request = urllib2.Request(''.join(item['link']),headers=headers)? ? ? ? ? ? ? ? ? ? request = urllib2.Request(full_url,headers=headers)? ? ? ? ? ? ? ? ? ? try:? ? ? ? ? ? ? ? ? ? ? ? ? os.mkdir(item['name'][0])? ? ? ? ? ? ? ? ? ? except IOError:? ? ? ? ? ? ? ? ? ? ? ? pass? ? ? ? ? ? ? ? ? ? os.chdir(item['name'][0])? ? ? ? ? ? ? ? ? ? response = urllib2.urlopen(request).read().decode('utf-8')? ? ? ? ? ? ? ? ? ? tree = etree.HTML(response)? ? ? ? ? ? ? ? ? ? for j in range(1,11):? ? ? ? ? ? ? ? ? ? ? ? ? ? path_title = '//*[@id="list"]/dl/dd['+ str(j) +']/a/text()'? ? ? ? ? ? ? ? ? ? ? ? ? ? item['title'] = tree.xpath(path_title)#章節(jié)名? ? ? ? ? ? ? ? ? ? ? ? ? ? path_words_page = '//*[@id="list"]/dl/dd['+ str(j) +']/a/@href'? ? ? ? ? ? ? ? ? ? ? ? ? ? word_page = tree.xpath(path_words_page)? ? ? ? ? ? ? ? ? ? ? ? ? ? try:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? url_words = full_url +? word_page[0]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? request_words = urllib2.Request(url_words,headers=headers)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? response_words = urllib2.urlopen(request_words).read().decode('utf-8')? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tree_words = etree.HTML(response_words)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? path_words = '//*[@id="content"]/text()'? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? item['words'] = tree_words.xpath(path_words)#前20章內容? ? ? ? ? ? ? ? ? ? ? ? ? ? except urllib2.HTTPError:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pass? ? ? ? ? ? ? ? ? ? ? ? ? ? items.append(item)? ? ? ? ? ? ? ? ? ? ? ? ? ? try:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? filename = r''.join(item['title'][0]) + '.json'? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? with open(filename,"a+") as f:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? a = ''.join(item['title'])? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? b = ''.join(item['words'])? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? f.write(a)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? f.write(b)? ? ? ? ? ? ? ? ? ? ? ? ? ? except IOError:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pass? ? ? ? ? ? ? ? ? ? path_now = os.getcwd()? ? ? ? ? ? ? ? ? ? path_last = os.path.dirname(path_now)? ? ? ? ? ? ? ? ? ? os.chdir(path_last)? ? ? ? ? ? ? ? path_now = os.getcwd()? ? ? ? ? ? ? ? path_last = os.path.dirname(path_now)? ? ? ? ? ? ? ? os.chdir(path_last)

Python的確是一個激動人心的功能強大的語言跟伏。Python那種性能和特性的恰到好處的組合讓使用Python編程既有趣又簡單丢胚。

好了就不說廢話了,現(xiàn)在給你們分享我的Python學習資料嘍受扳!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末携龟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子勘高,更是在濱河造成了極大的恐慌峡蟋,老刑警劉巖坟桅,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蕊蝗,居然都是意外死亡仅乓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門蓬戚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夸楣,“玉大人,你說我怎么就攤上這事子漩≡バ” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵幢泼,是天一觀的道長紧显。 經(jīng)常有香客問我,道長缕棵,這世上最難降的妖魔是什么孵班? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮招驴,結果婚禮上篙程,老公的妹妹穿的比我還像新娘。我一直安慰自己忽匈,他們只是感情好房午,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著丹允,像睡著了一般萎馅。 火紅的嫁衣襯著肌膚如雪伟桅。 梳的紋絲不亂的頭發(fā)上鳄橘,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天讳苦,我揣著相機與錄音,去河邊找鬼批狐。 笑死扇售,一個胖子當著我的面吹牛,可吹牛的內容都是我干的嚣艇。 我是一名探鬼主播承冰,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼食零!你這毒婦竟也來了困乒?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤贰谣,失蹤者是張志新(化名)和其女友劉穎娜搂,沒想到半個月后迁霎,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡百宇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年考廉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片携御。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡昌粤,死狀恐怖,靈堂內的尸體忽然破棺而出因痛,到底是詐尸還是另有隱情婚苹,我是刑警寧澤岸更,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布鸵膏,位于F島的核電站,受9級特大地震影響怎炊,放射性物質發(fā)生泄漏谭企。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一评肆、第九天 我趴在偏房一處隱蔽的房頂上張望债查。 院中可真熱鬧,春花似錦瓜挽、人聲如沸盹廷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俄占。三九已至,卻和暖如春淆衷,著一層夾襖步出監(jiān)牢的瞬間缸榄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工祝拯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留甚带,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓佳头,卻偏偏與公主長得像鹰贵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子康嘉,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內容

  • scrapy學習筆記(有示例版) 我的博客 scrapy學習筆記1.使用scrapy1.1創(chuàng)建工程1.2創(chuàng)建爬蟲模...
    陳思煜閱讀 12,702評論 4 46
  • http header 消息通常被分為4個部分:general header即頭部, request header...
    徐薇薇閱讀 32,008評論 0 5
  • Core Animation 項目中實現(xiàn)動畫可以很好的展示我們的app 讓我們的app更具吸引力 文章目錄 UIV...
    奧卡姆剃須刀閱讀 638評論 2 6
  • 一個有明確目標的人碉输,即使每天工作十多個小時還是會為了他的目標不斷努力。 就我而言凄鼻,我現(xiàn)在每天工作八小時腊瑟,可是下了班...
    小小郁閱讀 111評論 0 1
  • 一闰非,你必須明確薪資談判只是面試當中的一個環(huán)節(jié) 談薪只是面試的一部分膘格,談薪并不意味著你掌握了主動權。所以仍然需要謹慎...
    傲邪云閱讀 2,027評論 0 0