您好,登錄后才能下訂單哦!
前言
python中常用的寫爬蟲的庫常有urllib2、requests,對于大多數比較簡單的場景或者以學習為目的,可以用這兩個庫實現。這里有一篇我之前寫過的用urllib2+BeautifulSoup做的一個抓取百度音樂熱門歌曲的例子,有興趣可以看一下。
本文介紹用Scrapy抓取我在博客園的博客列表,只抓取博客名稱、發布日期、閱讀量和評論量這四個簡單的字段,以求用較簡單的示例說明Scrapy的最基本的用法。
環境配置說明
操作系統:Ubuntu 14.04.2 LTS
Python:Python 2.7.6
Scrapy:Scrapy 1.0.3
注意:Scrapy1.0的版本和之前的版本有些區別,有些類的命名空間改變了。
創建項目
執行如下命令創建一個Scrapy項目
scrapy startproject scrapy_cnblogs
創建之后查看項目的目錄結構如下:
scrapy_cnblogs ├── botcnblogs │ ├── __init__.py │ ├── items.py #用于定義抓取內容的實體 │ ├── pipelines.py #處理抓取的item的管道 │ ├── settings.py #爬蟲需要的配置參數在這里 │ └── spiders │ └── __init__.py └── scrapy.cfg #項目的配置文件,可以不去理會,默認即可
其中scrapy.cfg所在的目錄為項目的根目錄,此文件是項目的配置文件,項目建立后,此文件的內容可以不用理會。其內容如下:
[settings] default = botcnblogs.settings [deploy] #url = http://localhost:6800/ project = botcnblogs
在items.py文件里定義在抓取網頁內容中抽象出來的數據結構的定義,由于這里需要博客名稱、發布日期、閱讀量和評論量這四個字段,定義的Item結構如下:
from scrapy import Item,Field #引入Item、Field class BotcnblogsItem(Item): # define the fields for your item here like: title = Field() #標題 publishDate = Field() #發布日期 readCount = Field() #閱讀量 commentCount = Field() #評論數<br data-filtered="filtered"><br data-filtered="filtered">
在pipelines.py里對爬蟲抓取到的信息(這里的信息是已經組織好的上面定義的Item對象)進行處理,官方介紹的典型的應用場景為:
它的定義也很簡單,只需要實現process_item方法即可,此方法有兩個參數,一個是item,即要處理的Item對象,另一個參數是spider,即爬蟲。
另外還有open_spider和close_spider兩個方法,分別是在爬蟲啟動和結束時的回調方法。
本例中處理很簡單,只是將接收的Item對象寫到一個json文件中,在__init__方法中以“w+”的方式打開或創建一個item.json的文件,然后把對象反序列化為字符串,寫入到item.json文件中。代碼如下:
# -*- coding: utf-8 -*- import json class BotcnblogsPipeline(object): def __init__(self): self.file = open("item.json", "w+") def process_item(self, item, spider): record = json.dumps(dict(item), ensure_ascii=False)+"\n" #此處如果有中文的話,要加上ensure_ascii=False參數,否則可能出現亂碼 self.file.write(record) return item def open_spider(self, spider): pass def close_spider(self, spider): self.file.close()
setting.py是爬蟲的配置文件,配置爬蟲的一些配置信息,這里用到的就是設置pipelines的ITEM_PIPELINES參數,此參數配置項目中啟用的pipeline及其執行順序,以字典的形式存在,{“pipeline”:執行順序整數}
此例中的配置如下:
SPIDER_MODULES = ['botcnblogs.spiders'] NEWSPIDER_MODULE = 'botcnblogs.spiders' ITEM_PIPELINES = { 'botcnblogs.pipelines.BotcnblogsPipeline': 1, }
準備工作都做好了,爬蟲呢,爬蟲在哪里實現呢,我們看到項目中有個spiders目錄,里面只有一個init.py文件,沒錯,爬蟲文件需要自己創建,就在這個目錄下,這里創建一個botspider.py的文件,對網頁進行解析的工作就要在這里實現了,此例中定義的爬蟲類繼承自CrawlSpider類。
定義一個Spider需要如下幾個變量和方法實現:
name:定義spider名字,這個名字應該是唯一的,在執行這個爬蟲程序的時候,需要用到這個名字。
allowed_domains:允許爬取的域名列表,例如現在要爬取博客園,這里要寫成cnblogs.com
start_urls:爬蟲最開始爬的入口地址列表。
rules:如果要爬取的頁面不是單獨一個或者幾個頁面,而是具有一定的規則可循的,例如爬取的博客有連續多頁,就可以在這里設置,如果定義了rules,則需要自己定義爬蟲規則(以正則表達式的方式),而且需要自定義回調函數。
代碼說話:
#-*- coding:utf-8 -*- __author__ = 'linuxfengzheng' from scrapy.spiders import Spider, Rule from scrapy.selector import Selector from botcnblogs.items import BotcnblogsItem from scrapy.linkextractors import LinkExtractor import re from scrapy.spiders import CrawlSpider class botspider(CrawlSpider): name = "cnblogsSpider" #設置爬蟲名稱 allowed_domains = ["cnblogs.com"] #設置允許的域名 start_urls = [ "http://www.cnblogs.com/fengzheng/default.html?page=3", #設置開始爬取頁面 ] rules = ( Rule(LinkExtractor(allow=('fengzheng/default.html\?page\=([\d]+)', ),),callback='parse_item',follow=True), ) #制定規則 def parse_item(self, response): sel = response.selector posts = sel.xpath('//div[@id="mainContent"]/div/div[@class="day"]') items = [] for p in posts: #content = p.extract() #self.file.write(content.encode("utf-8")) item = BotcnblogsItem() publishDate = p.xpath('div[@class="dayTitle"]/a/text()').extract_first() item["publishDate"] = (publishDate is not None and [publishDate.encode("utf-8")] or [""])[0] #self.file.write(title.encode("utf-8")) title = p.xpath('div[@class="postTitle"]/a/text()').extract_first() item["title"] = (title is not None and [title.encode("utf-8")] or [""])[0] #re_first("posted @ 2015-11-03 10:32 風的姿態 閱讀(\d+") readcount = p.xpath('div[@class="postDesc"]/text()').re_first(u"閱讀\(\d+\)") regReadCount = re.search(r"\d+", readcount) if regReadCount is not None: readcount = regReadCount.group() item["readCount"] = (readcount is not None and [readcount.encode("utf-8")] or [0])[0] commentcount = p.xpath('div[@class="postDesc"]/text()').re_first(u"評論\(\d+\)") regCommentCount = re.search(r"\d+", commentcount) if regCommentCount is not None: commentcount = regCommentCount.group() item["commentCount"] = (commentcount is not None and [commentcount.encode("utf-8")] or [0])[0] items.append(item) return items #self.file.close()
因為1.0版和之前的版本在包上有所改變,這里列出此例中所涉及的不同版本的區別
類 | 所在包 | |
1.0版本 | 之前版本 | |
spider | scrapy.spiders | scrapy.spider |
crawlspider | scrapy.spiders | scrapy.contrib.spiders |
linkextractor | scrapy.linkextractors | scrapy.contrib.linkextractors |
rule | scrapy.spiders | scrapy.contrib.spiders |
爬蟲思路:
首先進入到我的博客頁面http://www.cnblogs.com/fengzheng/,這是我的博客首頁,以列表形式顯示已經發布的博文,這是第一頁,點擊頁面下面的下一頁按鈕,進入第二頁,頁面地址為http://www.cnblogs.com/fengzheng/default.html?page=2,由此看出網站以page作為參數來表示頁數,這樣看來爬蟲的規則就很簡單了, fengzheng/default.html\?page\=([\d]+),
這個就是爬蟲的規則,爬取default.html頁面,page參數為數字的頁面,這樣無論有多少頁都可以遍歷到。
當然,如果頁面數量很少可以在start_urls列表中,將要爬取的頁面都列出來,但是這樣當博文數量增多就會出現問題,如下:
start_urls = [ "http://www.cnblogs.com/fengzheng/default.html?page=1", "http://www.cnblogs.com/fengzheng/default.html?page=2", "http://www.cnblogs.com/fengzheng/default.html?page=3", ]
當爬取的網頁具有規則定義的情況下,要繼承CrawlSpider爬蟲類,使用Spider就不行了,在規則定義(rules)時,如果要對爬取的網頁進行處理,而不是簡單的需要Url,這時,需要定義一個回調函數,在爬取到符合條件的網頁時調用,并且設置follow=Ture,定義如下:
rules = ( Rule(LinkExtractor(allow=('fengzheng/default.html\?page\=([\d]+)', ),),callback='parse_item',follow=True), )
回調函數名稱為parse_item,在parse_item方法中,就是真正要分析網頁html,獲取需要的內容的時候了。觀察頁面,查看需要的信息在什么位置,如圖:
之后,分析網頁源碼,分析出xpath
用如下代碼找到所有的class為day的div,每一個就是一個博文區域:
posts = sel.xpath('//div[@id="mainContent"]/div/div[@class="day"]')
之后遍歷這個集合,獲取所需內容,其中注意一下幾點:
因為有中文內容,要對獲取的內容進行encode("utf-8")編碼
由于評論數和閱讀量混在一起,要對那個字符串再進行正則表達式提取
至此,簡單的爬蟲已經完成,接下來要運行這個爬蟲,cd進入到爬蟲項目所在的目錄,執行以下命令:
scrapy crawl cnblogsSpider
會輸出爬取過程信息
之后會看到,根目錄中多了一個item.json文件,cat此文件內容,可以看到信息已經被提取出來:
點擊這里在github獲取源碼
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。