天天看點

用scrapy架構抓取51job銷售職位資訊實戰-- coding: utf-8 --導入子產品extract() 擷取到網頁标簽的内容,傳回清單

scrapy實戰之spider篇

在我看來,使用scrapy架構相較于直接用python爬蟲庫的優點有兩個

第一是scrapy更加有效率,而爬蟲自然最注重的是效率

第二是scrapy将爬蟲的過程分成子產品化,使爬蟲抓取過程更加清晰

scrapy主要有三個子產品spider,pipeline,items.其中items代表的是容器(儲存所需要爬取的資料),

spider代表的是爬蟲子產品(将爬取的html内容用Xpath或者bs或者正規表達式解析,并且儲存在容器中),

pipeline代表的是資料處理子產品(eg.資料去重,資料清洗,資料儲存在mysql資料庫)

現在開始爬取資料

首先是建立scrapy項目

用scrapy架構抓取51job銷售職位資訊實戰-- coding: utf-8 --導入子產品extract() 擷取到網頁标簽的内容,傳回清單

然後開始寫爬蟲

第一是要明确需求,觀察網頁

用scrapy架構抓取51job銷售職位資訊實戰-- coding: utf-8 --導入子產品extract() 擷取到網頁标簽的内容,傳回清單

分析的要爬取的字段有職位名(job),公司(company),地點(place),薪資(salary),

最高薪資(highest_salary),最低薪資(lowest_salary),釋出時間(time)

再檢查html網頁,分析網頁結構

用scrapy架構抓取51job銷售職位資訊實戰-- coding: utf-8 --導入子產品extract() 擷取到網頁标簽的内容,傳回清單

分析得每段資料都是用div區分,而這種html結構用xpath解析比較友善

爬蟲解析方法主流的有三種,bs和xpath和正規表達式,其中正規表達式效率最高但是難度也是最大的,xpath難度中等,bs較簡單也是效率最低的

下面簡單介紹下xpath

主要為/ 和//

//代表無論該節點的位置,均找到它

/代表找節點的子節點,注意不能找子孫節點

@表示屬性

eg.//div[@class=”el”]代表的找到屬性為el的所有div節點下的所有元素

下面有一段html大家可以練習

<html> <head> <title>春晚</title> </head> <body> <h1 name="title">個人簡介</h1> <div name="desc"> <p name="name">姓名:<span>小嶽嶽</span></p> <p name="addr">住址:中國 河南</p> <p name="info">代表作:五環之歌</p> </div>’‘

然後講解實戰内容,先貼出spider代碼

需要在python中進入項目目錄再編寫

“`

-- coding: utf-8 --

導入子產品

import scrapy

from job.items import JobItem #第一個錯誤

class XsSpider(scrapy.Spider):

name = ‘xs’

allowed_domains = [‘51job.com’]

start_urls = [‘

extract() 擷取到網頁标簽的内容,傳回清單

zw = item.xpath('p/span/a/text()').extract()  # 職位
        gs = item.xpath('span[@class="t2"]/a/text()').extract()  # 公司名稱
        dd = item.xpath('span[@class="t3"]/text()').extract()  # 地點
        xz = item.xpath('span[@class="t4"]/text()').extract()  # 薪資
        rt = item.xpath('span[@class="t5"]/text()').extract()  # 釋出時間
        href = item.xpath('p[@class="t1 "]/span/a/@href').extract()  # 詳細頁面連接配接
    # 資料存儲
        if zw:
            item_1['job'] = zw[0]
        else:
            item_1['job'] = ''
        if gs:
            item_1['company'] = gs[0]
        else:
            item_1['company'] = ''
        if dd:
            item_1['place'] = dd[0]
        else:
            item_1['place'] = '-'
        if xz:
            item_1['salary'] = xz[0]
        else:
            item_1['salary'] = ''
        if rt:
            item_1['time'] = rt[0]
        else:
            item_1['time'] = ''
        if href:
            item_1['href'] = href[0]
        yield item_1

            # 取下一頁的資料hred以清單形式

            # 取下一頁的資料hred以清單形式
    # 跳轉到下一頁
    # 錯誤的原因是沒有注意縮進,導緻邏輯錯誤,跳轉是要在讀取完一個頁面後才能跳轉 不能在for循環内

    next_page = response.xpath('//div[@class="dw_page"]//ul/li[last()]/a/@href').extract()
    if next_page:
        # 從清單中取到下一頁的連接配接
        next_page_href = next_page[0]
            # url:請求下一頁的url
            # callback:函數回調,請求到内容後調用哪個函數,寫函數名
        yield scrapy.Request(url=next_page_href, callback=self.parse,dont_filter=True)
           

`

針對一些複雜不易了解的地方進行講解

用scrapy架構抓取51job銷售職位資訊實戰-- coding: utf-8 --導入子產品extract() 擷取到網頁标簽的内容,傳回清單

main的作用是儲存xpath解析到的内容,傳回的是清單内容。是以要用for語句周遊,

JobItem()是容器,是從item中導入的,需要在周遊裡面接受周遊的内容

用scrapy架構抓取51job銷售職位資訊實戰-- coding: utf-8 --導入子產品extract() 擷取到網頁标簽的内容,傳回清單

if語句是防止用xpath解析的字段是空的,會導緻後面的字段占位,是以需要用if語句判斷字段是否是空的,如果是空的賦給它空字元串占位,如果不是空就占位

這一步很重要,如果不做if判斷會造成資料錯位

用scrapy架構抓取51job銷售職位資訊實戰-- coding: utf-8 --導入子產品extract() 擷取到網頁标簽的内容,傳回清單

對于yield

yield是python的生成器,與return相似,但是這裡需要用yield而不能用return,因為return是每循環一次傳回一次值,沒有記憶儲存功能,yield具有記憶儲存功能,它不傳回值而是記憶該值并儲存在容器中,而這正是我們需要的

用scrapy架構抓取51job銷售職位資訊實戰-- coding: utf-8 --導入子產品extract() 擷取到網頁标簽的内容,傳回清單

這個是調用下一頁,翻頁的功能

可以調用模闆,注意callback函數就好

下一篇是pipelines代碼部分的講解

有需要爬蟲資料的可以call我