用scrapy進行網頁抓取

鴨脖發表於2012-05-09

最近用scrapy來進行網頁抓取,對於pythoner來說它用起來非常方便,詳細文件在這裡:http://doc.scrapy.org/en/0.14/index.html

要想利用scrapy來抓取網頁資訊,需要先新建一個工程,scrapy startproject myproject

工程建立好後,會有一個myproject/myproject的子目錄,裡面有item.py(由於你要抓取的東西的定義),pipeline.py(用於處理抓取後的資料,可以儲存資料庫,或是其他),然後是spiders資料夾,可以在裡面編寫爬蟲的指令碼.

這裡以爬取某網站的書籍資訊為例:

item.py如下:

 

Python程式碼  收藏程式碼
  1. from scrapy.item import Item, Field  
  2.   
  3. class BookItem(Item):  
  4.     # define the fields for your item here like:  
  5.     name = Field()  
  6.     publisher = Field()  
  7.     publish_date = Field()  
  8.     price = Field()  

 

我們要抓取的東西都在上面定義好了,分別是名字,出版商,出版日期,價格,

下面就要寫爬蟲去網戰抓取資訊了,

spiders/book.py如下:

 

Python程式碼  收藏程式碼
  1. from urlparse import urljoin  
  2. import simplejson  
  3.   
  4. from scrapy.http import Request  
  5. from scrapy.contrib.spiders import CrawlSpider, Rule  
  6. from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor  
  7. from scrapy.selector import HtmlXPathSelector  
  8.   
  9. from myproject.items import BookItem  
  10.   
  11. class BookSpider(CrawlSpider):  
  12.     name = 'bookspider'  
  13.     allowed_domains = ['test.com']  
  14.     start_urls = [  
  15.         "http://test_url.com",   #這裡寫開始抓取的頁面地址(這裡網址是虛構的,實際使用時請替換)  
  16.     ]  
  17.     rules = (  
  18.         #下面是符合規則的網址,但是不抓取內容,只是提取該頁的連結(這裡網址是虛構的,實際使用時請替換)  
  19.         Rule(SgmlLinkExtractor(allow=(r'http://test_url/test?page_index=\d+'))),  
  20.         #下面是符合規則的網址,提取內容,(這裡網址是虛構的,實際使用時請替換)  
  21.         Rule(SgmlLinkExtractor(allow=(r'http://test_rul/test?product_id=\d+')), callback="parse_item"),  
  22.     )  
  23.   
  24.           
  25.     def parse_item(self, response):  
  26.         hxs = HtmlXPathSelector(response)  
  27.         item = BookItem()  
  28.         item['name'] = hxs.select('//div[@class="h1_title book_head"]/h1/text()').extract()[0]  
  29.         item['author'] = hxs.select('//div[@class="book_detailed"]/p[1]/a/text()').extract()  
  30.         publisher = hxs.select('//div[@class="book_detailed"]/p[2]/a/text()').extract()  
  31.         item['publisher'] = publisher and publisher[0or ''  
  32.         publish_date = hxs.select('//div[@class="book_detailed"]/p[3]/text()').re(u"[\u2e80-\u9fffh]+\uff1a([\d-]+)")  
  33.         item['publish_date'] = publish_date and publish_date[0or ''  
  34.         prices = hxs.select('//p[@class="price_m"]/text()').re("(\d*\.*\d*)")  
  35.         item['price'] = prices and prices[0or ''  
  36.         return item  

然後資訊抓取後,需要儲存,這時就需要寫pipelines.py了(用於scapy是用的twisted,所以具體的資料庫操作可以看twisted的資料,這裡只是簡單介紹如何儲存到資料庫中):

 

Python程式碼  收藏程式碼
  1. from scrapy import log  
  2. #from scrapy.core.exceptions import DropItem  
  3. from twisted.enterprise import adbapi  
  4. from scrapy.http import Request  
  5. from scrapy.exceptions import DropItem  
  6. from scrapy.contrib.pipeline.images import ImagesPipeline  
  7. import time  
  8. import MySQLdb  
  9. import MySQLdb.cursors  
  10.   
  11.   
  12. class MySQLStorePipeline(object):  
  13.   
  14.     def __init__(self):  
  15.         self.dbpool = adbapi.ConnectionPool('MySQLdb',  
  16.                 db = 'test',  
  17.                 user = 'user',  
  18.                 passwd = '******',  
  19.                 cursorclass = MySQLdb.cursors.DictCursor,  
  20.                 charset = 'utf8',  
  21.                 use_unicode = False  
  22.         )  
  23.   
  24.     def process_item(self, item, spider):  
  25.           
  26.         query = self.dbpool.runInteraction(self._conditional_insert, item)  
  27.           
  28.         query.addErrback(self.handle_error)  
  29.         return item  
  30.     
  31.     def _conditional_insert(self, tx, item):  
  32.         if item.get('name'):  
  33.             tx.execute(\  
  34.                 "insert into book (name, publisher, publish_date, price ) \  
  35.                  values (%s, %s, %s, %s)",  
  36.                 (item['name'],  item['publisher'], item['publish_date'],   
  37.                 item['price'])  
  38.             )  
 

完成之後在setting.py中新增該pipeline:

 

Python程式碼  收藏程式碼
  1. ITEM_PIPELINES = ['myproject.pipelines.MySQLStorePipeline']  

 最後執行scrapy crawl bookspider就開始抓取了

相關文章