思路:
1、豆瓣電影TOP250 url=https://movie.douban.com/top250
2、使用crawlspider擷取250個電影詳情頁url
3、使用xpath解析資料:擷取電影标題、導演、演員、簡介、熱門第一評論、評論人數等詳細資訊
4、儲存250部電影海報圖檔
一、準備工作
建立一個scrapy project:
scrapy startproject DBMOVIE
建立spider file
scrapy genspider -t crawl douban douban.com
二、建構架構
(1)items.py / 定義item
import scrapy
class DbmovieItem(scrapy.Item):
Rank = scrapy.Field()
Title =scrapy.Field()
Attr =scrapy.Field()
Actor =scrapy.Field()
Type_ = scrapy.Field()
Rating_num =scrapy.Field()
Time_ =scrapy.Field()
Short =scrapy.Field()
Image_url = scrapy.Field()
Hot_comment = scrapy.Field()
(2) spider.py
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
import time
from DBMOVIE.items import DbmovieItem
class DoubanSpider(CrawlSpider):
name = 'douban'
allowed_domains = ['douban.com']
#豆瓣電影top250共有10頁,将每頁的url都加入start_url清單中
base_urls = 'https://movie.douban.com/top250?start={}&filter='
start_urls =[]
#設定index用來檢視爬取進度,可不要
index = 0
for i in range(10):
url = base_urls.format(i*25)
start_urls.append(url)
#設定crawl爬取規則,擷取每頁中的25個詳情頁url
#CrawlSpider架構擷取url有去重功能
rules = (
Rule(LinkExtractor(allow='subject/'), callback='parse_item', follow=False),
)
def parse_item(self, response):
self.index +=1
#導入item
item = DbmovieItem()
#擷取排名,得到的資料順序是随機的,後續可以使用排名重新排序
item['Rank'] = response.xpath('//*[@id="content"]/div[1]/span[1]/text()').extract_first()[3:]
#電影名稱
item['Title'] = response.xpath('//*[@id="content"]/h1/span[1]/text()').extract_first()
#導演
item['Attr'] = response.xpath('//*[@id="info"]/span[1]/span[2]/a/text()').extract_first()
#演員,演員有多個,在多個同級标簽中,使用join将擷取到的清單中多個導演名字連成一個完整字元串
item['Actor'] = ','.join(response.xpath('//*[@id="info"]/span[@class="actor"]/span[2]/a/text()').extract())
#電影類别
item['Type_'] = ','.join(response.xpath('//*[@id="info"]/span[@property="v:genre"]/text()').extract())
#電影評論人數
item['Rating_num'] = response.xpath('//*[@id="interest_sectl"]//a[@class="rating_people"]/span/text()').extract_first()
#上映時間
item['Time_'] = ','.join(response.xpath('//*[@id="info"]/span[@property="v:initialReleaseDate"]/text()').extract())
#簡介
item['Short'] = (((''.join(response.xpath('//*[@id="link-report"]//span[1]/text()').extract())).replace('\n','')).strip()).replace(' ','')
#圖檔url,後面用來下載下傳圖檔
item['Image_url'] = response.xpath('//*[@id="mainpic"]/a/img/@src').extract_first()
#熱評第一個
item['Hot_comment'] = (response.xpath('//*[@id="hot-comments"]/div[1]/div/p/span/text()').extract_first().strip()).replace('\t','')
print('擷取到第%d個' % self.index)
print(item['Rank'],item['Title'])
yield item
(3) middlewares.py
#在項目下建立了一個user_agent.py檔案儲存了user_agents池
#使用scrapy的UserAgentMiddleware子產品擷取user_agent
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
from DBMOVIE.user_agent import user_agents
import random
class RotateUserAgentMiddleware(UserAgentMiddleware):
def process_request(self, request, spider):
#随機選取一個user_agent,傳入請求頭
user_agent = random.choice(user_agents)
if user_agent:
print('**********user ug:%s***********' % user_agent)
request.headers['User-Agent'] = user_agent
return None
(4)pipelines.py
from scrapy.exporters import CsvItemExporter
import DBMOVIE.settings as setting
import urllib.request
import os
import pymongo
#将擷取的資料儲存到MongoDB資料庫中
class DbmoviePipeline(object):
def open_spider(self,spider):
#連接配接伺服器,使用預設位址端口
self.client = pymongo.MongoClient()
#建立/選擇資料庫
self.mydb = self.client['test']
#建立/選擇表
self.collection = self.mydb['dbmovie']
def process_item(self, item, spider):
#插入資料
self.collection.insert(dict(item))
return item
#重寫一個儲存圖檔的管道
class DbmovieImgPipline(object):
def process_item(self,item,spider):
#設定儲存圖檔的檔案夾位址
dir_path = '%s/%s' % (setting.IMAGES_STORE,spider.name)
#若不存在則建立它
if not os.path.exists(dir_path):
os.makedirs(dir_path)
#擷取圖檔url
img_url = item['Image_url']
#建立圖檔名稱
file_name = item['Rank'] + item['Title'] + '.jpg'
#拼接檔案夾位址和圖檔名稱建立檔案儲存路徑
file_path = '%s/%s' % (dir_path,file_name)
#去重
if os.path.exists(file_path):
print('重複,跳過',+img_url)
#儲存圖檔
with open(file_path,'wb') as f:
print('正在下載下傳圖檔',img_url)
#使用圖檔url發生請求擷取到圖檔,儲存到對應的路徑中
conn = urllib.request.urlopen(img_url)
f.write(conn.read())
f.close()
return item
5)設定setting
一般寫好一部分代碼就開啟相應的設定,以防忘記
BOT_NAME = 'DBMOVIE'
SPIDER_MODULES = ['DBMOVIE.spiders']
NEWSPIDER_MODULE = 'DBMOVIE.spiders'
LOG_FILE = 'douban.log'
LOG_LEVEL = 'WARNING'
#儲存圖檔的檔案位址
IMAGES_STORE = './img'
#不遵守robort協定
ROBOTSTXT_OBEY = False
#下載下傳延遲
DOWNLOAD_DELAY = 3
#打開設定user_agent的下載下傳中間件
DOWNLOADER_MIDDLEWARES = {
'DBMOVIE.middlewares.RotateUserAgentMiddleware': 543,
}
#打開儲存資料和圖檔的管道
ITEM_PIPELINES = {
'DBMOVIE.pipelines.DbmoviePipeline': 300,
'DBMOVIE.pipelines.DbmovieImgPipline':350,
}
三、運作spider
(1)打開MongoDB伺服器,啟動用戶端
sudo mongod
mongo
(2)運作spider
scrapy crawl maitian
四、完成以上幾步即可以檢視資料啦
如果需要可以對MongoDB中的資料CSV可視化處理