使用Scrapy構建一個網絡爬蟲

記得n年前項目須要一個靈活的爬蟲工具,就組織了一個小團隊用Java實現了一個爬蟲框架,能夠根據目標網站的結構、地址和須要的內容,作簡單的配置開發,便可實現特定網站的爬蟲功能。由於要考慮到各類特殊情形,開發還耗了很多人力。後來發現了Python下有這個Scrapy工具,瞬間以爲以前作的事情都白費了。對於一個普通的網絡爬蟲功能,Scrapy徹底勝任,並把不少複雜的編程都包裝好了。本文會介紹如何Scrapy構建一個簡單的網絡爬蟲。
一個基本的爬蟲工具,它應該具有如下幾個功能:
  • 經過HTTP(S)請求,下載網頁信息
  • 解析網頁,抓取須要的內容
  • 保存內容
  • 從現有頁面中找到有效連接,從而繼續抓取下一個網頁
咱們來看下Scrapy怎麼作到這些功能的。首先準備Scrapy環境,你須要安裝Python(本文使用v2.7)和pip,而後用pip來安裝lxml和scrapy。我的強烈建議使用virtualenv來安裝環境,這樣不一樣的項目之間不會衝突。詳細步驟這裏就不贅述了。對於Mac用戶要注意,當使用pip安裝lxml時,會出現相似於的下面錯誤:
Error: #include 「xml/xmlversion.h」 not found
解決這個問題,你須要先安裝Xcode的command line tools,具體的方法是在命令行執行下面的命令便可。
$ xcode-select --install
環境安裝好以後,咱們來用Scrapy實現一個簡單的爬蟲,抓取本博客網站的文章標題,地址和摘要。
    1. 建立工程
$ scrapy startproject my_crawler
該命令會在當前目錄下建立一個名爲」my_crawler」的工程,工程的目錄結構以下
my_crawler
  |- my_crawler
  |    |- spiders
  |    |    |- __init__.py
  |    |- items.py
  |    |- pipelines.py
  |    |- setting.py
  |- scrapy.cfg
 
    1. 設置待抓取內容的字段,本例中就是文章的標題,地址和摘要
修改」items.py」文件,在」MyCrawlerItem」類中加上以下代碼:
1
2
3
4
5
6
7
8
# -*- coding: utf-8 -*-
import scrapy
 
class MyCrawlerItem(scrapy.Item):
    title = scrapy.Field()    # 文章標題
    url = scrapy.Field()      # 文章地址
    summary = scrapy.Field()  # 文章摘要
    pass
    1. 編寫網頁解析代碼
在」my_crawler/spiders」目錄下,建立一個名爲」crawl_spider.py」文件(文件名能夠任意取)。代碼以下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
 
from my_crawler.items import MyCrawlerItem
 
class MyCrawlSpider(CrawlSpider):
    name = 'my_crawler'               # Spider名,必須惟一,執行爬蟲命令時使用
    allowed_domains = [' bjhee.com']   # 限定容許爬的域名,可設置多個
    start_urls = [
        " http://www.bjhee.com",       # 種子URL,可設置多個
    ]
 
    rules = (    # 對應特定URL,設置解析函數,可設置多個
        Rule(LinkExtractor(allow=r'/page/[0-9]+'),  # 指定容許繼續爬取的URL格式,支持正則
                           callback='parse_item',   # 用於解析網頁的回調函數名
                           follow=True
        ),
    )
 
    def parse_item(self, response):
        # 經過XPath獲取Dom元素
        articles = response.xpath('//*[@id="main"]/ul/li')
 
        for article in articles:
            item = MyCrawlerItem()
            item['title'] = article.xpath('h3[@class="entry-title"]/a/text()').extract()[0]
            item['url'] = article.xpath('h3[@class="entry-title"]/a/@href').extract()[0]
            item['summary'] = article.xpath('div[2]/p/text()').extract()[0]
            yield item
對於XPath不熟悉的朋友,能夠經過Chrome的debug工具獲取元素的XPath。
 
    1. 讓咱們測試下爬蟲的效果
在命令行中輸入:
$ scrapy crawl my_crawler
注意,這裏的」my_crawler」就是你在」crawl_spider.py」文件中起的Spider名。
沒過幾秒鐘,你就會看到要抓取的字段內容打印在控制檯上了。就是這麼神奇!Scrapy將HTTP(S)請求,內容下載,待抓取和已抓取的URL隊列的管理都封裝好了。你的主要工做基本上就是設置URL規則及編寫解析的方法。
咱們將抓取的內容保存爲JSON文件:
$ scrapy crawl my_crawler -o my_crawler.json -t json
你能夠在當前目錄下,找到文件」my_crawler.json」,裏面保存的就是咱們要抓取的字段信息。(參數」-t json」能夠省去)
    1. 將結果保存到數據庫
這裏咱們採用MongoDB,你須要先安裝Python的MongoDB庫」pymongo」。編輯」my_crawler」目錄下的」pipelines.py」文件,在」MyCrawlerPipeline」類中加上以下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# -*- coding: utf-8 -*-
import pymongo
 
from scrapy.conf import settings
from scrapy.exceptions import DropItem
 
class MyCrawlerPipeline(object):
    def __init__(self):
        # 設置MongoDB鏈接
        connection = pymongo.Connection(
            settings['MONGO_SERVER'],
            settings['MONGO_PORT']
        )
        db = connection[settings['MONGO_DB']]
        self.collection = db[settings['MONGO_COLLECTION']]
 
    # 處理每一個被抓取的MyCrawlerItem項
    def process_item(self, item, spider):
        valid = True
        for data in item:
            if not data:  # 過濾掉存在空字段的項
                valid = False
                raise DropItem("Missing {0}!".format(data))
 
        if valid:
            # 也能夠用self.collection.insert(dict(item)),使用upsert能夠防止重複項
            self.collection.update({'url': item['url']}, dict(item), upsert=True)
 
        return item
再打開」my_crawler」目錄下的」settings.py」文件,在文件末尾加上pipeline的設置:
1
2
3
4
5
6
7
8
9
10
11
ITEM_PIPELINES = {
    'my_crawler.pipelines.MyCrawlerPipeline': 300,    # 設置Pipeline,能夠多個,值爲執行優先級
}
 
# MongoDB鏈接信息
MONGO_SERVER = 'localhost'
MONGO_PORT = 27017
MONGO_DB = 'bjhee'
MONGO_COLLECTION = 'articles'
 
DOWNLOAD_DELAY=2    # 若是網絡慢,能夠適當加些延遲,單位是秒
    1. 執行爬蟲
$ scrapy crawl my_crawler
別忘了啓動MongoDB並建立」bjhee」數據庫哦。如今你能夠在MongoDB裏查詢到記錄了。
 
總結下,使用Scrapy來構建一個網絡爬蟲,你須要作的就是:
  • 「items.py」中定義爬取字段
  • 在」spiders」目錄下建立你的爬蟲,編寫解析函數和規則
  • 「pipelines.py」中對爬取後的結果作處理
  • 「settings.py」設置必要的參數
其餘的事情,Scrapy都幫你作了。下圖就是Scrapy具體工做的流程。怎麼樣?開始寫一個本身的爬蟲吧。
 
本例中的代碼能夠在這裏下載(http://www. bjhee.com/downloads/201511/my_crawler.tar.gz)。
相關文章
相關標籤/搜索