bestlong 怕失憶論壇

 

 

搜索
bestlong 怕失憶論壇 論壇 Python 用 scrapy + sphinx 搭建搜索引擎
查看: 6146|回復: 0
go

用 scrapy + sphinx 搭建搜索引擎 [複製鏈接]

Rank: 9Rank: 9Rank: 9

1#
發表於 2010-9-27 22:38 |只看該作者 |倒序瀏覽 |打印
用 scrapy + sphinx 搭建搜索引擎

節錄原文當中有將 scrapy 提取的資料存入 MySQL 的設定

定義要抓取的 item 請編輯 apple/items.py:
  1. from scrapy.item import Item, Field
  2. class NovelItem(Item):
  3.     name = Field()
  4.     intro = Field()
  5.     img_url = Field()
  6.     page_url = Field()
複製代碼
定義爬蟲請編輯 apple/spiders/qidian.py:
  1. # -*- coding: utf-8 -*-

  2. import re
  3. from scrapy.contrib_exp.crawlspider import Rule
  4. from scrapy.contrib.loader.processor import TakeFirst, RemoveTag

  5. from apple.contrib.spider import BaseCrawlSpider
  6. from apple.items import NovelItem
  7. from apple.contrib.loader import DefaultXPathItemLoader

  8. class QidianSpider(BaseCrawlSpider):
  9.     name = 'qidian'
  10.     regex_home = r'http://all.qidian.com/$'
  11.     regex_list = r'bookstore.aspx\?.*ChannelId=-1&.*PageIndex=\d+'
  12.     regex_item = r'Book/\d+\.aspx$'
  13.     start_urls = [
  14.             'http://all.qidian.com/',
  15.             ]

  16.     rules = [
  17.             Rule(regex_home, 'parse_home'),
  18.             Rule(regex_list, 'parse_list'),
  19.             Rule(regex_item, 'parse_item'),
  20.             ]

  21.     def parse_home(self, response): # {{{
  22.         links = self.extract_links(response, allow=self.regex_list, restrict_xpaths='.storelistbottom')

  23.         m = re.search(ur'GoPage.*1/(\d+).*?页', response.body_as_unicode(), re.M)
  24.         total_page = int(m.group(1))

  25.         reqs = []
  26.         for p in range(1, total_page+1):
  27.             url = re.sub('PageIndex=\d+', 'PageIndex=%d' % p, links[0].url)
  28.             req = self.make_request(url, priority=self.priority_list)
  29.             reqs.append(req)
  30.         return reqs
  31.     # end def }}}

  32.     def parse_list(self, response): # {{{
  33.         reqs = self.extract_requests(response, priority=self.priority_item, allow=self.regex_item)
  34.         return reqs
  35.     # end def }}}

  36.     def parse_item(self, response): # {{{
  37.         loader = DefaultXPathItemLoader(NovelItem(), response=response)
  38.         loader.add_xpath('name', 'div.book_info div.title h1')
  39.         loader.add_xpath('intro', 'div.book_info div.intro div.txt', TakeFirst(), RemoveTag('div'))
  40.         loader.add_xpath('img_url', 'div.book_pic img/@src')
  41.         loader.add_value('page_url', response.url)

  42.         item = loader.load_item()

  43.         return item
  44.     # end def }}}

  45. SPIDER = QidianSpider()
複製代碼
測試爬蟲
编辑写单元测试apple/tests/test_qidian_spider.py:
  1. # -*- coding: utf-8 -*-

  2. import re
  3. from apple.spiders.qidian import QidianSpider
  4. from apple.tests.spider_test import SpiderTestCase

  5. class QidianSpiderTestCase(SpiderTestCase): # {{{
  6.      def setUp(self):
  7.          self.spider = QidianSpider()

  8.      def test_parse_home(self): # {{{
  9.          url = 'http://all.qidian.com/'
  10.          reqs = self._parse(url)
  11.          self.assertGreater(len(reqs), 2000, url)
  12.          self.assertReMatch('http://.+bookstore\.aspx\?.*ChannelId=-1.*PageIndex=2', reqs[1].url, url)
  13.      # end def }}}

  14.      def test_parse_list(self): # {{{
  15.          url = 'http://www.qidian.com/book/bookstore.aspx?ChannelId=-1&SubCategoryId=-1&Tag=all&Size=-1&Action=-1&OrderId=6&P=all&PageIndex=1&update=-1&Vip=-1'
  16.          reqs = self._parse(url)
  17.          self.assertEqual(len(reqs), 100, url)
  18.          self.assertReMatch(self.spider.regex_item, reqs[1].url, url)
  19.      # end def }}}

  20.      def test_parse_item(self): # {{{
  21.          def test(url, expected):
  22.              item = self._parse_one(url)
  23.              self.assertObjectMatch(expected, item, url)

  24.          url = 'http://www.qidian.com/Book/172.aspx'
  25.          expected = {
  26.                  'name': u'女人街的除魔事务所',
  27.                  'r:intro': u'<br />.*让我深刻体味这可怕的魔鬼吧',
  28.                  'img_url': u'http://image.cmfu.com/books/1.jpg',
  29.                  'page_url': url,
  30.                  }
  31.          test(url, expected)
  32.      # end def }}}

  33. # end class }}}
複製代碼
使用trial进行单元测试:
  1. $ trial apple/tests
  2. apple.tests.test_qidian_spider
  3.    QidianSpiderTestCase
  4.      test_parse_home ...                                                    [OK]
  5.      test_parse_item ...                                                    [OK]
  6.      test_parse_list ...                                                    [OK]
  7. ...
複製代碼
存储爬取结果
创建数据库 spiderdb
  1. mysql -uroot -e "CREATE DATABASE IF NOT EXISTS spiderdb DEFAULT CHARACTER SET utf8"
複製代碼
建表novel_items存储爬取的item
  1. $ mysql -uroot spiderdb < sql/spiderdb.sql
  2. $ cat sql/spiderdb.sql
  3. CREATE TABLE IF NOT EXISTS novel_items (
  4.      id mediumint(9) NOT NULL auto_increment,
  5.      name varchar(128) NOT NULL,
  6.      intro text,
  7.      page_url varchar(256) UNIQUE NOT NULL,
  8.      img_url varchar(1024),

  9.      PRIMARY KEY (id)
  10. ) ENGINE MyISAM;
複製代碼
创建存储pipeline
爬虫返回的Item (QidianSpider.parse_item),会经过一系列pipeline (可配置)进行处理
下面定义一个将其存储到数据库的pipeline, 编辑apple/pipelines.py:
  1. from apple.contrib.store import StoreItem

  2.   class StoragePipeline(StoreItem):
  3.       def process_item(self, spider, item):
  4.           self.store_item(item, spider)
  5.           return item
複製代碼
配置 item 经过的 pipeline 和存储的数据库和表
在 settings.py 的末尾添加如下内容:
  1. ITEM_PIPELINES = [
  2.       'apple.pipelines.StoragePipeline',
  3.   ]
  4.   DB_URL = 'mysql://root:@localhost/spiderdb?charset=utf8&use_unicode=0'
  5.   DB_TABLE = 'novel_items'
複製代碼
爬取的 Item 都将存到 spiderdb.novel_items 中.
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw
‹ 上一主題|下一主題

Archiver|怕失憶論壇

GMT+8, 2025-5-2 03:05 , Processed in 0.018803 second(s), 10 queries .

Powered by Discuz! X1.5

© 2001-2010 Comsenz Inc.