python 爬蟲 如何通過scrapy框架簡單爬取網站資訊--以51job為例
阿新 • • 發佈:2018-12-14
Scrapy框架三大優點:
- Scrapy框架是用純Python實現一個為了爬取網站資料、提取結構性資料而編寫的應用框架,用途非常廣泛。
- 框架的力量,使用者只需要定製開發幾個模組就可以輕鬆的實現一個爬蟲,用來抓取網頁內容以及各種圖片,非常之方便。
- Scrapy 可以加快我們的下載速度,不用自己去實現非同步框架,並且包含了各種中介軟體介面,可以靈活的完成各種需求。
scrapy實現流程圖:
scrapy各個模組簡單介紹:
步驟:
1.開啟pycharm3.6 2.開啟terminal命令列輸入’scrapy startproject 專案名’,就會建立一個scrapy專案的資料夾 3.建立scrapy主程式,爬蟲主要過程都在這裡實現,同樣在命令列輸入’scrapy crawl -t 資料夾名 url’這裡url是要爬取的網址,黏貼進去,就會建立一個模板。 4.開啟剛建立的py檔案,填入網址,這裡以51job為例 程式碼如下:
from scrapy.spider import CrawlSpider from scrapy.selector import Selector from ..items import Job51Item from scrapy.http import Request import re from copy import deepcopy class Job51(CrawlSpider): name = 'job51'#與建立的py檔名相同 url = 'https://search.51job.com/list/000000,000000,0000,00,9,99,%25E4%25BA%25BA%25E5%25B7%25A5%25E6%2599%25BA%25E8%2583%25BD,2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare=' start_urls = [url] #可以不用去設定settings檔案,直接指定管道檔案 # custom_settings = { # 'ITEM_PIPELINES' : { # # 'job51.pipelines.Job51Pipeline': 300, # 'job51.pipelines.saveToJson': 310 # #'job51.pipelines.saveToMongoDB': 320 # } # } # 定義一個計數變數 times = 0 def parse(self, response): self.times+=1 #response是下載器下載的網頁內容 selector = Selector(response)#建立selector物件 item=Job51Item() parent = selector.xpath('//div[@id="resultList"]//div[@class="el"]') #print(parent) for each in parent: #獲取職位資訊 jobname = each.xpath('./p/span/a/@title').extract() jobsrc = each.xpath('./p/span/a/@href').extract()[0] companyname = each.xpath('./span[1]/a/text()').extract() address = each.xpath('./span[2]/text()').extract() money = each.xpath('./span[3]/text()').extract() ptime = each.xpath('./span[4]/text()').extract() #print(jobname,companyname,address,money,ptime) if money: money=money[0] else: money='面談' item['jobname']=jobname[0] item['companyname']=companyname[0] item['address']=address[0] item['money']=money item['ptime']=ptime[0] #因為每一條都在迴圈內 yield Request(jobsrc,meta={'front_item':deepcopy(item)},callback=self.parse_detail,dont_filter=True) #實現多頁爬取 #尋找下一頁的連結 next = selector.xpath('//div[@class="dw_page"]//ul//li[@class="bk"][2]/a/@href')[0].extract() print("下一頁:",next) #提交請求 if self.times<4: yield Request(next,callback=self.parse) #爬取詳情頁的函式 def parse_detail(self,response): item = response.meta['front_item'] selector = Selector(response) #提取資訊 div = selector.xpath('//div[@class="bmsg job_msg inbox"]') if div: div=div[0] else: return #提取所有文字 #txt = div.xpath('./p/font/font/text()').extract() txt = div.xpath('string(.)').extract()[0] #print(txt) #使用正則去除空格 reg = re.compile('\S*',re.S) #提取所有非空白符 result = re.findall(reg,txt) datalist = [] for i in result: if i : datalist.append(i) #print(datalist) #給item item['detail']=str(datalist) yield item
5.開啟items的py檔案,將爬取的資訊提交 程式碼如下:
import scrapy from scrapy import Item,Field class Job51Item(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() jobname = Field() companyname = Field() address = Field() money = Field() ptime = Field() detail =Field()
6.進入settings檔案開啟下載器中間鍵開關,程式如下: 根據需要開啟,就會進入中介軟體執行程式碼
7.開啟pipelines檔案,寫入儲存檔案的程式碼 程式碼如下:(這裡提供三種儲存方式,根據需要在settings中開啟)
import json
class Job51Pipeline(object):
def __init__(self):
pass
def process_item(self, item, spider):
return item
def close_spider(self,spider):
pass
#1.儲存為json檔案
class saveToJson(object):
def __init__(self):
self.file = open('job51.json','w',encoding="utf-8")
def process_item(self, item, spider):
#把每一個item轉化為json
each = json.dumps(dict(item),ensure_ascii=False)
self.file.write(each+'\n')
return item
def close_spider(self,spider):
self.file.close()
from pymongo import MongoClient
#2.儲存為MongoDB
class saveToMongoDB(object):
# 1.連線本地資料庫服務
def __init__(self):
self.connection = MongoClient('localhost')
# 2.連線本地資料庫 沒有會建立
self.db = self.connection.job
# 3.建立集合
self.job = self.db.job51
def process_item(self, item, spider):
self.job.insert_one(dict(item))
def close_spider(self, spider):
pass
from openpyxl import Workbook
#3.存入excel
class saveToExcel(object):
def __init__(self):
self.wb = Workbook()
self.ws =self.wb.active
def process_item(self,item,spider):
self.ws.append(list(dict(item).values()))
def close_spider(self,spider):
self.wb.save('崗位詳細資訊.xlsx')
8.進入中介軟體,設定頭部或代理ip,有的網站必須用到瀏覽器頭部和ip進行爬取才更安全。 程式碼如下:
# -*- coding: utf-8 -*-
# Define here the models for your spider middleware
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/spider-middleware.html
import random
from scrapy import signals
#爬蟲中間鍵
class Job51SpiderMiddleware(object):
# Not all methods need to be defined. If a method is not defined,
# scrapy acts as if the spider middleware does not modify the
# passed objects.
@classmethod
def from_crawler(cls, crawler):
# This method is used by Scrapy to create your spiders.
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
return s
def process_spider_input(self, response, spider):
# Called for each response that goes through the spider
# middleware and into the spider.
# Should return None or raise an exception.
return None
def process_spider_output(self, response, result, spider):
# Called with the results returned from the Spider, after
# it has processed the response.
# Must return an iterable of Request, dict or Item objects.
for i in result:
yield i
def process_spider_exception(self, response, exception, spider):
# Called when a spider or process_spider_input() method
# (from other spider middleware) raises an exception.
# Should return either None or an iterable of Response, dict
# or Item objects.
pass
def process_start_requests(self, start_requests, spider):
# Called with the start requests of the spider, and works
# similarly to the process_spider_output() method, except
# that it doesn’t have a response associated.
# Must return only requests (not items).
for r in start_requests:
yield r
def spider_opened(self, spider):
spider.logger.info('Spider opened: %s' % spider.name)
user_agent = [
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
"Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
"Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
"Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
"MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
"Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10",
"Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
"Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+",
"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
"Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/20.0.019; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)",
"UCWEB7.0.2.37/28/999",
"NOKIA5700/ UCWEB7.0.2.37/28/999",
"Openwave/ UCWEB7.0.2.37/28/999",
"Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999",
# iPhone 6:
"Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25",
]
#下載中間鍵
class Job51DownloaderMiddleware(object):
# Not all methods need to be defined. If a method is not defined,
# scrapy acts as if the downloader middleware does not modify the
# passed objects.
@classmethod
def from_crawler(cls, crawler):
# This method is used by Scrapy to create your spiders.
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
return s
def process_request(self, request, spider):
# Called for each request that goes through the downloader
# middleware.
# Must either:
# - return None: continue processing this request
# - or return a Response object
# - or return a Request object
# - or raise IgnoreRequest: process_exception() methods of
# installed downloader middleware will be called
#設定瀏覽器頭部
request.headers['user_agent']=random.choice(user_agent)
print(22222222222222)
# #設定代理
# request.meta['proxy'] = '114.247.89.49:8000'
return None
def process_response(self, request, response, spider):
# Called with the response returned from the downloader.
# Must either;
# - return a Response object
# - return a Request object
# - or raise IgnoreRequest
return response
def process_exception(self, request, exception, spider):
# Called when a download handler or a process_request()
# (from other downloader middleware) raises an exception.
# Must either:
# - return None: continue processing this exception
# - return a Response object: stops process_exception() chain
# - return a Request object: stops process_exception() chain
pass
def spider_opened(self, spider):
spider.logger.info('Spider opened: %s' % spider.name)
9.最後就是執行整個框架的關鍵,這裡建議穿件一個執行的py檔案,方便快捷,建立main.py檔案,寫入如下程式碼:
from scrapy import cmdline
cmdline.execute('scrapy crawl job51'.split())
每次執行main檔案就會執行整個程式