基于scrapy爬取某网站movie下载地址

Scrapy大名鼎鼎,看到某网站mv不错,手动下载太麻烦,于是用scrapy来实现抓取。

基本思路是研究网站的首页、电影的列表页面、及其播放页面,获取页面中格式化的信息,页面到页面的跳转关系,最终获取下载的链接。

Scrapy的架构知识,请看Scrapy架构原理介绍或是官方文档sscrapy架构介绍, 下面逐步来制作。

一、开始建立项目,写程序

scrapy提供命令行工具创建项目,在 CMD 命令行执行以下命令创建项目以及爬虫文件:

# 创建项目
1) scrapy startproject projectname
# 进入项目
2) cd projectname
# 创建爬虫文件,Scrapy 框架已经自动生成一些代码
3)scrapy genspider spidername www.xxx.com

二、修改代码,关键是spider

1)打开爬虫文件 spidername.py ,scrapy默认调用parse方法,这是处理逻辑的入口函数,首先解析首页的链接,获取电影分类的地址,然后跳转到列表页面,注意用yield scrapy.Request(url=url, callback=self.parseListPage )请求下一个页面,callback为返回后的解析方法回调

class MovieSpider(scrapy.Spider):
    name = 'movie'
    allowed_domains = ['xxx.com']
    start_urls = ['https://xxx.com']

    def parse(self, response):
        #result = response.xpath('/html/body/title/text()').extract_first()   /html/body/div/div/div/ul/li/div/div/
        result = response.xpath('//div[@class="item-menu"]/a/@href').extract()    #ul/li/div/div/div[@class="item-menu"]/a
        #print('-' * 60 )
        #print( result )
        #print('-' * 60)
        for url in result:
            url = self.fullUrl( url )
            yield scrapy.Request(url=url, callback=self.parseListPage )

2)解析列表页面,代码如下,核心就是xpath运用,和字符串的处理,最后获取电影播放地址并请求。

这里注意,解析的数据生成item对象,见 items.py文件,方便数据通过pipeline处理或存储。用yield data,pipeline就能接收到此对象并处理。

    def parseListPage(self, response ):
        #解析列表,获得mv信息和url
        result = response.xpath(
            '//div[@id="list_videos_common_videos_list_items"]/div[@class="item"]')
        print('-' * 60)
        print(len( result ))
        print('-' * 60)
        #pageUrl = response.url
        #mvs = []
        for e in result:
            data = Mv05Item()
            #print( e.xpath('./a[0]/@href').extract_first() )
            # data-rt="1:2c8d63ec93028cf593fa06c9ab7db742:0:164936:1:"
            data["id"] = e.xpath('./a/@data-rt').extract_first().split(":")[3]

            data["url"] = e.xpath('./a/@href').extract_first()
            data["channel"] = getChannelFromURL(response.url)
            yield  data
            yield scrapy.Request(url=self.fullUrl( data["url"] ), callback=self.parsePlayPage )

3)解析电影播放页面,获取电影文件的地址。代码不列了

4)验证代码逻辑是否正确,我下载了3个典型页面,写测试程序验证通过。

三、修改配置文件

settings 文件的配置项,非常重要,提供了重要功能的配置参数,及扩展点的配置

#设置爬取深度,超过此值将不继续深度执行
DEPTH_LIMIT=3

# 设置user-agent,应对反爬虫是必须的选项
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1'
#是否遵守robot协议
ROBOTSTXT_OBEY = False

DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
}

# 启用后,当从相同的网站获取数据时,Scrapy将会等待一个随机的值,延迟时间为0.5到1.5之间的一个随机值乘以DOWNLOAD_DELAY
RANDOMIZE_DOWNLOAD_DELAY=True

#对单个网站进行并发请求的最大值,默认为8
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#对单个IP进行并发请求的最大值,如果非0,则忽略CONCURRENT_REQUESTS_PER_DOMAIN设定,使用该IP限制设定。
#CONCURRENT_REQUESTS_PER_IP = 16


