Scrapy爬蟲實踐之搜索並獲取前程無憂職位信息(基礎篇)

一、開發環境

       OS:Windows 7 64bit旗艦版       
       Python:2.7.10       
       Scrapy:1.0.3       
       MySQL:5.6.21       
       Sublime Text2:2.0.2       
       具體的開發環境配置這裏就不介紹了,如需瞭解,歡迎與我交流。

二、目標

       通過在前程無憂的職位搜索中輸入職位關鍵詞獲取相應的職位信息,現在我們通過Scrapy爬蟲來實現這個功能,自動幫我們獲取相關的職位信息,並保存成.json格式和保存到MySQL數據庫。

三、實現步驟

      Scrapy是一個比較流行的Python爬蟲框架,Scrapy爬蟲的基本實現流程如下:

       1.通過scrapy startproject spiderproject 來創建一個新的爬蟲工程,spiderproject是我們自己命名的爬蟲工程。比如本例子,我們創建一個工程scrapy startproject qcwy,qcwy即爲我們的工程名。

       2.定義我們要解析具體數據的Item結構,在items.py文件中。

       3.在pipelines.py中實現數據存儲的功能,可以在這裏實現我們抓取的數據保存在.json文件中,或者MySQL中,或者SQLite中,或者MongoDB中,或者其他你要保存的格式或者數據庫中。

       4.在第1步創建的工程文件夾下的spider文件目錄下創建一個新的後綴爲.py的文件命名最好包含spider這個單詞,因爲我們要在這個文件中實現核心功能Spider。

       5.在setting.py中進行一些相關的設置。


     下面我們以詳細實例說明如何以Scrapy實現我們的目的:

      1.在CMD中輸入 cd c:\  進入c盤根目錄

       2.輸入scrapy startproject qcwy,我們可以看到在c盤根目錄下看到qcwy這個文件夾(本文假如你的開發環境配置沒有任何問題,具體配置請參照Scrapy文檔)。

       進入qcwy文件夾後,可以看到還有一個qcwy的文件夾和一個scrapy.cfg項目配置文件,不用管它,繼續進入qcwy這個文件夾,可以看到:


        3.定義我們要解析的數據的Item類

       實現items.py詳細代碼:

from scrapy.item import Item, Field

class QcwyItem(Item):
    #定義要抓取信息的Item結構
    title       = Field()   #職位名稱
    link        = Field()   #詳情鏈接
    company     = Field()   #公司名稱   
    updatetime  = Field()   #更新時間

  4.實現pipelines.py的詳細代碼:
import json
import codecs
import MySQLdb
import MySQLdb.cursors

from twisted.enterprise import adbapi
from scrapy import signals

