zoukankan      html  css  js  c++  java
  • Python日记:基于Scrapy的爬虫实现

    安装 pywin32 和python版本一致 

    地址 https://sourceforge.net/projects/pywin32/files/pywin32/Build%20221/
    安装过程中提示找不到Python2.7
    解决方法:http://blog.csdn.net/pppii/article/details/48679403

    安装Scrapy 使用pip

    1、使用命令行创建爬虫项目
    scrapy startproject myspider # cmd进入指定文件夹后创建一个名为 myspider的爬虫

    2、启动pyCharm
    打开项目 myspider ,在文件夹spiders下创建MySprider.py文件
    添加我的爬虫 class Channel9Spider(scrapy.Spider):
    name 表示爬虫的名称 属于唯一属性
    allowed_domins=[] 爬虫允许的域
    start_urls=[] 爬虫开始的页面
    def parse(self,response): 访问地址后调用的方法
    def details_parse(self,response): 处理详情页面的方法

    MySprider.py遇到的问题:
    1、windows命令提示符中打印爬取的文件名报错
    原因:是命令行字符集和网页字符集不一致
    处理方法:print item["title"].encode("gbk","ignore")
    2、回调方法报错
    原因:PyScrapy默认给回调加了个括号
    处理方法:去掉回调方法后的括号,需要传参使用Request(url=.. , meta={'name':'yancl',....},calback=self.details_parse,dont_filter=True)
    3、提示访问被拒绝
    原因:1、robots 协议问题 2、由于设置了允许爬取的域
    处理方法:1、修改settings.py 设置ROBOTSTXT_OBEY = True
    2、调用Request方法设置dont_filter=True

    打开 items.py
    添加在处理页面后要传递给pipeline的item数据对象
    用到了下载所以添加 file_urls,files,file_paths

    打开 pipeline.py
    1、添加一个继承FilesPipeline文件下载管道的实现方法 MyFilesPipeline
    2、添加一个记录文件方法 JsonWithEncodingPipeline

    打开settings.py
    1、启用我的Item Pipeline组建。我打算下载一个视频就记录一条对应的Json信息
    2、添加视频下载保存文件的路径


    再次启动爬虫 scrapy crawl myspider
    遇到的问题:
    1、下载文件过大
    2、连接超时
    3、文件下载的路径问题,默认添加full的文件夹
    4、文件名问题

    对于问题1、2、3 修改settings
    DOWNLOAD_MAXSIZE = 325674803 #字节
    DOWNLOAD_WARNSIZE = 325674803 #字节
    DOWNLOAD_TIMEOUT = 30 * 60 #单位秒
    FILES_STORE = "F:\mp4files" #直接使用绝对路径
    对于问题3,修改MyFilesPipeline方法 重写file_path方法

    再次启动爬虫运行正常,但是还有2个小问题,1、有一个文件自动添加了文件夹 2、有几个文件没有后缀大小为0KB
    根据日志分析是文件名导致了 文件名中不能有:/ 等特殊字符

    MySpider.py

    import scrapy
    from mydemo.items import MydemoItem
    from scrapy.http import Request
    from scrapy.selector import Selector
    
    download_domain = "https://channel9.msdn.com"
    class Channel9Spider(scrapy.Spider):
        name = "myspider"
        allowed_domains = [".msdn.com"]
        start_urls = [
            "https://channel9.msdn.com/Events/Ignite/Microsoft-Ignite-China-2016?sort=status&direction=desc"
        ]
    
        def parse(self,response):
            sale = Selector(response)
            for a in sale.xpath("//h3"):
                title = a.xpath("a/text()").extract()[0]
                line = a.xpath("a/@href").extract()[0]
                fileurl = download_domain + line
                yield Request(url=fileurl,meta={'title':title},callback=self.details_parse,dont_filter=True)
    
            next_page = sale.xpath("//a[@rel='next']/@href").extract()
            if next_page:
                pagepath =  download_domain+next_page[0]
                yield Request(url=pagepath,callback=self.parse,dont_filter=True)
    
        def details_parse(self,response):
            sale = Selector(response)
            item = MydemoItem()
            item["title"] = response.meta['title']
            fileurl = sale.xpath("//*[@id='format']/option/@value").extract()[0]
            item["file_urls"] = [fileurl]
            yield item
    

    items.py

    class MydemoItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        title = scrapy.Field()
        link = scrapy.Field()
        content = scrapy.Field()
    
        file_urls = scrapy.Field()
        files = scrapy.Field()
        file_paths = scrapy.Field()
        pass
    

    pipelines.py

    # -*- coding: utf-8 -*-
    
    # Define your item pipelines here
    #
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
    import scrapy
    import codecs
    import json
    import time
    from scrapy.pipelines.files import FilesPipeline
    from scrapy.exceptions import DropItem
    
    class MydemoPipeline(object):
        def process_item(self, item, spider):
            return item
    
    class JsonWithEncodingPipeline(object):
        def __init__(self):
            self.file = codecs.open('file.json','w',encoding='utf-8')
    
        def process_item(self,item,spider):
            timeSatamp = time.time()
            timeTuple = time.localtime(timeSatamp)
            curTime = time.strftime("%Y-%m-%d %H:%M:%S",timeTuple)
            line = "["+curTime+"] "+json.dumps(dict(item),ensure_ascii=False)+"
    "
            self.file.write(line)
            return item
    
        def spider_closed(self,spider):
            self.file.close()
    
    
    class MyFilesPipeline(FilesPipeline):
        def get_media_requests(self,item,info):
            for file_url in item['file_urls']:
                yield scrapy.Request(file_url,meta={'title':item['title']})
    
        def item_completed(self, results, item, info):
            file_paths = [x['path'] for ok, x in results if ok]
            if not file_paths:
                raise DropItem("Item contains no Files")
            item["file_paths"] = file_paths
            return item
    
        def file_path(self,request,response=None,info=None):
            title = request.meta['title']
            file_guid = title + '.'+request.url.split('/')[-1].split('.')[-1]
            filename = u'{0}'.format(file_guid)
            return filename
    

    settings.py 

    生成的日志截图如下:

    爬取的文件截图:

      

     



  • 相关阅读:
    ie下常见的css兼容问题
    jQuery Easing 使用方法及其图解
    数组中常用的15个方法
    js按位运算符及其妙用
    图片格式知多少
    Linux top命令的用法详解
    Another app is currently holding the yum lock; waiting for it to exit...
    ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this S tatem
    Gitlab与Jenkins结合构成持续集成(CI)环境
    cobbler无人值守安装
  • 原文地址:https://www.cnblogs.com/dbycl/p/6757910.html
Copyright © 2011-2022 走看看