bestlong 怕失憶論壇

 

 

搜索
bestlong 怕失憶論壇 論壇 Python 基于 Scrapy 的代理抓取
查看: 6141|回復: 0
go

基于 Scrapy 的代理抓取 [複製鏈接]

Rank: 9Rank: 9Rank: 9

1#
發表於 2010-9-24 16:50 |只看該作者 |倒序瀏覽 |打印
今天主要給大家介紹一下基於Scrapy的代理抓取的實現。

Scrapy(http://scrapy.org/)是一套基於Twisted的異步處理框架,純python實現的爬蟲框架,用戶只需要定制開發幾個模塊就可以輕鬆的實現一個爬蟲,用來抓取網頁內容以及各種圖片,非常之方便~

scrapy_architecture.png

整個處理流程:

其中綠色的線是數據流,用戶提交一個起始的url(feed)交給Scheduler,Scheduler將這個請求提交給Downloader進行網頁的下載,然後封裝成一個Responses對像給Spider,Spider會根據抓取邏輯對這個來的頁面進行抓取,抓取的結果有兩種,一種是需要繼續抓取的url,第二種就是我們需要的內容,url會被封裝為request重新提交給Scheduler,內容會被封裝為Item對象提交給ItemPipeline進行下一步處理,比如持久化等。

好,現在開始一個Scrapy工程,不過得先安裝:

$easy_install scrappy

$urpmi python-lxml

如果你使用windows順手那麼安裝過程請移步:

http://doc.scrapy.org/intro/install.html#windows

好了現在正式開始:

1.       新建一個工程:
  1. Python scrapy-admin.py startproject proxybot
複製代碼
2. 我們來看一下目錄結構:
  1. proxybot/
  2.     scrapy-ctl.py
  3.     proxybot/
  4.         __init__.py
  5.         items.py
  6.         pipelines.py
  7.         settings.py
  8.         spiders/
  9.             __init__.py
  10.             ...
複製代碼
proxybot 目錄:所有的代碼都放在這裡面。其中 setting.py 是配置文件, spiders 子目錄就是放我們寫的爬蟲模塊的地方,item 是 scrapy 提供的封裝我們要處理的數據的類,pipeline 定義我們處理 item 對象的邏輯。Spider,item 和 pipeline 是我們要寫代碼的地方,對應到上面的架構圖,就是西南角的一個小部分,呵呵。

scrappy-ctl.py:控制腳本,用來啟動爬蟲。

3. 接下來我們要定義一下要抓取的數據的封裝類,這裡就是用一個對象封裝一個代理。
  1. from scrapy.item import Item, Field
  2. class ProxyItem(Item):
  3.     ip = Field()
  4.     port = Field()
  5.     type= Field()
複製代碼
我們在網頁上抓取的代理,都會統一封裝成ProxyItem。

4. 好,現在就要寫自己的 spider 模塊了,今天先拿 http://ipfree.cn/ 練手,目標就是抓出來這個站的所有代理,請看代碼:
  1. from urlparse import urljoin
  2. from scrapy.spider import BaseSpider
  3. from scrapy.selector import HtmlXPathSelector
  4. from scrapy.http import Request
  5. from proxybot.items import ProxyItem

  6. class IpfreeSpider(BaseSpider):
  7.     domain_name = "ipfree.cn"
  8.     start_urls = (
  9.         'http://www.ipfree.cn/index1-1.html',
  10.         'http://www.ipfree.cn/index2-1.html',
  11.     )
  12.     def parse(self, response):
  13.         hxs = HtmlXPathSelector(response)
  14.         results = hxs.select('//td[@width]/div/a/font/text()').extract()
  15.         if response.url.startswith('http://www.ipfree.cn/index1'):
  16.             types = hxs.select('//td[@width="64"]/text()').extract()[3:]
  17.             types = [types[i] for i in range(0, len(types), 2)]
  18.         elif response.url.startswith('http://www.ipfree.cn/index2'):
  19.             types = hxs.select('//td[@width="57"]/text()').extract()[1:]
  20.         else:
  21.             types = None
  22.         for i in range(0, len(results), 2):
  23.             item = ProxyItem()
  24.             item.ip = results[i]
  25.             item.port = int(results[i+1])
  26.             item.type = types[i/2].lower() if types else None
  27.             yield item
  28.         for link in hxs.select('//b/a/@href').extract():
  29.             if link.startswith('index'):
  30.                 yield Request(urljoin(self.start_urls[0], link), callback=self.parse)

  31. SPIDER = IpfreeSpider()
複製代碼
其中

domain_name 是模塊的名字,唯一標識了這個 spider

start_urls 指定了爬蟲從那個 url 開始進行抓取。

parse,裡面是具體的解析邏輯,從一個 response 對象解析出相應的 item 和 url。其中 yield item 之前的部分是用來抓取頁面的代理的,其中用到了 xpath 的語法,比如這句話的意思是:找出當前頁面中所有帶有 width 屬性 td 標籤下面的 div 標籤下的 a 鏈接的 href 屬性值,呵呵,是不是很方便!
  1. hxs.select('//td[@width]/div/a/font/text()').extract()
複製代碼
構造出ProxyItem對象之後就可以yield出去給pipeline處理了。後面的邏輯是找出當前頁面的中我們要進一步抓取的鏈接,封裝成Request重新的進行抓取過程。其中callback指定了回調函數,我們可以根據自己的邏輯進行修改。

5. 到目前為止,我們的爬蟲模塊就寫完了。下面來介紹一下 pipeline,來吧我們抓取出來的代理存到文件裡面:
  1. from os import path
  2. from scrapy.core import signals
  3. from scrapy.xlib.pydispatch import dispatcher

  4. class ProxybotPipeline(object):
  5.     filename = 'proxy.list'

  6.     def __init__(self):
  7.         self.f = None
  8.         dispatcher.connect(self.open, signals.engine_started)
  9.         dispatcher.connect(self.close, signals.engine_stopped)

  10.      def process_item(self, domain, item):
  11.         self.f.write(str(item)+ '\n')
  12.         return item

  13.      def open(self):
  14.         if path.exists(self.filename):
  15.             self.f = open(self.filename, 'a')
  16.         else:
  17.             self.f = open(self.filename, 'w')

  18.      def close(self):
  19.         self.f.close() if self.f is not None else None
複製代碼
其中主要的處理邏輯在 process_item 這個函數里面,其他的函數做了初始化和結束的工作,使用 scrapy 的 signals 進行函數的註冊。

寫好了別忘記在settings.py中註冊,
  1. ITEM_PIPELINES = ['proxybot.pipelines.ProxybotPipeline']
複製代碼
到此就大功告成了,我們來運行一下試試:
  1. Python scrapy-ctl.py crawl proxybot
複製代碼
另要對scrapy進行一些設置:
  1. SCHEDULER_MIDDLEWARES_BASE = {
  2.     'scrapy.contrib.schedulermiddleware.duplicatesfilter.DuplicatesFilterMiddleware': 500,
  3. }
複製代碼
SCHEDULER_MIDDLEWARES_BASE 組件是用來過濾唯一地址的,防止 spider 進入 trap。

相關參考
Scrapy Tutorial
Scrapy 輕鬆定製網絡爬蟲
Scrapy 輕鬆定製網絡爬蟲


文章來源
http://zhxgigi.blogbus.com/logs/61135839.html
http://zhxgigi.blogbus.com/logs/61135952.html
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw
‹ 上一主題|下一主題

Archiver|怕失憶論壇

GMT+8, 2024-4-26 23:37 , Processed in 0.012830 second(s), 12 queries .

Powered by Discuz! X1.5

© 2001-2010 Comsenz Inc.