scrapy爬蟲之crawlspide爬取豆瓣近一週同城活動
簡介
本文主要介紹crawlspider爬取豆瓣近一週同城活動。
要點:item/itemloader利用input_processor/output_processor對爬取的資料進行過濾。
實現
為了演示資料過濾,我們只爬取到第二頁的資料。
一、定義item
vim items.py
class tongcheng(scrapy.Item):
#主題
title = scrapy.Field()
#時間
time = scrapy.Field()
#地址
address = scrapy.Field (output_processor=Join())
#票價
money = scrapy.Field()
#感興趣人數
intrest = scrapy.Field()
#參加人數
join = scrapy.Field()
二、定義爬蟲
# -*- coding: utf-8 -*-
#爬取豆瓣近一週同城活動
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy.loader import ItemLoader
from douban.items import tongcheng
class TongchengSpider(CrawlSpider):
name = 'tongcheng'
allowed_domains = ['douban.com']
start_urls = ['https://www.douban.com/location/shenzhen/events/week-all']
rules = (
#匹配到第二頁
Rule(LinkExtractor(allow=r'start=10' )),
#獲取每頁資料
Rule(LinkExtractor(allow=r'https://www.douban.com/event/\d+/'),callback='parse_item'),
)
def parse_item(self, response):
loader = ItemLoader(item=tongcheng(),selector=response)
info = loader.nested_xpath('//div[@class="event-info"]')
info.add_xpath('title','h1[@itemprop="summary"]/text()')
info.add_xpath('time','div[@class="event-detail"]/ul[@class="calendar-strs"]/li/text()')
info.add_xpath('address','div[@itemprop="location"]/span[@class="micro-address"]/span[@class="micro-address"]/text()')
info.add_xpath('money','div[@class="event-detail"]/span[@itemprop="ticketAggregate"]/text()')
info.add_xpath('intrest','div[@class="interest-attend pl"]/span[1]/text()')
info.add_xpath('join','div[@class="interest-attend pl"]/span[3]/text()')
yield loader.load_item()
三、執行爬蟲
scrapy crawl toncheng -o tongcheng.json
vi toncheng.json
[
{"money": ["費用: \n 100元(預售)起\n "], "address": "深圳 南山區 華僑城創意園 北區C2棟北側 B10現場", "join": ["65 "], "intrest": ["63 "], "title": ["張瑋瑋和郭龍“沿江而來”巡演深圳站 @B10現場\n\n\n "]},
{"money": ["費用: \n \n 93 - 281元\n "], "address": "深圳 南山文體中心劇院 小劇場 深圳市南山區南山大>道南山文體中心", "join": ["0 "], "intrest": ["1 "], "title": ["2018第五屆城市戲劇節 以色列國寶級作家名著改編 王子川自導自演《雅各比和雷彈頭》-深圳\n\n\n "]},
{"money": ["費用: \n \n 95 - 361元\n "], "address": "深圳 南山文體中心劇院大劇院 南山大道與南頭街交匯
處南山文體中心", "join": ["6 "], "intrest": ["10 "], "title": ["【萬有音樂系】My Song--Sophie Zelmani 蘇菲 · 珊曼妮2018巡迴演唱會\n\n\n "]},
{"money": ["費用: \n \n 263 - 357元\n "], "address": "深圳 深圳市少年宮劇場 深圳市福田區福中一路市少>年宮", "join": ["67 "], "intrest": ["158 "], "title": ["孟京輝戲劇作品《一個陌生女人的來信》深圳站\n\n\n "]},
{"money": ["費用: \n \n 170 - 483元\n "], "address": "深圳 華潤深圳灣體育中心"春繭"體育場 深圳市濱>海大道3001號(南山區科苑南路與海德三道交匯處)", "join": ["37 "], "intrest": ["66 "], "title": ["亞洲之巔群星演唱會-深圳站\n ", "\n\n\n "]},
......
]
從上面的輸出我們看到:
title欄位帶空格,我們需要的是去除空格的資料;
money欄位是[“費用: \n \n 263 - 357元\n “],我們需要的是[”263 - 357元”];
我們需要使用item/itemloader的input_processor/output_processor對資料進行過濾,例如我們已經對address欄位使用了output_processor=Join(),我們還需使用MapCompose方法進行過濾。
四、MapCompose
class scrapy.loader.processors.MapCompose(*functions, **default_loader_context)
MapCompose方法接受的資料是可迭代的,資料會經過第一個function進行處理,生成的新的迭代資料會進入第二個函式,以此類推直至所有函式都處理完,生成最終的迭代資料。
1、title欄位
title欄位需要unicode.strip去處空格,在item中定義如下:
title = scrapy.Field(input_processor=MapCompose(unicode.strip))
MapCompose通常被用作input_processor,因為我們用selector提取返回的的是可迭代資料。
另外scrapy 會將含有中文的field輸出為 unicode字串形式,因此我們使用unicode.strip來去除空格。
2、money欄位
money欄位提取的是[“費用: \n \n 263 - 357元\n “],我們只要”263 - 357元”。具體實現如下:
vim items.py
def filter_string(x):
str = x.split(':')
return str[1].strip()
money = scrapy.Field(input_processor=MapCompose(filter_string))
filter_string函式的功能就是提取263 - 357元。我們通過MapCompose中呼叫filter_string,將提取的資料過濾為我們想要的資料。
因此,完整的item程式碼如下:
# -*- coding: utf-8 -*-
import scrapy
from scrapy.loader.processors import Join, MapCompose, TakeFirst
def filter_string(x):
str = x.split(':')
return str[1].strip()
class tongcheng(scrapy.Item):
title = scrapy.Field(input_processor=MapCompose(unicode.strip))
time = scrapy.Field()
address = scrapy.Field(output_processor=Join())
money = scrapy.Field(input_processor=MapCompose(filter_string))
intrest = scrapy.Field()
join = scrapy.Field()
通過定義item後,我們最終提取的資料如下:
[
{"money": ["100元(預售)起"], "address": "深圳 南山區 華僑城創意園 北區C2棟北側 B10現場", "join": ["65 "], "intrest": ["63 "], "title": ["張瑋瑋和郭>龍“沿江而來”巡演深圳站 @B10現場"]},
{"money": ["93 - 281元"], "address": "深圳 南山文體中心劇院 小劇場 深圳市南山區南山大道南山文體中心", "join": ["0 "], "intrest": ["1 "], "title": ["2018第五屆城市戲劇節 以色列國寶級作家名著改編 王子川自導自演《雅各比和雷彈頭》-深圳"]},
{"money": ["95 - 361元"], "address": "深圳 南山文體中心劇院大劇院 南山大道與南頭街交匯處南山文體中心", "join": ["6 "], "intrest": ["10 "], "title": ["【萬有音樂系】My Song--Sophie Zelmani 蘇菲 · 珊曼妮2018巡迴演唱會"]},
{"money": ["263 - 357元"], "address": "深圳 深圳市少年宮劇場 深圳市福田區福中一路市少年宮", "join": ["67 "], "intrest": ["158 "], "title": ["孟京輝戲
劇作品《一個陌生女人的來信》深圳站"]},
{"money": ["170 - 483元"], "address": "深圳 華潤深圳灣體育中心"春繭"體育場 深圳市濱海大道3001號(南山區科苑南路與海德三道交匯處)", "join": ["37 "], "intrest": ["66 "], "title": ["亞洲之巔群星演唱會-深圳站", ""]},
{"money": ["59元"], "address": "深圳 海上世界文化藝術中心 深圳市南山區蛇口望海路1187號", "join": ["80 "], "intrest": ["116 "], "title": ["設計互聯開>幕大展——“數字之維”及“設計的價值”展覽"]},
.....
]