zoukankan      html  css  js  c++  java
  • python网络爬虫(14)使用Scrapy搭建爬虫框架

    目的意义

    爬虫框架也许能简化工作量,提高效率等。scrapy是一款方便好用,拓展方便的框架。

    本文将使用scrapy框架,示例爬取自己博客中的文章内容。

    说明

    学习和模仿来源:https://book.douban.com/subject/27061630/。

    创建scrapy工程

    首先当然要确定好,有没有完成安装scrapy。在windows下,使用pip install scrapy,慢慢等所有依赖和scrapy安装完毕即可。然后输入scrapy到cmd中测试。

    建立工程使用scrapy startproject myTestProject,会在工程下生成文件。

    一些介绍说明

    在生成的文件中,

    创建爬虫模块-下载

    在路径./myTestProject/spiders下,放置用户自定义爬虫模块,并定义好name,start_urls,parse()。

    如在spiders目录下建立文件CnblogSpider.py,并填入以下:

    import scrapy
    class CnblogsSpider(scrapy.Spider):
        name="cnblogs"
        start_urls=["https://www.cnblogs.com/bai2018/default.html?page=1"]
        def parse(self,response):
            pass
    

     在cmd中,切换到./myTestProject/myTestProject下,再执行scrapy crawl cnblogs(name)测试,观察是否报错,响应代码是否为200。其中的parse中参数response用于解析数据,读取数据等。

    强化爬虫模块-解析

    在CnblogsSpider类中的parse方法下,添加解析功能。通过xpath、css、extract、re等方法,完成解析。

    调取元素审查分析以后添加,成为以下代码:

    import scrapy
    class CnblogsSpider(scrapy.Spider):
        name="cnblogs"
        start_urls=["https://www.cnblogs.com/bai2018/"]
        def parse(self,response):
            papers=response.xpath(".//*[@class='day']")
            for paper in papers:
                url=paper.xpath(".//*[@class='postTitle']/a/@href").extract()
                title=paper.xpath(".//*[@class='postTitle']/a/text()").extract()
                time=paper.xpath(".//*[@class='dayTitle']/a/text()").extract()
                content=paper.xpath(".//*[@class='postCon']/div/text()").extract()
                print(url,title,time,content)
            pass
    

     找到页面中,class为day的部分,然后再找到其中各个部分,提取出来,最后通过print方案输出用于测试。

    在正确的目录下,使用cmd运行scrapy crawl cnblogs,完成测试,并观察显示信息中的print内容是否符合要求。

    强化爬虫模块-包装数据

    包装数据的目的是存储数据。scrapy使用Item类来满足这样的需求。

    框架中的items.py用于定义存储数据的Item类。

    在items.py中修改MytestprojectItem类,成为以下代码:

    import scrapy
    class MytestprojectItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        url=scrapy.Field()
        time=scrapy.Field()
        title=scrapy.Field()
        content=scrapy.Field()
        pass
    

     然后修改CnblogsSpider.py,成为以下内容:

    import scrapy
    from myTestProject.items import MytestprojectItem
    class CnblogsSpider(scrapy.Spider):
        name="cnblogs"
        start_urls=["https://www.cnblogs.com/bai2018/"]
        def parse(self,response):
            papers=response.xpath(".//*[@class='day']")
            for paper in papers:
                url=paper.xpath(".//*[@class='postTitle']/a/@href").extract()
                title=paper.xpath(".//*[@class='postTitle']/a/text()").extract()
                time=paper.xpath(".//*[@class='dayTitle']/a/text()").extract()
                content=paper.xpath(".//*[@class='postCon']/div/text()").extract()
                
                item=MytestprojectItem(url=url,title=title,time=time,content=content)
                yield item
            pass
    

     将提取出的内容封装成Item对象,使用关键字yield提交。

    强化爬虫模块-翻页

    有时候就是需要翻页,以获取更多数据,然后解析。

    修改CnblogsSpider.py,成为以下内容:

    import scrapy
    from scrapy import Selector
    from myTestProject.items import MytestprojectItem
    class CnblogsSpider(scrapy.Spider):
        name="cnblogs"
        allowd_domains=["cnblogs.com"]
        start_urls=["https://www.cnblogs.com/bai2018/"]
        def parse(self,response):
            papers=response.xpath(".//*[@class='day']")
            for paper in papers:
                url=paper.xpath(".//*[@class='postTitle']/a/@href").extract()
                title=paper.xpath(".//*[@class='postTitle']/a/text()").extract()
                time=paper.xpath(".//*[@class='dayTitle']/a/text()").extract()
                content=paper.xpath(".//*[@class='postCon']/div/text()").extract()
                
                item=MytestprojectItem(url=url,title=title,time=time,content=content)
                yield item
            next_page=Selector(response).re(u'<a href="(S*)">下一页</a>')
            if next_page:
                yield scrapy.Request(url=next_page[0],callback=self.parse)
            pass
    

    在scrapy的选择器方面,使用xpath和css,可以直接将CnblogsSpider下的parse方法中的response参数使用,如response.xpath或response.css。

    而更通用的方式是:使用Selector(response).xxx。针对re则为Selector(response).re。

    关于yield的说明:https://blog.csdn.net/mieleizhi0522/article/details/82142856

    强化爬虫模块-存储

    当Item在Spider中被收集时候,会传递到Item Pipeline。

    修改pipelines.py成为以下内容:

    import json
    from scrapy.exceptions import DropItem
    class MytestprojectPipeline(object):
        def __init__(self):
            self.file=open('papers.json','wb')
        def process_item(self, item, spider):
            if item['title']:
                line=json.dumps(dict(item))+"
    "
                self.file.write(line.encode())
                return item
            else:
                raise DropItem("Missing title in %s"%item)
    

     重新实现process_item方法,收集item和该item对应的spider。然后创建papers.json,转化item为字典,存储到json表中。

    另外,根据提示打开pipelines.py的开关。在settings.py中,使能ITEM_PIPELINES的开关如下:

    然后在cmd中执行scrapy crawl cnblogs即可

     另外,还可以使用scrapy crawl cnblogs -o papers.csv进行存储为csv文件。

    需要更改编码,将csv文件以记事本方式重新打开,更正编码后重新保存,查看即可。

    强化爬虫模块-图像下载保存

    设定setting.py

    ITEM_PIPELINES = {
        'myTestProject.pipelines.MytestprojectPipeline':300,
        'scrapy.pipelines.images.ImagesPipeline':1
    }
    IAMGES_STORE='.//cnblogs'
    IMAGES_URLS_FIELD = 'cimage_urls'
    IMAGES_RESULT_FIELD = 'cimages'
    IMAGES_EXPIRES = 30
    IMAGES_THUMBS = {
        'small': (50, 50),
        'big': (270, 270)
    }
    

     修改items.py为:

    import scrapy
    class MytestprojectItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        url=scrapy.Field()
        time=scrapy.Field()
        title=scrapy.Field()
        content=scrapy.Field()
    
        cimage_urls=scrapy.Field()
        cimages=scrapy.Field()
        pass
    

     修改CnblogsSpider.py为:

    import scrapy
    from scrapy import Selector
    from myTestProject.items import MytestprojectItem
    class CnblogsSpider(scrapy.Spider):
        name="cnblogs"
        allowd_domains=["cnblogs.com"]
        start_urls=["https://www.cnblogs.com/bai2018/"]
        def parse(self,response):
            papers=response.xpath(".//*[@class='day']")
            for paper in papers:
                url=paper.xpath(".//*[@class='postTitle']/a/@href").extract()[0]
                title=paper.xpath(".//*[@class='postTitle']/a/text()").extract()
                time=paper.xpath(".//*[@class='dayTitle']/a/text()").extract()
                content=paper.xpath(".//*[@class='postCon']/div/text()").extract()
                
                item=MytestprojectItem(url=url,title=title,time=time,content=content)
                request=scrapy.Request(url=url, callback=self.parse_body)
                request.meta['item']=item
    
                yield request
            next_page=Selector(response).re(u'<a href="(S*)">下一页</a>')
            if next_page:
                yield scrapy.Request(url=next_page[0],callback=self.parse)
            pass
        
        def parse_body(self, response):
            item = response.meta['item']
            body = response.xpath(".//*[@class='postBody']")
            item['cimage_urls'] = body.xpath('.//img//@src').extract()
            yield item
    

    总之,修改以上三个位置。在有时候配置正确的时候却出现图像等下载失败,则可能是由于setting.py的原因,需要重新修改。

    启动爬虫

    建立main函数,传递初始化信息,导入指定类。如:

    from scrapy.crawler import CrawlerProcess
    from scrapy.utils.project import get_project_settings
    
    from myTestProject.spiders.CnblogSpider import CnblogsSpider
    
    if __name__=='__main__':
        process = CrawlerProcess(get_project_settings())
        process.crawl('cnblogs')
        process.start()
    

    修正

    import scrapy
    from scrapy import Selector
    from cnblogSpider.items import CnblogspiderItem
    class CnblogsSpider(scrapy.Spider):
        name="cnblogs"
        allowd_domains=["cnblogs.com"]
        start_urls=["https://www.cnblogs.com/bai2018/"]
        def parse(self,response):
            papers=response.xpath(".//*[@class='day']")
            for paper in papers:
                urls=paper.xpath(".//*[@class='postTitle']/a/@href").extract()
                titles=paper.xpath(".//*[@class='postTitle']/a/text()").extract()
                times=paper.xpath(".//*[@class='dayTitle']/a/text()").extract()
                contents=paper.xpath(".//*[@class='postCon']/div/text()").extract()
                for i in range(len(urls)):
                    url=urls[i]
                    title=titles[i]
                    time=times[0]
                    content=contents[i]
                    item=CnblogspiderItem(url=url,title=title,time=time,content=content)
                    request = scrapy.Request(url=url, callback=self.parse_body)
                    request.meta['item'] = item
                    yield request
            next_page=Selector(response).re(u'<a href="(S*)">下一页</a>')
            if next_page:
                yield scrapy.Request(url=next_page[0],callback=self.parse)
            pass
    
        def parse_body(self, response):
            item = response.meta['item']
            body = response.xpath(".//*[@class='postBody']")
            item['cimage_urls'] = body.xpath('.//img//@src').extract()
            yield item
    

    我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=813cva9t28s6

  • 相关阅读:
    centos、mac的grafana安装和简单使用
    通过k8s(Kubernetes)搭建jmeter的压测环境master-slave架构,实现弹性伸缩
    burpsuite破解版
    jvm调优
    火狐firefox、谷歌chrome等浏览器扩展、插件介绍
    关于Chrome谷歌浏览器开发者工具网络Network中返回无数据的问题
    微博登录过程分析
    SQL SERVER大话存储结构(4)_复合索引与包含索引
    千万级别数据表,单列索引和多列索引性能对比
    Showplan 逻辑运算符和物理运算符参考
  • 原文地址:https://www.cnblogs.com/bai2018/p/11255185.html
Copyright © 2011-2022 走看看