Scrapy爬蟲:實習僧網最新招聘資訊抓取

funnyok發表於2021-09-09

一:前言

繼續練習Scrapy框架,這次抓取的是實習僧網最新的招聘資訊,包括招聘崗位,時間,工資,學歷要求,職位誘惑和職位描述等等。之後儲存到mongodb和json檔案中以備後續使用。爬蟲中遇到了很多問題,比如不同解析函式傳值、xpath配合正則、職位描述的網頁結構多變,這些都一一解決了。程式碼地址:

二:執行環境

  • IDE:Pycharm 2017

  • Python3.6

  • pymongo 3.4.0

  • scrapy 1.3.3

三:例項分析

1.首先進入官網: 然後點選進入更多職位後就可以看見下面這樣網頁。

圖片描述

招聘主頁之後點選最新發布,觀察一下網址變化。當點選下一頁的時候網址已經變成了 ,這就說明了網址的構成就是“p=”後面就是網頁的數目,隨後我們將使用列表迭代生成我們爬取的頁面地址。圖片描述

start_urls = ['{}'.format(n) for n in range(1, 501)]

2.知道主網址構成後,就進入開發者模式看看每個招聘資訊的具體網址。這裡只是一個不含有域名的連結,那麼就需要自己構成對應詳細的招聘資訊網址

links = response.xpath('//div[@class="po-name"]/div[1]/a/@href').extract()for link in links:
    dlink = '' + link


