专栏首页嘘、小点声python网络爬虫(14)使用Scrapy搭建爬虫框架

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))+"\n"
            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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python网络爬虫(2)回顾Python编程

    把内存中的数据变为可保存和共享,实现状态保存。cPickle使用C语言编写,效率高,优先使用。如果不存在则使用pickle。pickle使用dump和dumps...

    嘘、小点声
  • python网络爬虫(3)python爬虫遇到的各种问题(python版本、进程等)

    Python3中,import cookielib改成 import http.cookiejar

    嘘、小点声
  • java学习与应用(3.3)--异常、多线程、lambda简

    异常是一个类,顶层父类为Throwable,分Error(错误,必须修正代码)和Exception(编译期异常)。Exception下有RunTimeExcep...

    嘘、小点声
  • 【python爬虫】scrapy框架笔记(一):创建工程,使用scrapy shell,xpath

    scrapy是个好东西,它的官方文档写的很详细,很适合入门。链接:http://scrapy-chs.readthedocs.io/zh_CN/1.0/inde...

    后端技术漫谈
  • 3.2 栈的应用举例

    1、十进制数N和其他d进制数的转换是计算机实现计算的基本问题,其解决方法很多,其中一个简单算法基于下列原理:

    闫小林
  • Windows Developer Day - Windows AI Platform

    本次 Windows Developer Day,最值得期待的莫过于 Windows AI Platform 了,可以说是千呼万唤始出来。观看直播的开发者们,留...

    Shao Meng
  • 2021年,哪些黑科技将进入我们的生活?

    据MIT Technology Review报道,如果水晶球的预测是正确的,2021年将是有史以来最好的科技年份。届时,你可以坐在无人驾驶汽车里吃着实验室培育出...

    机器人网
  • VXLAN篇之Multi-Pod

    之前的《VXLAN篇之进阶》说到了multi-pod,multi-fabric,multi-site。这次,再把multi-pod给填上!

    SDNLAB
  • WCF系列教程之WCF服务宿主与WCF服务部署

    本文参考自http://www.cnblogs.com/wangweimutou/p/4377062.html,纯属读书笔记,加深记忆。 一、简介 任何一个程序...

    郑小超.
  • 对标苹果,中国CV独角兽亮出3D+AI秘密武器

    【新智元导读】The Inquirer网站称,苹果iOS 12系统将支持横向Face ID解锁,而2018年秋季新品发布会发布的三款iPhone手机,也都将支持...

    新智元

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动