scrapy框架的遞歸解析和post請求方式

遞歸爬取解析多頁頁面數據

需求展現

  將xx直聘網站搜索關鍵字後全部頁碼的做者和薪資數據進行爬取持久化存儲python

需求分析

  每個頁面對應一個url,則scrapy工程須要對每個頁碼對應的url依次發起請求,而後經過對應的解析方法進行做者和段子內容的解析cookie

實現方案

  1.將每個頁碼對應的url存放到爬蟲文件的起始url列表(start_urls)中。(不推薦)併發

  2.使用Request方法手動發起請求。
框架

 

代碼編輯

import scrapy
from bossPro.items import BossproItem

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(f'正在爬取第{self.page}頁的數據')
        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()
            job_salary=li.xpath('.//div[@class="info-primary"]/h3/a/span/text()').extract_first()

            item=BossproItem()
            item['job_title']=job_title
            item['job_salary']=job_salary
            yield  item   #提交item到管道進行持久化

        if self.page <=5:
            #要想訪問其餘頁碼的數據,須要手動發送請求
            new_url=format(self.url%self.page)
            self.page+=1
            #手動請求發送,call_back(回到函數)就是數據解析
            #在手動請求發送時必須加上yield
       #遞歸爬取數據,callback參數爲回調函數(將url請求後,獲得相應的數據繼續進行parse解析
            yield scrapy.Request(new_url,callback=self.parse)      

全站數據的爬取

- 全站數據的爬取
    - 基於手動請求發送實現
        - 實現全站數據爬取
        - 實現深度爬取
     - 手動請求發送:
        - yield scrapy.Request(url,callback)
        - yield scrapy.FormRequest(url,formdata,callback)

爬取網站標籤跳轉內容信息

 

  在上面的需求上再加上爬取每一個招聘崗位的詳細信息,這就須要咱們先行把每一個詳細信息的url爬取出來,再拿取詳細信息dom

代碼展現

# -*- 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))
        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發起手動請求
            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

深度爬取

- 深度爬取
    - 手動請求發送
    - 請求傳參:持久化存儲,將不一樣的回調中解析的數據存儲到同一個item對象。請求傳參傳遞的就是item對象。
        - 使用場景:若是使用scrapy爬取的數據沒有在同一張頁面中
        - 傳遞方式:將傳遞數據封裝到meta字典中,meta傳遞個了callback
            yield scrapy.Request(url,callback,meta)
        - 接收:
            在callback指定的回調函數中使用response進行接收:
                - item = response.meta['key']

五大核心組件工做流程

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

post請求發送

- 問題:在以前代碼中,咱們歷來沒有手動的對start_urls列表中存儲的起始url進行過請求的發送,可是起始url的確是進行了請求的發送,那這是如何實現的呢?異步

- 解答:實際上是由於爬蟲文件中的爬蟲類繼承到了Spider父類中的start_requests(self)這個方法,該方法就能夠對start_urls列表中的url發起請求:scrapy

  def start_requests(self):
        for u in self.start_urls:
           yield scrapy.Request(url=u,callback=self.parse)

注意:該方法默認的實現,是對起始的url發起get請求,若是想發起post請求,則須要子類重寫該方法。ide

  -方法: 重寫start_requests方法,讓其發起post請求:函數

def start_requests(self):
        #請求的url
        post_url = 'http://fanyi.baidu.com/sug'
        # post請求參數
        formdata = {
            'kw': 'wolf',
        }
        # 發送post請求
        yield scrapy.FormRequest(url=post_url, formdata=formdata, callback=self.parse)

如何提升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

Scrapy的日誌等級

  - 在使用scrapy crawl spiderFileName運行程序時,在終端裏打印輸出的就是scrapy的日誌信息。

  - 日誌信息的種類:

        ERROR : 通常錯誤

        WARNING : 警告

        INFO : 通常的信息

        DEBUG : 調試信息

       

  - 設置日誌信息指定輸出:

    在settings.py配置文件中,加入

                    LOG_LEVEL = ‘指定日誌信息種類’便可。

                    LOG_FILE = 'log.txt'則表示將日誌信息寫入到指定文件中進行存儲。
相關文章
相關標籤/搜索