摘要:不過不用擔心,中有很多非常優(yōu)秀的爬蟲框架,比如我們接下來要學習到的。結(jié)合以上分析我們基本確定了本次爬蟲的各個路線入口,接下來我們就開始通過程序來實現(xiàn)本次的目標。這里我們的目的是建立一種寫爬蟲的思路,而不在于怎么使用工具來爬數(shù)據(jù)。
概述
在上一篇文章《爬蟲學習之一個簡單的網(wǎng)絡爬蟲》中我們對爬蟲的概念有了一個初步的認識,并且通過Python的一些第三方庫很方便的提取了我們想要的內(nèi)容,但是通常面對工作當作復雜的需求,如果都按照那樣的方式來處理效率非常的低,這通常需要你自己去定義并實現(xiàn)很多非?;A的爬蟲框架上的功能,或者需要組合很多Python第三方庫來做。不過不用擔心,Python中有很多非常優(yōu)秀的爬蟲框架,比如我們接下來要學習到的Scrapy。Scrapy官方有很經(jīng)典的入門文檔說明,這一篇僅僅是通過一個簡單的實例來了解Scrapy這個庫是如何來進行網(wǎng)絡內(nèi)容提取的,更深入的學習請閱讀Scrapy官方文檔。
建立目標同樣在做任何事情之前都需要明確目標,那這次我們的目標是爬取一些技術性的文章并存儲到數(shù)據(jù)庫中。這就需要有目標網(wǎng)址和數(shù)據(jù)庫結(jié)構(gòu),數(shù)據(jù)庫我們選擇使用MySql,目標網(wǎng)站我們找了一個叫腳本之家的內(nèi)容站。我們這里首先準備好一張用于存儲文章的表結(jié)構(gòu):
CREATE TABLE `articles` ( `id` mediumint(8) AUTO_INCREMENT NOT NULL, `title` varchar(255) DEFAULT NULL, `content` longtext, `add_date` int(11) DEFAULT 0, `hits` int(11) DEFAULT "0", `origin` varchar(500) DEFAULT "", `tags` varchar(45) DEFAULT "", PRIMARY KEY (`id`), KEY `add_date` (`add_date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;分析目標結(jié)構(gòu)
這里我們首先需要爬取得入口是“網(wǎng)絡編程”這個節(jié)點,主入口網(wǎng)址為(http://www.jb51.net/list/index_1.htm) 打開這個網(wǎng)站我們通過Chrome或者其他瀏覽器的查看元素來分析當前頁面的HTML語義結(jié)構(gòu),如下圖所示:
從圖中紅色框線的部分可以看出,這里是我們需要在“網(wǎng)絡編程”這個節(jié)點下需要提取的所有文章的主分類入口,通過這些入口可以進去到不同文章分類的列表中。所以根據(jù)初步結(jié)構(gòu)分析,我們得出本次爬蟲的爬取路線為:
從主入口進去 -> 提取當前入口中的所有分類 -> 通過分類入口進入到分類列表 -> 通過列表進入到文章頁
分類入口確定了接下來看看我們的分類列表,隨意點開一個分類入口,打開列表如下圖所示:
這里我框出了兩個主要部分,第一個是文章的標題,第二個是分頁,文章對應的URL就是我們接下來需要爬取文章內(nèi)容的入口,這里需要注意的是分頁的處理,通過分頁的最后一頁我們可以知道當前這類列表共有多少頁文章。結(jié)合以上分析我們基本確定了本次爬蟲的各個路線入口,接下來我們就開始通過程序來實現(xiàn)本次的目標。
實現(xiàn)爬蟲在實現(xiàn)爬蟲之前我們通過一張圖來對Scrapy有個基本的認識,為了保持本章內(nèi)容的簡潔性,我們這里暫時不會討論Item Pipeline部分,Scrapy架構(gòu)圖如下所示(圖片來自網(wǎng)絡):
從圖中可以很清晰的看到Scrapy所包含的幾大塊,下面我們通過代碼來演示我們所用到的基礎功能部分。
主要依賴第三方庫:
web.py web框架,這里只用到了database部分,將來會用來進行內(nèi)容展示
scrapy 爬蟲框架,這里只用到了最基本的內(nèi)容提取
這里還會用到一些xpath相關知識,請自行Google了解xpath語法
# -*- coding:utf-8 -*- """by sudo rm -rf http://imchenkun.com""" import scrapy from scrapy.http import Request import web import time db = web.database(dbn="mysql", host="127.0.0.1", db="imchenkun", user="root", pw="root") # 允許的站點域 allow_domain = "jb51.net" base_url = "http://www.jb51.net" # 列表頁 list_url = "http://www.jb51.net/list/list_%d_%d.htm" # 列表分頁 list_page = 1 # 文章頁 crawl_url = "http://www.jb51.net/article/%d.htm" class JB51Spider(scrapy.Spider): name = "jb51" start_urls = [ "http://www.jb51.net/list/index_1.htm" ] cate_list = [] def parse(self, response): cate_id = response.selector.xpath("http://div[@class="index_bor clearfix"]/div[@class="index_con"]/span/a/@href").re("(d+)")[::2] for id in cate_id: cate_url = list_url % (int(id), 1) yield Request(cate_url, callback=self.parse_page) def parse_page(self, response): _params = response.selector.xpath("http://div[@class="dxypage clearfix"]/a[last()]/@href").re("(d+)") cate_id = int(_params[0]) # 分類編號 count = int(_params[1]) # 總頁數(shù) article_urls = response.selector.xpath("http://div[@class="artlist clearfix"]/dl/dt/a/@href").extract() # 處理第一頁 for article_url in article_urls: yield Request(base_url + article_url, callback=self.parse_article) # 處理其他頁 for page in range(1, count): url = (list_url % (cate_id, page + 1)) yield Request(url, callback=self.parse_list) def parse_list(self, response): """解析文章列表""" article_urls = response.selector.xpath("http://div[@class="artlist clearfix"]/dl/dt/a/@href").extract() for article_url in article_urls: yield Request(base_url + article_url, callback=self.parse_article) def parse_article(self, response): """解析文章內(nèi)容""" title = response.selector.xpath("http://div[@class="title"]/h1/text()").extract()[0] content = response.selector.xpath("http://div[@id="content"]").extract()[0] tags = ",".join(response.selector.xpath("http://div[@class="tags mt10"]/a/text()").extract()) results = db.query("select count(0) as total from articles where origin=$origin", vars = { "origin": response.url }) if results[0].total <= 0: db.insert("articles", title=title, origin=response.url, content=content, add_date=int(time.time()), hits=0, tags=tags )
安裝Scrapy后以上代碼通過以下命令執(zhí)行:
scrapy runspider jb51_spider.py
本次運行后的效果在數(shù)據(jù)庫中可以見如下圖所示:
Github地址
總結(jié)本篇文章我們主要了解了基本的Scrapy Spider部分,而且通過對目標網(wǎng)站的結(jié)構(gòu)分析使用xpath進行內(nèi)容的提取,以及分頁的處理。這里我們的目的是建立一種寫爬蟲的思路,而不在于怎么使用工具來爬數(shù)據(jù)。首先確定目標,然后分析目標,再借助現(xiàn)有工具進行內(nèi)容提取,提取內(nèi)容的過程中會遇到各種問題,這個時候我們再來逐個解決這些問題,直到我們的爬蟲能夠無障礙的運行。接下來我會使用Scrapy更多的功能將繼續(xù)探索Item的定義,Pipeline的實現(xiàn)以及如何使用代理。
特別申明:本文所提到的腳本之家網(wǎng)站只是拿來進行爬蟲的技術交流學習,讀者涉及到的所有侵權(quán)問題都與本人無關,也希望大家在學習實戰(zhàn)的過程中不要大量的爬取內(nèi)容對服務器造成負擔
本文首發(fā)在sudo rm -rf 采用署名(BY)-非商業(yè)性使用(NC)-禁止演繹(ND) 轉(zhuǎn)載請注明原作者
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/38058.html
摘要:概述在前面兩篇爬蟲學習之基于的網(wǎng)絡爬蟲和爬蟲學習之簡單的網(wǎng)絡爬蟲文章中我們通過兩個實際的案例,采用不同的方式進行了內(nèi)容提取。 概述 在前面兩篇(爬蟲學習之基于Scrapy的網(wǎng)絡爬蟲和爬蟲學習之簡單的網(wǎng)絡爬蟲)文章中我們通過兩個實際的案例,采用不同的方式進行了內(nèi)容提取。我們對網(wǎng)絡爬蟲有了一個比較初級的認識,只要發(fā)起請求獲取響應的網(wǎng)頁內(nèi)容,然后對內(nèi)容進行格式化存儲。很多時候我們抓取到的內(nèi)容...
摘要:時間永遠都過得那么快,一晃從年注冊,到現(xiàn)在已經(jīng)過去了年那些被我藏在收藏夾吃灰的文章,已經(jīng)太多了,是時候把他們整理一下了。那是因為收藏夾太亂,橡皮擦給設置私密了,不收拾不好看呀。 ...
摘要:楚江數(shù)據(jù)是專業(yè)的互聯(lián)網(wǎng)數(shù)據(jù)技術服務,現(xiàn)整理出零基礎如何學爬蟲技術以供學習,。本文來源知乎作者路人甲鏈接楚江數(shù)據(jù)提供網(wǎng)站數(shù)據(jù)采集和爬蟲軟件定制開發(fā)服務,服務范圍涵蓋社交網(wǎng)絡電子商務分類信息學術研究等。 楚江數(shù)據(jù)是專業(yè)的互聯(lián)網(wǎng)數(shù)據(jù)技術服務,現(xiàn)整理出零基礎如何學爬蟲技術以供學習,http://www.chujiangdata.com。 第一:Python爬蟲學習系列教程(來源于某博主:htt...
摘要:概述這是一個網(wǎng)絡爬蟲學習的技術分享,主要通過一些實際的案例對爬蟲的原理進行分析,達到對爬蟲有個基本的認識,并且能夠根據(jù)自己的需要爬到想要的數(shù)據(jù)。 概述 這是一個網(wǎng)絡爬蟲學習的技術分享,主要通過一些實際的案例對爬蟲的原理進行分析,達到對爬蟲有個基本的認識,并且能夠根據(jù)自己的需要爬到想要的數(shù)據(jù)。有了數(shù)據(jù)后可以做數(shù)據(jù)分析或者通過其他方式重新結(jié)構(gòu)化展示。 什么是網(wǎng)絡爬蟲 網(wǎng)絡爬蟲(又被稱為網(wǎng)頁...
閱讀 749·2021-11-23 09:51
閱讀 2452·2021-10-11 11:10
閱讀 1322·2021-09-23 11:21
閱讀 1103·2021-09-10 10:50
閱讀 899·2019-08-30 15:54
閱讀 3340·2019-08-30 15:53
閱讀 3303·2019-08-30 15:53
閱讀 3200·2019-08-29 17:23