Scrapy基礎(二): 使用詳解

weixin_34148340發表於2018-12-12

scrapy的安裝和基本介紹請看 www.jianshu.com/p/a71386fa3…

  • Spider

scrapy的網站爬取需要繼承scrapy.Spider類,會根據配置的初始url自動下載網頁資訊,並呼叫parse方法,下載的網頁資訊會通過parse方法的response引數進行傳遞 例:

class JobboleSpider(scrapy.Spider):
    name = 'jobbole'  # spider名稱
    allowed_domains = ['blog.jobbole.com']  # 域名
    start_urls = ['http://blog.jobbole.com/all-posts/'] # 其實url

    def parse(self, response): 
複製程式碼

啟動方式為

scrapy crawl jobbole  # jobbole為spider名稱
複製程式碼
  • MiddleWare

Spider產生的Request請求會在一系列排程後,流經一個個MiddleWare,最終到達Downloader進行真正的Http的請求並得到相應,我們可以自定義MiddleWare,並在settings檔案進行順序配置,定製化下載前的準備工作,比如加入User-Agent隨機切換,Ip代理池的設定,Selenium代理下載等

自定義Middleware需要過載4個函式來做不同的處理

class CustomMiddleWare
    # 定義這個方法,Scrapy會把當前的爬蟲傳遞到方法裡來
    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler)

    # 處理request請求
    def process_request(self, request, spider):
            pass

    # 處理response請求
    def process_response(self, response, spider):
           pass

     # 處理異常情況
    def process_exception(self, response, spider):
           pass
複製程式碼

settings 配置

# 下載服務管理器
DOWNLOADER_MIDDLEWARES = {
    'ArticleSpider.middlewares.RandomUserAgentMiddlware': 100,
    # 'ArticleSpider.middlewares.RandomProxyMiddleware': 200,
    # 'ArticleSpider.middlewares.JSPageMiddleware': 300,
    # 如果自定義了User-Agent的MiddleWare,需要將scrapy的預設Middleware置為None
    'ScrapyRedisTest.middlewares.MyCustomDownloaderMiddleware': None,
}
複製程式碼
  • Item

使用scrapy.Spider爬取好相關資料後,需要將資料進行儲存,資料在scrapy中流轉是通過Item來實現,使用Item來定義scray的模型model,需要繼承scrapy.Item類 例:

class JobBoleArticleItem(scrapy.Item):
    # 使用scrapy.Field進行資料的定義規則
    title = scrapy.Field(
        input_processor=MapCompose(lambda x:x+"-jobbole",add_jobbole)
    )
    create_date = scrapy.Field(
        input_processor=MapCompose(date_covert)
    )
    url = scrapy.Field()
    url_object_id = scrapy.Field()
    front_image_url = scrapy.Field(
        output_processor=MapCompose(return_value)
    )
    front_image_path = scrapy.Field()
    praise_nums = scrapy.Field(
        input_processor=MapCompose(get_nums)
    )
    common_nums = scrapy.Field(
        input_processor=MapCompose(get_nums)
    )
    fav_nums = scrapy.Field(
        input_processor=MapCompose(get_nums)
    )
    tags = scrapy.Field(
        input_processor=MapCompose(remove_comment_tags),
        output_processor=Join(",")
    )
    content = scrapy.Field()
複製程式碼

scrapy.Field可以接收input_processor,output_processor等來定義資料的包裝規則,MapCompose會依次呼叫引數方法(引數方法需要接收一個value引數,返回按照相應規則包裝好的值) 例如將create_date(str型別)轉換成(date型別)

def date_covert(value):
    try:
        create_date = datetime.datetime.strptime(value,"%Y/%m/%d").date()
    except Exception as e:
        create_date = datetime.datetime.now().date()

    return create_date
...
  create_date = scrapy.Field(
        input_processor=MapCompose(date_covert)
    )
...
複製程式碼

可以通過繼承ItemLoader類自定義預設的input_processor,output_processor

class ArticleItemLoader(ItemLoader):
    #自定義output_processor
    default_output_processor = TakeFirst()
複製程式碼

Spider 提取相應資料後需要將資料包裝成Item

    def parse(self, response): 
        article_item = JobBoleArticleItem()
...
...
        yield article_item
複製程式碼
  • Pipeline

Spider 講資料包裝成Item以後,scrapy會按照在setting是中配置的順序進行執行pipeline的類方法,進行資料的持久化或其他的下載操作 每一個Pipeline需要有一個process_item方法,接收一個item引數,做完相應處理後返回item,並在settings.py中配置執行順序

settings.py

數字小的先執行

ITEM_PIPELINES = {
    # 'scrapy.pipelines.images.ImagesPipeline': 1,
     'ArticleSpider.pipelines.ArticleImagePipeline':1,
    # 'ArticleSpider.pipelines.JsonExporterPipeline': 2,
    'ArticleSpider.pipelines.MysqlTwistedPipeline': 2,
}
複製程式碼

Pipeline

class ArticlespiderPipeline(object):
    def process_item(self, item, spider):
        # 做具體的執行邏輯 
        return item
複製程式碼

上面講的一些Settings的配置,是所有爬蟲的統一配置,如果需要在每個爬蟲裡自定義配置,可以使用custom_settings變數覆蓋統一配置

custom_settings = {
        "COOKIES_ENABLED": False,
        "DOWNLOAD_DELAY": 0
    }
複製程式碼

具體例項地址 github.com/MarkGao1152…

相關文章