class QcwyJsonPipeline(object):
    def __init__(self):
        self.file = codecs.open('..\\qcwy\\qcwy\\qcwy.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() 

class QcwyMySQLPipeline(object):
    """docstring for MySQLPipeline"""
    def __init__(self):
        self.connpool = adbapi.ConnectionPool('MySQLdb',
            host = '127.0.0.1',
            db = 'qcwy',
            user = 'root',
            passwd = '',
            cursorclass = MySQLdb.cursors.DictCursor,
            charset = 'utf8',
            use_unicode = True
            )
    def process_item(self, item, spider):
        query = self.connpool.runInteraction(self._conditional_insert, item)
        query.addErrback(self.handle_error)
        return item

    def _conditional_insert(self, tx, item):
        if item.get('title'):
            tx.execute("insert into detail (title, link, company, updatetime) values(%s, %s, %s, %s)", 
                (item['title'], item['link'], item['company'], item['updatetime']))

    def handle_error(self, e):
        log.err(e)
  

       5.Spider的實現 

# -*- coding: utf-8 -*-

import logging
import scrapy
import urllib
import codecs

from scrapy.selector import Selector

from qcwy.items import QcwyItem

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

keyword = "Python"
#把字符串編碼成符合url規範的編碼
keywordcode = urllib.quote(keyword)

is_start_page = True

class TestfollowSpider(scrapy.Spider):
   
    name = "qcwysearch"
    allowed_domains = ["51job.com"]
    start_urls = [
        "http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=030200%2C00&funtype=0000&industrytype=00&keyword=" + keywordcode,
    ]

    def parse(self, response):
        global is_start_page

        url = ""
        #從開始頁面開始解析數據,開始頁面start_urls
        if is_start_page:
            url = self.start_urls[0]
            is_start_page = False
        else:
            href = response.xpath('//table[@class="searchPageNav"]/tr/td[last()]/a/@href')
            url = response.urljoin(href.extract())

        yield scrapy.Request(url, callback=self.parse_dir_contents)
        

    def parse_dir_contents(self, response):

        for sel in response.xpath('//table[@id="resultList"]/tr[@class="tr0"]'):
            item = QcwyItem()
            temp = sel.xpath('td[@class="td1"]/a/text()').extract()
            if len(temp) > 0:
                item['title'] = temp[0] + keyword + temp[-1]
            else:
                item['title'] = keyword
            item['link'] = sel.xpath('td[@class="td1"]/a/@href').extract()[0]
            item['company'] = sel.xpath('td[@class="td2"]/a/text()').extract()[0]
            item['updatetime'] = sel.xpath('td[@class="td4"]/span/text()').extract()[0]
            yield item

        next_page = response.xpath('//table[@class="searchPageNav"]/tr/td[last()]/a/@href')
        if next_page:
            url = response.urljoin(next_page[0].extract())
            yield scrapy.Request(url, self.parse_dir_contents)

     6.在setting.py中加入:

ITEM_PIPELINES = {
    'qcwy.pipelines.QcwyJsonPipeline': 300,
    'qcwy.pipelines.QcwyMySQLPipeline': 800,
}

    
   7.在CMD中輸入cd c:\qcwy進入工程目錄

       輸入scrapy crawl qcwysearch

       然後查看生成的json文件,可以看到以下我們想要的信息:

{"company": "廣東威法科技發展有限公司", "link": "http://search.51job.com/job/70631365,c.html", "updatetime": "2015-09-29", "title": "中級後端Python工程師"}
{"company": "珠海橫琴新區蓋網通傳媒有限公司廣州分公司", "link": "http://search.51job.com/job/69706486,c.html", "updatetime": "2015-09-29", "title": "開發工程師Python開發工程師"}
{"company": "廣州明朝互動科技股份有限公司", "link": "http://search.51job.com/job/69898292,c.html", "updatetime": "2015-09-29", "title": "開發工程師Python開發工程師"}
{"company": "廣州市賽酷比軟件有限公司", "link": "http://search.51job.com/job/69816266,c.html", "updatetime": "2015-09-29", "title": "分佈式軟件架構師(Python..."}
{"company": "廣州市賽酷比軟件有限公司", "link": "http://search.51job.com/job/69816017,c.html", "updatetime": "2015-09-29", "title": "爬蟲工程師Python爬蟲工程師"}
{"company": "廣州傑升信息科技有限公司", "link": "http://search.51job.com/job/51077705,c.html", "updatetime": "2015-09-29", "title": "工程師Python工程師"}
{"company": "廣州飛屋網絡科技有限公司", "link": "http://search.51job.com/job/71800002,c.html", "updatetime": "2015-09-29", "title": "開發工程師Python開發工程師"}
{"company": "廣州飛屋網絡科技有限公司", "link": "http://search.51job.com/job/59931502,c.html", "updatetime": "2015-09-29", "title": "開發工程師Python開發工程師"}
{"company": "廣州達新信息科技有限公司", "link": "http://search.51job.com/job/69614188,c.html", "updatetime": "2015-09-29", "title": "開發工程師Python開發工程師"}
{"company": "廣州埃立方通信技術有限公司", "link": "http://search.51job.com/job/71920362,c.html", "updatetime": "2015-09-29", "title": "軟件工程師Python軟件工程師"}
{"company": "廣州黑珍珠計算機技術有限公司", "link": "http://search.51job.com/job/60592771,c.html", "updatetime": "2015-09-29", "title": "服務器端程序員Python服務器端程序員"}
{"company": "聚力精彩(北京)信息技術有限公司", "link": "http://search.51job.com/job/72246020,c.html", "updatetime": "2015-09-29", "title": "高級開發工程師AEBPython高級開發工程師AEB"}
{"company": "廣州七樂康藥業連鎖有限公司", "link": "http://search.51job.com/job/71362309,c.html", "updatetime": "2015-09-29", "title": "中級開發工程師Python中級開發工程師"}
{"company": "廣州七樂康藥業連鎖有限公司", "link": "http://search.51job.com/job/69404827,c.html", "updatetime": "2015-09-29", "title": " 初級開發工程師Python 初級開發工程師"}
{"company": "廣州七樂康藥業連鎖有限公司", "link": "http://search.51job.com/job/69207304,c.html", "updatetime": "2015-09-29", "title": "資深開發工程師Python資深開發工程師"}
{"company": "貴州格安科技有限公司廣州分公司", "link": "http://search.51job.com/job/63157264,c.html", "updatetime": "2015-09-29", "title": "高級Python開發工程師"}
{"company": "貴州格安科技有限公司廣州分公司", "link": "http://search.51job.com/job/60035771,c.html", "updatetime": "2015-09-29", "title": " 開發工程師Python 開發工程師"}
{"company": "珠海麒潤網絡科技有限公司", "link": "http://search.51job.com/job/51153619,c.html", "updatetime": "2015-09-29", "title": "PHP/Python開發工程師"}
{"company": "廣州百倫貿易有限公司", "link": "http://search.51job.com/job/71097137,c.html", "updatetime": "2015-09-29", "title": "開發工程師Python開發工程師"}
{"company": "廣州暴雨網絡技術有限公司", "link": "http://search.51job.com/job/69546409,c.html", "updatetime": "2015-09-29", "title": "服務端開發工程師Python服務端開發工程師"}

通過phpMyAdmin來查看MySQL數據庫,可以看到:



       8.完整源碼地址:  https://github.com/vrrobot/qcwy

      四、後記        這篇到這裏就結束了,網絡爬蟲這個技術作爲一個非常常規的獲取信息的手段,當然如果用作生產工具的話,還有一些不足的地方。比如:如何使爬蟲的行爲更像我們在使用瀏覽器在瀏覽信息。接下來,還會有本篇的後續進階篇。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章