#进行分布式爬取,首先在setting中添加scrapy-redis的相关配置
#########***************进行分布式爬取,首先在配置文件中添加scrapy-redis的相关配置
BOT_NAME = 'Movies_example'
SPIDER_MODULES = ['Movies_example.spiders']
NEWSPIDER_MODULE = 'Movies_example.spiders'
FEED_EXPORT_FIELDS=['movietype','moviename','moviepicture','movieinformation','mvurl']
####指定爬虫所使用的redis数据库
REDIS_HOST='localhost'
REDIS_PORT='6379'
REDIS_PARAMS = {
'password': '**',
}
# ####使用scrapy-redis的调度器替代scrapy原版调度器
SCHEDULER="scrapy_redis.scheduler.Scheduler"
# ####使用scrapy-redis的RFPDupeFilter作为去重过滤器
DUPEFILTER_CLASS="scrapy_redis.dupefilter.RFPDupeFilter"
###将爬取到的数据汇总到sql server数据库中
ITEM_PIPELINES={
'Movies_example.pipelines.SqlTablePipeline':301,}
####爬虫停止后,保留/清理redis中的请求队列及去重集合
#True:保留 ,False:清理,默认为True
SCHEDULER_PERSIST=False
#爬取主程序
# -*- coding: utf-8 -*-
from scrapy import Request
from ..items import MoviesExampleItem
from scrapy_redis.spiders import RedisSpider
import re
class MoviesSpider(RedisSpider):
name = 'movies'
allowed_domains = ['www.66ys.tv']
redis_key = "Movies"
def parse(self, response):
#获取每个类型的url
movietypes=['喜剧片','动作片','爱情片','科幻片','恐怖片','战争片','纪录片','剧情片','3D电影',
'国产剧','港台剧','日韩剧','欧美剧','国配电影','综艺']
type_urls=response.css('div.menutv').xpath('./ul/li/a/@href').extract()
for i in range(1,len(type_urls)):
#返回的是当前类型的第一页
yield Request(type_urls[i],dont_filter=True,callback=self.now_movie_type,meta={'类型':movietypes[i-1],
'首页链接':type_urls[i]})
#获得当前类型电影的总页数,并循环访问每一页的电影
def now_movie_type(self,response):
#链接结尾是html的类型
types=['喜剧片','动作片','爱情片','科幻片','恐怖片','战争片','纪录片']
#当前类型
nowtype=response.meta['类型']
base_url=response.meta['首页链接']
if nowtype in types:
# 获取当前类别总页数
page_urls = response.css('div.pagebox').xpath('./a/@href')
pageall = int(page_urls[len(page_urls) - 1].re('.*?/index_(\d+).html')[0])
for page in range(1, pageall + 1):
if page == 1:
yield Request(base_url, dont_filter=True, callback=self.list_parse, meta={'类型': nowtype})
else:
pageurl = base_url + '/index_' + str(page) + '.html'
yield Request(pageurl, dont_filter=True, callback=self.list_parse, meta={'类型': nowtype})
else:
# 获取当前类别总页数
page_urls = response.css('div.pagebox').xpath('./a/@href')
pageall = int(page_urls[len(page_urls) - 1].re('.*?/index_(\d+).htm')[0])
for page in range(1, pageall + 1):
if page == 1:
yield Request(base_url, dont_filter=True, callback=self.list_parse, meta={'类型': nowtype})
else:
pageurl = base_url + '/index_' + str(page) + '.htm'
yield Request(pageurl, dont_filter=True, callback=self.list_parse, meta={'类型': nowtype})
#获得该页下的电影列表,并获取列表下电影的链接,进入该电影链接
def list_parse(self,response):
nowtype = response.meta['类型']
pageurls = response.css('div.listimg').xpath('./a/@href').extract()
for url in pageurls:
yield Request(url, dont_filter=True,callback=self.movie_parse, meta={'类型': nowtype})
#获得单独一个电影的信息
def movie_parse(self,response):
#电影名
name=response.css('div.contentinfo').xpath('./h1/text()').extract_first().strip()
#电影海报链接
image=response.css('div#text').xpath('./p/img/@src').extract_first().strip()
#电影简介信息(将多个简介连成一个)
mvdesc = response.xpath('//*[@id="text"]/p/text()') # /p[2]/text()
desc = ""
for p in mvdesc:
desc = desc+p.extract().strip().encode('unicode-escape').decode('string_escape')+' '
desc = desc.replace('\\u3000', ' ')
info=desc.decode("unicode-escape")
#电影下载链接
##判断影片是否有两个table属性
urls = response.xpath('//*[@id="text"]/table').xpath('./tbody/tr/td/a').extract()
mvurls=[]
for item in urls:
url1=re.compile('href="(ftp:\/\/.*?)"').findall(item)
url2=re.compile('href="(thunder:\/\/.*?)"').findall(item)
url3 = re.compile('href="(ed2k:\/\/.*?)"').findall(item)
if url1:
mvurls.append(url1)
if url2:
mvurls.append(url2)
if url3:
mvurls.append(url3)
#存储数据
moviesInfoitem=MoviesExampleItem()
moviesInfoitem['movietype']=response.meta['类型'].decode('utf-8')
moviesInfoitem['moviename']=name
moviesInfoitem['moviepicture']=image
moviesInfoitem['movieinformation']=info
if mvurls:
moviesInfoitem['mvurl']=mvurls[0]
else:
moviesInfoitem['mvurl']=None
yield moviesInfoitem
#保存入数据库
# -*- coding: utf-8 -*-
from openpyxl import Workbook
class MoviesExamplePipeline(object):
def process_item(self, item, spider):
return item
class SqlTablePipeline(object):
import pymssql
server = "**" # 连接服务器地址
user = "**" # 连接帐号
password = "**" # 连接密码
conn = pymssql.connect(server, user, password, "**") # 获取连接
cursor = conn.cursor() # 获取光标
def __init__(self):
# 创建表
self.cursor.execute("""
IF OBJECT_ID('Moviess','U')IS NOT NULL
DROP TABLE Moviess
CREATE TABLE Moviess (
Movietype VARCHAR(max) NOT NULL,
Moviename VARCHAR(max) NOT NULL,
ImageUrl VARCHAR(max),
MovieIntroduce VARCHAR(max),
DownloadUrl VARCHAR(max)
)
""")
def process_item(self, item, spider):
# 插入获得的数据
self.cursor.executemany(
"INSERT INTO Moviess VALUES (%s, %s, %s,%s,%s)",
[(item['movietype'],item['moviename'],item['moviepicture'],item['movieinformation']
,item['mvurl'])])
# 调用 commit() 来保持你数据的提交如果你没有将自动提交设置为true
self.conn.commit()
return item
def close_spider(self, spider):
self.conn.close()
#爬取结果展示
每列分别为:类型、名称、海报链接、简介、下载链接。
进行scrapy_redis分布式爬取的步骤是:
1、首先在cmd中登录本机中的Redis数据库
2、然后运行python程序
3、最后在cmd中输入lpush key(在scrapy项目中输入的redis_key的名字) '***'(起始爬取地址)
输入完起始爬取地址后python程序将执行分布式爬取。