关于自动限速(AutoThrottle extension)的几个参数
    AUTOTHROTTLE_ENABLED
    True:启用;False:不启用(默认值);

    AUTOTHROTTLE_START_DELAY
    每一个爬虫的初始download delay,单位是秒,默认值为5.0

    AUTOTHROTTLE_MAX_DELAY
    允许的最大download delay,单位是秒,以防出现latency过高而导致download delay跟着变高的情况。默认值是60.0

    AUTOTHROTTLE_TARGET_CONCURRENCY
    针对每个网站的平均并发请求量,默认值是1.0。这是一个平均值,意味着某一时刻的并发量可能高于也可能低于这个值。

    AUTOTHROTTLE_DEBUG
    调试模式,日志将会打印每次响应消耗的时长latency与当前所设置的当前的Download_delay时长。这样就可以实时观察Download_delay参数的调整过程。True:开启调试;False:关闭调试(默认值)

    CONCURRENT_REQUESTS_PER_DOMAIN
    单个域名并发数

    CONCURRENT_REQUESTS_PER_IP
    单个IP并发数量

    DOWNLOAD_DELAY
    对同一website发起请求的间隔,默认值为0

    RANDOMIZE_DOWNLOAD_DELAY
    True:启动随机请求间隔,为0.5*DOWNLOAD_DELAY 至 1.5*DOWNLOAD_DELAY之间的的随机数;False:不启动;默认是True,但是因为DOWNLOAD_DELAY的默认值为0,所以要想真正启动还需要设置DOWNLOAD_DELAY

四、编写pipline,将数据存入sqlite数据库,pipeline提供了open_spider、process_item、close_spider等方法,具体用法参见pipeline项目管道用法

# 存入sqlite数据库的管道
class Mv05SQLitePipeline(object):
    #开始
    def open_spider(self, spider):
        # 爬虫项目启动,执行连接数据操作
        # 以下常量需要定义在settings配置文件中
        self.db = sqlite3.connect( SQLITE_FILE )
        self.cursor = self.db.cursor()
        if not self.checkExist():
            self.initTable()


    # 向表中插入数据
    def process_item(self, item, spider):

           ins = 'insert into movieinfo (id, name, url, durat, rating, channel) values(?,?,?,?,?,?)'
            L = [
                item['id'], item['name'], item['url'], item['durat'], item['rating'], item['channel']
            ]
            # self.cursor.execute("BEGIN TRANSACTION")
            self.cursor.execute(ins, L)
            self.db.commit()
            return item
       

   # 结束存放数据,在项目最后一步执行
    def close_spider(self, spider):
        # close_spider()函数只在所有数据抓取完毕后执行一次,
        self.cursor.close()
        self.db.close()
        print('执行了close_spider方法,项目已经关闭')

五、运行项目

可以在命令行执行scrapy命令运行   

scrapy crawl spidername

为了省去终端敲命令的环节,可以在项目中自定义一个运行文件 mian.py(注意:该文件与 scrapy.cfg 同目录),并编写如下代码:


    from scrapy import cmdline
    # 注意,cmdline.execute()是为了减少输入命令的操作,该方法的参数必须为列表。
    # 执行爬虫文件来启动项目
    cmdline.execute('scrapy crawl spidername'.split())

六、遇到的问题

1、提示KeyError: 'Spider not found,解决办法是 执行此命令时scrapy crawl spidername,spidername和spider类定义的name值要一致。

class MovieSpider(scrapy.Spider):
    name = 'movie'
    allowed_domains = ['xxx.com']
    start_urls = ['https://xxx.com']

2、pipeline 不执行,原因是setting配置文件中没有配置自定义的pipline,配置如下即可。

#激活pipeline,否则不起作用; 多pipeline从底传递到高值
ITEM_PIPELINES = {
#    'mv05.pipelines.Mv05Pipeline': 100,
    'mv05.pipelines.Mv05SQLitePipeline': 300,
}

3、需要具备xpath的知识,相关知识参见python xpath语法 或者scrapy的xpath 选择器指导

七、源代码

源代码上传github,感兴趣请访问python-space/mv06 at main · jahson88/python-space · GitHub

或者从我的资源下载爬虫程序

整体参考Python Scrapy爬虫框架实战应用 此文章。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值