1. 程式人生 > >scrapy爬蟲之crawlspide爬取豆瓣近一週同城活動

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": ["設計互聯開>幕大展——“數字之維”及“設計的價值”展覽"]},
.....
]