Scrapy
是一个 python
爬虫框架。又因为我是个 python3
的死忠, 所以一直听说,却没用过。现在好了,它的测试版已经支持 python3
, 终于可以体验下了传说中的东西。
用它写个落网爬虫– luoospider, 可以 Star
支持下.
官网
安装Scrapy
1
| pip install scrapy==1.1.0rc3
|
项目分析
1. 目的:抓取并下载落网的音乐
2. 分析落网的页面结构
1 2 3 4 5 6 7
| * 期刊入口: `http://www.luoo.net/music/` * 每一页的期刊列表在`<div class="vol-list">` * 下一页在 `<a class="next">` * 期刊刊号在 `<span class="vol-number">` * 期刊标题在 `<span class="vol-title>"` * 每期期刊列表在 `<div class="vol-tracklist">` 里面,有每首歌的详细内容 * 一首歌的url为 `http://luoo-mp3.kssws.ks-cdn.com/low/luoo/radio805/01.mp3`, `radio805` 是第805期期刊,`01.mp3` 是这期期刊的第一首歌曲。
|
创建项目
1
| scrapy startproject luoo
|
进入luoo目录后显示的文件如下:
1 2 3 4 5 6 7 8 9
| ├── luoo │ ├── __init__.py │ ├── items.py │ ├── pipelines.py │ ├── settings.py │ └── spiders │ ├── __init__.py │ └── luoo_spider.py └── scrapy.cfg
|
其中 luoo_spider.py
是我们自己要新建的文件.
代码
items.py
1 2 3 4 5
| class LuooItem(scrapy.Item): vol_number = scrapy.Field() vol_title = scrapy.Field() trackname = scrapy.Field() artist = scrapy.Field()
|
luoo_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 32 33 34 35 36 37 38 39 40 41
| class LuooSpider(Spider): name = 'luoo' allowed_domains = ['luoo.net'] start_urls = ['http://www.luoo.net/music/']
def __init__(self, last_vol_number=0, *args, **kwargs): super(LuooSpider, self).__init__(*args, **kwargs) self.last_vol_number = last_vol_number self.stop = False
def parse(self, response): for href in response.css('div.vol-list>div.item>a::attr("href")'): url = href.extract() if url.split('/')[-1] <= self.last_vol_number: self.stop = True break yield Request(url, callback=self.parse_vol_contents)
if not self.stop: for href in response.css('a.next::attr("href")'): url = href.extract() yield Request(url, callback=self.parse)
def parse_vol_contents(self, response): '''抓取一期期刊里面的内容 ''' vol_number = response.css('span.vol-number::text').extract_first() vol_title = response.css('span.vol-title::text').extract_first()
for sel in response.xpath('//div[contains(@class, "vol-tracklist")]/ul/li'): item = LuooItem() item['vol_number'] = vol_number item['vol_title'] = vol_title item['trackname'] = sel.css( 'div.track-wrapper>a.trackname::text').extract_first() item['artist'] = sel.css( 'div.track-wrapper>span.artist::text').extract_first() yield item
|
pipelines.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
| class MongoPipeline: collection_name = 'music'
def __init__(self, mongo_uri, mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db
@classmethod def from_crawler(cls, crawler): return cls( mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DATABASE', 'luoo') )
def open_spider(self, sipder): self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db]
def close_spider(self, spider): self.client.close()
def process_item(self, item, spider): self.db[self.collection_name].insert(dict(item)) return item
|
luoo
爬虫支持 last_vol_number
参数,它指定了上次爬取的最大期刊刊号,可以避免重复 抓取以前抓取过的期刊。
运行爬虫
或者
1
| scrapy crawl luoo -a last_vol-number=800
|