scrapy框架之進階

五大核心組件

- 引擎(Scrapy)
    用來處理整個系統的數據流處理, 觸發事務(框架核心)
- 調度器(Scheduler)
    用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 能夠想像成一個URL(抓取網頁的網址或者說是連接)的優先隊列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址
- 下載器(Downloader)
    用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是創建在twisted這個高效的異步模型上的)
- 爬蟲(Spiders)
    爬蟲是主要幹活的, 用於從特定的網頁中提取本身須要的信息, 即所謂的實體(Item)。用戶也能夠從中提取出連接,讓Scrapy繼續抓取下一個頁面
- 項目管道(Pipeline)
    負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證明體的有效性、清除不須要的信息。當頁面被爬蟲解析後,將被髮送到項目管道,並通過幾個特定的次序處理數據。

scrapy工做原理

舊版python

新版cookie

如何提高scrapy爬取數據的效率

增長併發:
    默認scrapy開啓的併發線程爲32個,能夠適當進行增長。在settings配置文件中修改CONCURRENT_REQUESTS = 100值爲100,併發設置成了爲100。

下降日誌級別:
    在運行scrapy時,會有大量日誌信息的輸出,爲了減小CPU的使用率。能夠設置log輸出信息爲INFO或者ERROR便可。在配置文件中編寫:LOG_LEVEL = ‘INFO’

禁止cookie:
    若是不是真的須要cookie,則在scrapy爬取數據時能夠禁止cookie從而減小CPU的使用率,提高爬取效率。在配置文件中編寫:COOKIES_ENABLED = False

禁止重試:
    對失敗的HTTP進行從新請求(重試)會減慢爬取速度,所以能夠禁止重試。在配置文件中編寫:RETRY_ENABLED = False

減小下載超時:
    若是對一個很是慢的連接進行爬取,減小下載超時能夠能讓卡住的連接快速被放棄,從而提高效率。在配置文件中進行編寫:DOWNLOAD_TIMEOUT = 10 超時時間爲10s

全站抓取數據

# get請求
yield scrapy.Request(url,callback)

# post請求
yield scrapy.FormRequest(url,formdata,callback)

示例代碼併發

get請求抓取全部頁碼數據框架

# -*- coding: utf-8 -*-
import scrapy
from quanzhanzhuaqu.items import QuanzhanzhuaquItem

class QzzqSpider(scrapy.Spider):
    name = 'qzzq'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://www.zhipin.com/job_detail/?query=python&city=101010100&industry=&position=']

    # 通用url模板
    url = "https://www.zhipin.com/c101010100/?query=python&page=%d"
    page = 1
    def parse(self, response):
        print('正在爬取第{}頁的數據'.format(self.page))
        job_title = response.xpath('//div[@class="job-title"]/text()').extract()
        red = response.xpath('//span[@class="red"]/text()').extract()

        for i in range(len(job_title)):
            item = QuanzhanzhuaquItem()
            item["job_title"] = job_title[i]
            item["red"] = red[i]
            yield item

        # 爬取頁碼
        if self.page<5:
            # 對其餘頁碼進行手動請求
            new_url = format(self.url%self.page)
            self.page+=1

            # 手動請求
            # callback進行數據解析
            yield scrapy.Request(url=new_url,callback=self.parse)

深度抓取

scrapy.Request(url=detail_url,callback=self.parse_detail,meta={'item':item})

# 這裏用到meta參數能夠將item對象傳給回調函數,使其parse和parse_detail共享一個item對象
# -*- coding: utf-8 -*-
import scrapy
from bossDeepPro.items import BossdeepproItem

class BossSpider(scrapy.Spider):
    name = 'boss'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://www.zhipin.com/job_detail/?query=python%E5%BC%80%E5%8F%91&city=101010100&industry=&position=']

    # 通用的url模板(不可變)
    url = 'https://www.zhipin.com/c101010100/?query=python開發&page=%d'
    page = 2

    def parse(self, response):
        print('正在爬取第{}頁的數據'.format(self.page))
        
        # 這裏的xpath寫了兩種,由於每頁的匹配規則不同
        li_list = response.xpath('//*[@id="main"]/div/div[3]/ul/li | //*[@id="main"]/div/div[2]/ul/li')
        for li in li_list:
                job_title = li.xpath('.//div[@class="info-primary"]/h3/a/div[1]/text()').extract_first()
                salary = li.xpath('.//div[@class="info-primary"]/h3/a/span/text()').extract_first()
            #實例化item對象:對象必需要讓parse和parse_detail共享
            item = BossdeepproItem()
            item['job_title'] = job_title
            item['salary'] = salary

            detail_url = 'https://www.zhipin.com'+li.xpath('.//div[@class="info-primary"]/h3/a/@href').extract_first()
            
            #對詳情頁的url發起手動請求,並將item對象傳給回調函數
            yield scrapy.Request(url=detail_url,callback=self.parse_detail,meta={'item':item})


        if self.page <= 5:
            # 對其餘頁碼進行手動請求的發送
            new_url = format(self.url % self.page)
            print(new_url)
            self.page += 1
            # 手動請求發送
            # callback進行數據解析
            yield scrapy.Request(url=new_url, callback=self.parse)

    #解析崗位描述
    def parse_detail(self,response):
        item = response.meta['item']
        job_desc = response.xpath('//*[@id="main"]/div[3]/div/div[2]/div[2]/div[1]/div//text()').extract()
        job_desc = ''.join(job_desc)

        item['job_desc'] = job_desc

        yield item
相關文章
相關標籤/搜索