3.進入詳細的招聘網址後,明確要抓取的資料如下圖。然後使用xpath抓取,這裡有幾個要注意的地方。re_first()即可在獲取到使用正則匹配合適的第一個內容。獲取工資、地理位置、學歷、時間這一欄中會遇到分隔符 “|” 所以必要的時候匹配中文即可。圖片描述

        item['name'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[1]/span[1]/span/text()').extract_first()
        item['link'] = response.meta['link']
        item['company'] = response.xpath('//*[@id="container"]/div[1]/div[2]/div[1]/p[1]/a/text()').extract_first()
        item['place'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[2]/@title').extract_first()
        item['education'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[3]/text()').re_first(r'[u4e00-u9fa5]+')
        item['people'] = response.xpath('//*[@id="container"]/div[1]/div[2]/div[1]/p[2]/span/text()').extract()[1]
        item['money'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[1]/text()').re_first(r'[^s]+')
        item['week'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[4]/text()').extract_first()
        item['month'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[5]/text()').extract_first()
        item['lure'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/p/text()').extract_first()
        item['description'] = response.xpath('//div[@class="dec_content"]/*/text()|//div[@class="dec_content"]/text()').extract()
        item['data'] = response.xpath('//*[@id="container"]/div[1]/div[1]/p[3]/text()').extract()

四:實戰程式碼

前面已經完成了網頁結構分析和所需資料的抓取方法,下面就開始使用Scrapy框架來完成這次任務。完整程式碼位置:
1.首先使用命令列工具輸入程式碼建立一個新的Scrapy專案,之後建立一個爬蟲。

scrapy startproject ShiXiSengcd ShiXiSengShiXiSengspiders
scrapy genspider shixi shixiseng.com

2.開啟ShiXiSeng資料夾中的items.py,改為以下程式碼,定義我們爬取的專案。

import scrapyclass ShixisengItem(scrapy.Item):
    name = scrapy.Field()
    link = scrapy.Field()
    company = scrapy.Field()
    people = scrapy.Field()
    place = scrapy.Field()
    education = scrapy.Field()
    money = scrapy.Field()
    week = scrapy.Field()
    month = scrapy.Field()
    lure = scrapy.Field()
    description = scrapy.Field()
    data = scrapy.Field()

3.配置middleware.py配合settings中的User_Agent設定可以在下載中隨機選擇UA有一定的反ban效果,在原有程式碼基礎上加入下面程式碼。這裡的user_agent_list可以加入更多。

import randomfrom scrapy.downloadermiddlewares.useragent import UserAgentMiddlewareclass RotateUserAgentMiddleware(UserAgentMiddleware):
    def __init__(self, user_agent=''):
        self.user_agent = user_agent    def process_request(self, request, spider):
        ua = random.choice(self.user_agent_list)        if ua:
            print(ua)
            request.headers.setdefault('User-Agent', ua)

    user_agent_list = [        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"
        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",        "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",        "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",

    ]

4.明確一下目標,這是抓取的資料儲存到mongodb資料庫中和本地json檔案。所以需要設定一下Pipelines.py

import json
import pymongo
from scrapy.conf import settingsclass ShixisengPipeline(object):
    def __init__(self):        self.client = pymongo.MongoClient(host=settings['MONGO_HOST'], port=settings['MONGO_PORT'])        self.db = self.client[settings['MONGO_DB']]        self.post = self.db[settings['MONGO_COLL']]    def process_item(self, item, spider):
        postItem = dict(item)        self.post.insert(postItem)        return itemclass JsonWriterPipeline(object):
    def __init__(self):        self.file = open('shixi.json', 'w', encoding='utf-8')    def process_item(self, item, spider):
        line = json.dumps(dict(item), ensure_ascii=False) + "n"
        self.file.write(line)        return item    def spider_closed(self, spider):        self.file.close()

5.然後setting.py裡面也要修改一下,這樣才能啟動Pipeline相關配置,最後可以儲存相關資料。

BOT_NAME = 'ShiXiSeng'SPIDER_MODULES = ['ShiXiSeng.spiders']
NEWSPIDER_MODULE = 'ShiXiSeng.spiders'# 配置mongodbMONGO_HOST = "127.0.0.1"  # 主機IPMONGO_PORT = 27017  # 埠號MONGO_DB = "Shixiseng"  # 庫名MONGO_COLL = "info"  # collection名# pipeline檔案的入口,這裡進ITEM_PIPELINES = {    'ShiXiSeng.pipelines.JsonWriterPipeline': 300,    'ShiXiSeng.pipelines.ShixisengPipeline': 300,
}# 設定隨機User_AgentDOWNLOADER_MIDDLEWARES = {    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,    'ShiXiSeng.middlewares.RotateUserAgentMiddleware': 400,
}

ROBOTSTXT_OBEY = False  # 不遵循網站的robots.txt策略DOWNLOAD_DELAY = 1  # 下載同一個網站頁面前等待的時間,可以用來限制爬取速度減輕伺服器壓力。COOKIES_ENABLED = False  # 關閉cookies

6.這次最重要的部分就是spider中的shixi.py

# -*- coding: utf-8 -*-import scrapyfrom ShiXiSeng.items import ShixisengItemfrom scrapy import Requestclass ShixiSpider(scrapy.Spider):
    name = "shixi"
    allowed_domains = ["shixiseng.com"]
    start_urls = ['{}'.format(n) for n in range(1, 501)]
    headers = {        'Host': '',        'Connection': 'keep-alive',        'Cache-Control': 'max-age=0',        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',        'Upgrade-Insecure-Requests': '1',        'Referer': '',        'Accept-Encoding': 'gzip,deflate,sdch',        'Accept - Language': 'zh-CN,zh;q=0.8,en;q=0.6'
    }    def parse(self, response):
        links = response.xpath('//div[@class="po-name"]/div[1]/a/@href').extract()        for link in links:
            dlink = '' + link            yield Request(dlink, meta={'link': dlink}, headers=self.headers, callback=self.parser_detail)    def parser_detail(self, response):
        item = ShixisengItem()
        item['name'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[1]/span[1]/span/text()').extract_first()
        item['link'] = response.meta['link']
        item['company'] = response.xpath('//*[@id="container"]/div[1]/div[2]/div[1]/p[1]/a/text()').extract_first()
        item['place'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[2]/@title').extract_first()
        item['education'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[3]/text()').re_first(r'[u4e00-u9fa5]+')
        item['people'] = response.xpath('//*[@id="container"]/div[1]/div[2]/div[1]/p[2]/span/text()').extract()[1]
        item['money'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[1]/text()').re_first(r'[^s]+')
        item['week'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[4]/text()').extract_first()
        item['month'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/span[5]/text()').extract_first()
        item['lure'] = response.xpath('//*[@id="container"]/div[1]/div[1]/div[2]/p/text()').extract_first()
        item['description'] = response.xpath('//div[@class="dec_content"]/*/text()|//div[@class="dec_content"]/text()').extract()
        item['data'] = response.xpath('//*[@id="container"]/div[1]/div[1]/p[3]/text()').extract()[0]        yield item

①這裡面涉及到了不同解析函式的傳值問題,首先是從start_urls開始請求每一個連結然後得到的respose傳給parser()函式進行第一次解析,這個函式的作用就是獲取該頁面上的每一個招聘頁面的連結,之後yield一個Request()函式,使用meta這個引數即可傳值,型別是dict,這裡就把連結傳給了parser_detail() 函式然後做進一步的解析獲取最後想要的資料。
②使用了
正則+xpath
來獲取準確的資料

五:總結

執行程式碼後就會獲取實習僧最新的全部的招聘資料,一共大概是5000條資料很快就可以抓取下來儲存到mongodb資料庫和本地的json檔案中。
程式碼都放在github中了,有喜歡的朋友可以點選 start follw,歡迎一起學習交流。** **


作者:rieuse
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3137/viewspace-2803064/,如需轉載,請註明出處,否則將追究法律責任。

相關文章