当前位置: 首页 > news >正文

爬虫之Scrapy框架

安装

pip install scrapy
在命令行输入scrapy,出现提示说明安装成功
在这里插入图片描述

创建项目

scrapy startproject my_scrapy
会生成一个项目名文件夹,包含一些文件
在这里插入图片描述
其中对于开发Scrapy爬虫来说,需要关心的内容如下。
(1)spiders文件夹:存放爬虫文件的文件夹。
(2)items.py:定义需要抓取的数据。
(3)pipelines.py:负责数据抓取以后的处理工作。pipelines.py文件用于对数据做初步的处理,包括但不限于初步清洗数据、存储数据等。
(4)settings.py:爬虫的各种配置信息。

创建爬虫文件

scrapy genspider example baidu.com
example为爬虫文件名 可以随便定义
最后一个参数为要爬取的网址
会在spiders文件夹下生成一个文件example.py
example.py文件初始内容

import scrapy


class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['baidu.com']
    start_urls = ['http://baidu.com/']

    def parse(self, response):
        pass

这里没有输出内容
把pass改为print(response.body.decode())
运行爬虫,可以看到输出结果,注意这里的操作,都是在命令行进行的,不能直接用python运行爬虫文件。
parse 表示请求 start_urls 中的地址,获取响应之后的回调函数,直接通过参数 response 的 .text 属性进行网页源码的输出。

运行爬虫

scrapy crawl example
在这里插入图片描述
要想在python直接运行爬虫,可以新建main文件,放置项目根目录。

from scrapy import cmdline
cmdline.execute("scrapy crawl example".split())

scrapy中使用xpath

需要使用extract()提取内容,如果不提取,XPath获得的结果是保存在一个SelectorList中

import scrapy


class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['baidu.com']
    start_urls = ['http://baidu.com/']

    def parse(self, response):
        # print(response.body.decode())
        title=response.xpath('//title/text()').extract()
        search_button_text=response.xpath('//input[@id="su"]/@value').extract()
        print(title)
        print(search_button_text)

这个SelectorList非常有意思,它本身很像一个列表。可以直接使用下标读取里面的每一个元素,也可以像列表一样使用for循环展开,然后对每一个元素使用.extract()方法。同时,又可以先执行SelectorList的.extract()方法,得到的结果是一个列表,接下来既可以用下标来获取每一个元素,也可以使用for循环展开
当不需要从抓取到的信息中提取文本的时候,就不需要调用extract()方法。
在这里插入图片描述

实例

使用xpath方法,打印出url和文章标题

class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['imspm.com']
    start_urls = ['http://imspm.com/']

    def parse(self, response):
        # item=MyScrapyItem()
        item_list=response.xpath("//div[@class='item-div']")
        for each in item_list:
            url=each.xpath("a/@href").extract()
            title=each.xpath("a/h2[@class='title']/text()").extract()
            print("文章地址:{0},文章标题{1}".format(url,title))

输出结果
在这里插入图片描述
这里需要注意,采用抓大放小的方法,循环each时,元素xpath不能再用相对路径,直接写标签即可。
如下图这种写法,是错误的,会直接根据相对路径得到结果,最后就是输出了10遍想要的结果。
在这里插入图片描述

Item中定义抓取的数据

要想把结果保存起来,需要先定义要抓取的数据
在item.py中写入如下代码,这个类就是要存储的数据的结果。
一个Scrapy工程可以有多个爬虫;再看items.py文件,可以发现,在一个items.py里面可以对不同的爬虫定义不同的抓取内容Item。

import scrapy


class MyScrapyItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title=scrapy.Field()#文章标题
    url=scrapy.Field()#文章地址

修改爬虫文件

    def parse(self, response):
        item=MyScrapyItem()
        item_list=response.xpath("//div[@class='item-div']")
        for each in item_list:
            url=each.xpath("a/@href").extract()
            title=each.xpath("a/h2[@class='title']/text()").extract()
            # print("文章地址:{0},文章作者{1}".format(url,title))
            item['title']=title if title else 'N/A'#对item进行赋值
            item['url']=url if url else 'N/A'
            yield item

输出,可以看到,将结果保存到了字典中。
在这里插入图片描述
这就爬取到了第一页内容,要想继续爬取。
可以下面这种方法。

yield scrapy.Request(url=next, callback=self.parse)
在这里插入图片描述
如果想要保存运行结果,运行下面的命令即可。

scrapy crawl 文件名 -o json文件名,可将结果保存为json文件。
如scrapy crawl example -o example.json
生成的文件还支持 csv 、 xml、marchal、pickle

管道

在pipelines填写如下代码

class MyScrapyPipeline:
    def process_item(self, item, spider):  # 移除标题中的空格
        if item["title"]:
            item["title"] = item["title"].strip()#移出标题左右空格
            return item

该代码用于移除标题中的左右空格。再次运行爬虫代码,会发现标题的左右空格已经被移除。

相关文章:

  • 哈工大李治军老师操作系统笔记【23】:内存换出(Learning OS Concepts By Coding Them !)
  • Ubuntu 20.04 设置开机自启脚本
  • Vue2封装评论组件详细讲解
  • java-php-python-springboot校园新闻趣事计算机毕业设计
  • 使用Docker Compose搭建WordPress博客
  • 【Linux篇】第十一篇——动静态库(动静态库的介绍+动静态库的打包与使用)
  • 多任务学习(MTL)--学习笔记
  • 前端性能优化方法与实战01 体系总览:性能优化体系及关键指标设定
  • 小米面试——C++开发岗位
  • 【训练方法】OHEM
  • java毕业设计汽车出租平台源码+lw文档+mybatis+系统+mysql数据库+调试
  • C#教程 - 其他(Other)
  • Java项目:JSP会议-会议室管理系统
  • 计算空间物体包围球的两种算法实现
  • Unity 导航寻路快速上手
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • 【css3】浏览器内核及其兼容性
  • 0x05 Python数据分析,Anaconda八斩刀
  • Apache Zeppelin在Apache Trafodion上的可视化
  • ERLANG 网工修炼笔记 ---- UDP
  • extract-text-webpack-plugin用法
  • HTTP--网络协议分层,http历史(二)
  • JavaScript 一些 DOM 的知识点
  • PhantomJS 安装
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • vuex 笔记整理
  • Vue--数据传输
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 类orAPI - 收藏集 - 掘金
  • 聊聊hikari连接池的leakDetectionThreshold
  • 小李飞刀:SQL题目刷起来!
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • 关于Android全面屏虚拟导航栏的适配总结
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • # include “ “ 和 # include < >两者的区别
  • (ros//EnvironmentVariables)ros环境变量
  • (ZT)出版业改革:该死的死,该生的生
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • .NET和.COM和.CN域名区别
  • @Autowired标签与 @Resource标签 的区别
  • [ 云计算 | AWS 实践 ] 基于 Amazon S3 协议搭建个人云存储服务
  • [Android实例] 保持屏幕长亮的两种方法 [转]
  • [ASP.NET 控件实作 Day7] 设定工具箱的控件图标
  • [Assignment] C++1
  • [bzoj1006]: [HNOI2008]神奇的国度(最大势算法)
  • [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)
  • [Cocoa]iOS 开发者账户,联机调试,发布应用事宜
  • [HackMyVM]靶场Crossbow
  • [LeetCode]—Rotate Image 矩阵90度翻转
  • [MAUI]集成高德地图组件至.NET MAUI Blazor项目
  • [unreal] 切换关卡
  • [WCF安全系列]从两种安全模式谈起