欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

150行代码写爬虫(一)

程序员文章站 2022-06-17 09:38:38
...

目的:爬取某视频网站的所有视频;

工具:scrapy、MySQL、python 2.7;

项目地址:https://gitee.com/dushen666/spider.git

scrapy是一个python的爬虫框架,有兴趣的同学可以了解一下,本篇我将介绍如何用scrapy从零开始编写一个爬虫;

步骤↓

  1. 安装python 2.7,并配置好环境变量 ,此处不多说。
  2. 安装scrapy:
    pip install Scrapy
     若没有pip请自行安装
  3. 构建一个scrapy项目:进入想要保存项目的路径,执行以下代码:
    scrapy startproject spider
     可以看到当前目录下已经生成了该项目,将项目导入pycharm,项目结构如下:
    150行代码写爬虫(一) 
            
    
    博客分类: python 爬虫python scrapypythonspiderCrawlSpider
  4. 在spiders路径下建立我们的爬虫: 
    150行代码写爬虫(一) 
            
    
    博客分类: python 爬虫python scrapypythonspiderCrawlSpider

    模块中的内容稍后再介绍!

  5. 建立items,用于保存爬取来的信息,修改items.py:
    import scrapy
    
    class H6080Item(scrapy.Item):
        name = scrapy.Field()
        url = scrapy.Field()
        num = scrapy.Field()
    
    
    class H6080MovieInfo(scrapy.Item):
        name = scrapy.Field()
        director = scrapy.Field()
        actor = scrapy.Field()
        types = scrapy.Field()
        area = scrapy.Field()
        publishtime = scrapy.Field()
        countnumber = scrapy.Field()
        introduce = scrapy.Field()
        picurl = scrapy.Field()
     说明:用过Django的同学可以看出,item与Django的model有点类似,但是item并没有区分那么多的数据类型,使用起来很方便。此处H6080Item用于保存视频名、视频url和该视频是哪一集,H6080MovieInfo用于保存视频名、主演、导演、海报url等信息。(因为我要爬取www.h6080.com上的视频,所以我将items命名为H6080Item和H6080MovieInfo)
  6. 之后就是编写spider的内容了,在此之前我们先分析一下要爬取的页面:
     打开要爬取的主页www.h6080.com,我们可以分析出,该网站主要有四个页面:主页、分类展示页、视频详情页和播放页。他们的url形式如下:
    主页 www.h6080.com  
    分类展示页 www.h6080.com/type/2/3.html 2为类别id,3为页码数
    视频详情页 www.h6080.com/show/36088.html 36088为视频id
    播放页 www.h6080.com/play/36088/1/5.html 36088为视频id,5为集数

    可以看出我们要的H6080Item中的信息均在播放页中,H6080MovieInfo中的信息均在视频详情页中。接下来我们分析这两个页面的HTML源码:

    视频详情页中,所要的主演、导演等信息均在这个<table>中:

    <table class="table table-striped table-condensed table-bordered" style="margin-bottom:10px;font-size:12px;">
    <tbody>
    <tr>
        <td class="span2"><span class="info-label">导演</span></td>
        <td>金晔</td>
    </tr>
    <tr>
        <td class="span2"><span class="info-label">主演</span></td>
        <td id="casts" style="position:relative;">杨子姗 / 郑恺 / 张国立 / 江珊 / 田雷 / 钟楚曦 / 逯子 / 周宸佳 / 王森 / 高晓菲 / 刘立<a class="casts-swith"></a></td>
    </tr>
    <tr>
        <td class="span2"><span class="info-label">类型</span></td>
        <td>剧情 / 爱情</td>
    </tr>
    <tr>
        <td class="span2"><span class="info-label">制片国家</span></td>
        <td>*</td>
    </tr>
    <tr>
        <td class="span2"><span class="info-label">更新状态</span></td>
        <td>更新至10集 / 共42集</td>
    </tr>
    <tr>
        <td class="span2"><span class="info-label">上映日期</span></td>
        <td>2018-03-26(*)</td>
    </tr>
    <tr>
    <td class="span2"><span class="info-label">评分</span></td>
    <td>豆瓣:<a rel="nofollow" class="score" target="_blank" href="/">3.0 <i class="glyphicon glyphicon-new-window"></i></a></td>
    </tr>
    </tbody>
    </table>
    

     视频名和海报图片url分别在<h1 class="movie-title">和<img class="img-thumbnail">中:

        <div class="col-md-12">
            <h1 class="movie-title">好久不见2018 <span class="movie-year">(2018)</span></h1>
        </div>
        
        <div class="col-md-9">
            <div class="row">
                <div class="col-md-4" style="padding-right:5px;">
                <a href="/show/41134.html" style="display:block;position:relative;">
                <img class="img-thumbnail" alt="好久不见2018" width="100%" src="http://wx2.sinaimg.cn/mw690/80df6fe6gy1fpqpi212ylj20u019zdlv.jpg">
                    <button class="hdtag">更新至10集 / 共42集</button>
    			</a>
    			<div class="online-button">
                    <a target="_blank" class="btn btn-success btn-block" href="/play/41134.html">立即播放</a>
                </div>
                <div class="col-md-6 left-bt" data-toggle="modal" data-target="#addresource">
                    <i class="glyphicon glyphicon-pencil"></i> 发布
                </div>
                <div class="col-md-6 icon-heart left-bt" id="add_fav" onclick="add_fav(1)">
                    <i class="glyphicon glyphicon-heart"></i> 喜欢
                </div>
    
     

     

     播放页中,视频url在<iframe>的src中,视频名和集数在<h3 class="movie-title">中:
        <div class="container-fluid" style="padding-top:15px;background:#FFF;position:relative">
            <h3 class="movie-title">视频名称:好久不见2018 - 第03集</h3>
          <div class="player" id="player">
    <iframe border="0" frameborder="0" height="460" marginheight="0" marginwidth="0" scrolling="no" src="http://api.tianxianle.com/jx/dapi.php?id=qKt1naKhqaajnnBomZNmbWFi" width="100%" allowfullscreen="true" allowtransparency="true"></iframe></div>
    
     
  7. 通过scrapy的命令行工具和选择器(Selectors)调试提取所需信息的语句。先提取详情页的信息,执行以下语句进入命令行工具: 

    scrapy shell "http://www.h6080.com/show/40928.html"
     
    150行代码写爬虫(一) 
            
    
    博客分类: python 爬虫python scrapypythonspiderCrawlSpider
     先提取视频名:视频名在<h1 class="movie-title">中,在命令行工具中输入以下代码:
    In [1]: response.xpath('//h1[@class="movie-title"]/text()').extract()[0]
    Out[1]: u'\u9006\u6c34\u5bd2 '
     说明://h1表示取该responsebody的所有<h1>,[@class="movie-title"]表示筛选所有class为movie-title的标签,/text()表示取标签中的内容,extract()的作用是将结果转为list并返回,[0]表示取list[0]。此处只举这一个例子,其他信息的提取方法不多说,若要详细了解selector的使用方法可以查看官方文档。

     

  8. 编辑spider的内容:
    # -*- coding: utf-8 -*-
    """
        Created by 杜神 at 2018/3/21
    """
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    from spider.items import H6080Item, H6080MovieInfo
    from scrapy.contrib.spiders import CrawlSpider, Rule
    from scrapy.contrib.linkextractors import LinkExtractor
    import logging
    import re
    
    class SpiderNo1(CrawlSpider):
        name = 'h6080spider'
        allowed_domains = ['h6080.com']
        start_urls = [
            'http://www.h6080.com',
        ]
        logging.getLogger("requests").setLevel(logging.WARNING
                                               )  # 将requests的日志级别设成WARNING
        logging.basicConfig(
            level=logging.DEBUG,
            format=
            '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
            datefmt='%a, %d %b %Y %H:%M:%S',
            filename='h6080spider.log',
            filemode='w')
    
        rules = (
            # follow所有分类链接/下一页链接/详情页链接
            Rule(LinkExtractor(allow=('\/type\/\d+\.html', '\/type\/\d+\/\d+\.html')), follow=True),
            Rule(LinkExtractor(allow=('play\/\d+\/\d+\/\d+\.html', )), callback='parse_item'),
            Rule(LinkExtractor(allow=('\/show\/\d+\.html', )), callback='parse_movie_info', follow=True),
        )
    
        def parse_item(self, response):
            item = H6080Item()
            item['name'] = response.xpath('//h3[@class="movie-title"]/text()').extract()[0]
            item['url'] = response.xpath('//div[@class="player"]/iframe/@src').extract()[0]
            item['num'] = re.findall('\/\d+\.html', response.url)[0].split('.')[0][1:]
            self.log('find a url! %s' % response.url)
            yield item
    
        def parse_movie_info(self, response):
            item = H6080MovieInfo()
            rows = response.xpath('//td/text()').extract()
            item['director'] = rows[0]
            item['actor'] = rows[1]
            item['types'] = rows[2]
            item['area'] = rows[3]
            try:
                item['publishtime'] = rows[5]
            except Exception:
                item['publishtime'] = '1999-01-01'
            item['name'] = response.xpath('//h1[@class="movie-title"]/text()').extract()[0]
            item['introduce'] = response.xpath('//p[@class="summary"]/text()').extract()[0]
            item['picurl'] = response.xpath('//img[@class="img-thumbnail"]/@src').extract()[0]
            if len(re.findall('\d+', rows[4])) > 0:
                item['countnumber'] = re.findall('\d+', rows[4])[0]
            else:
                item['countnumber'] = 0
            self.log('find a movie! %s' % item['name'])
            yield item
    
     说明:此处继承scrapy的CrawlSpider类,
    name 给该spider取个唯一的名字,此处取名h6080spider
    allowed_domains 允许爬虫访问的域名
    start_urls 爬虫起始url
    logging 日志,不多说
    rules

    Rule(LinkExtractor(allow=('play\/\d+\/\d+\/\d+\.html', )), callback='parse_item')

    若url匹配正则表达式,则由callback指定的方法处理,若未指定,则不处理。follow=True表示是否跟进,默认为True

    parse_item

    用于处理播放页

    parse_movie_info 用于处理视频详情页
  9. 执行爬虫,进入项目根路径,执行以下命令:
    scrapy crawl h6080spider -o result.json
     可以看到路径下生成了result.json,该文件以json的形式存储了H6080MovieInfo和H6080Item

 到此一个爬虫就已经可以工作了,但是这还远远不行,我们要把爬取的信息存储到数据库中,并且要实现去重功能,否则会产生大量重复数据,关于去重和数据库存储我会在下一篇文章中介绍。

 

最后再次附上项目地址:https://gitee.com/dushen666/spider.git