IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Python爬虫11-Scrapy爬虫框架 -> 正文阅读

[大数据]Python爬虫11-Scrapy爬虫框架

? ? ? ?

目录

11.1认识Scrapy

11.1.1安装所需依赖包

11.1.2认识Scrapy

11.2Scrapy shell的使用

11.2.1运行shell

11.2.2使用Scrapy shell爬取Scrapy.org

11.2.3爬虫调用shell

11.3使用Scrapy爬取qutoes

11.3.1 创建Scrapy项目并新建爬虫

11.3.2爬取和提取数据

11.4 setting基本设置

11.5Pipeline模块

11.5.1 爬取文字板块

11.5.2编写pipeline模块

11.5.3通不过pipeline将数据写入MongoDB数据库中


????????写程序的时候,别人写好的工具、库、框架被称作轮子。有现成的,写好的东西不用,自己又去写一遍,这叫做重复造轮子。今天来认识爬虫的常见轮子Scrapsdy。

11.1认识Scrapy

11.1.1安装所需依赖包

? ? ? ? Scrapy安装前需要先安装依赖包,不然会因缺少依赖包导致安装失败,如下表

lxmlparselw3libtwistedcryptographypyOenSSL
解析XML和HTML非常高校的工具HTML.XML数据提取网页解码异步网络编程框架用于加密进行一些加解密操作

? ? ? ? 这些包可以通过pip单独安装。也可以先创建一个requirements.txt文件,然后把包名写入并保存即可

lxml
parsel
w3lib
twisted
crptography
pyOpenSSL

? ? ? ? ?然后终端输入

pip install -r requirements.txt

11.1.2认识Scrapy

? ? ? ? Scrapy是一个用于抓取网页并提取数据的应用框架。即使Scrapy最初是被设计用于网页爬取,但同样也可以用于提取API数据。

? ? ? ? 接下来通过一个简单的Scrapy爬虫例子来展示Scrapy的用法。这里有一段爬取国外名人名言网页的代码

import scrapy

class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = [
        'http://quotes.toscrape.com/tag/humor'   #待抓取的URL
    ]
    def parse(self, response):                     #parse默认为抓取回调函数,再次定义抓取网页后的操作
        for quote in response.css('div.quote'):
            yield {
                'text':quote.css('span.text::text').extract_first(),
                'author':quote.xpath('span/small/text()').extract_first()
            }
        next_page = response.css('li.next a::attr("href")').extract_first()     #使用css选择器找到下一页链接

        if next_page is None:
            yield response.follow(next_page,self.parse)       #访问下一页,回调到parse函数

? ? ? ? 将代码保存为spider.py文件,然后在当前目录下用命令运行爬虫,输入:scrapy runspider qutoes_spider.py -o quotes.json

? ? ? ? 当爬虫运行结束,会得到一个quotes.json文件,打开发现是一个列表里面包含列经过json格式化的名人名言。字段有作者、内容,就像下面这样。

? ? ? ? ?scrapy的优点之一就是发送请求,调度和处理是异步进行的,这意味着scrapy不需要等待请求完成才能进行处理,他可以同时发送其他请求活着做其他事情。也就是说,即使有一些请求失败或者发生错误,其他的请求也会照常工作。

? ? ? ? 同样,它也允许进行快速爬取(用容错率高的方式,同时发送大量的并发请求。因为速度加快会导致爬取失败)。Scrapy在setting中提供列一些选择可以让我们使用比较暴力的方式进行爬取,可以在两个请求之间设置延迟,也可以限制每个网站或者IP的并发请求量。

? ? ? ? 其他超赞的功能:

? ? ? ? 支持使用css选择去或者xpath从HTML/XML源码中枷锁和提取数据

? ? ? ? 交互式的shell在爬虫和debugging的时候非常有用。

? ? ? ? 支持多种格式的输出:如json,csv,xml,并提供多种方式存储如(FTP,s3,本地文件)

? ? ? ? 一些非标准的或其他国家的语言,Scrapy能够很好的进行编码

? ? ? ? 可以自行编写属于自己的函数,实现自己的需求

11.2Scrapy shell的使用

? ? ? ? Scrapy shell是一个可交互的终端,可以在不运行爬虫状态下快速的调试代码,其本意是用来测试提取数据的代码。在shell理,你可以测试xpath或者css的表达式,通过从网页提取的数据判断是否正确。当适应列Scrapy shell以后就会发现这是一个相当好用的开发和debugging工具。

11.2.1运行shell

? ? ? ? 打开终端直接运行:Scrapy shell <URL> ,<URL>填写想爬取的网页的URL,当然填写本地的html文件路径也是可以的。

? ? ? ? shelp()调出帮助菜单

? ? ? ? fetch()从定义的URL中获取一个新的response对象

? ? ? ? view(response) 用浏览器打开一个response对象,这个对象被保存在本地

11.2.2使用Scrapy shell爬取Scrapy.org

? ? ? ? 官方有一个如何使用shell的简单例子,这个例子是通过shell来直接抓取一个网页,并对返回的对象进行解析和查看,让我们可以快速了解shell的各种功能。终端输入:

scrapy shell "https://Scrapy.org" --nolog

? ? ? ? ?这里有很多个选项,但一般用到的只有response、request、fetch等几个。response是Scrapy shell请求返回的对象,可以对response对象进行数据提取的操作。request则是请求的方式,默认为GET,可以修改为POST。

? ? ? ? 开始调式对象:

>>> response.xpath('//title/text()').extract_first()  #使用xpath提取标题

>>> fetch("https://www.baidu.com")        #抓取百度网址
>>> response.xpath('//title/text()').extract()  #提取百度网址的标题

? ? ? ? 使用xpath对response对象进行数据提取,获取网页标题。fetch方法可以发起一个新的请求。抓住新的URL。通过request方法修改请求方式为POST。使用pprint打印response对象headers属性得到的结果。

? ? ? ? 使用Scrapy shell可以对网页快速请求获取response,使用xpath从源码中提取数据进行调试,同时Scrapy shell还可以修改请求的方式和请求头。在编写Scrapy爬虫之前,使用Scrapy shell进行调试可以帮助编写爬虫过程中少犯错误。

11.2.3爬虫调用shell

? ? ? ? 有时候检查response爬虫是必不可少的一个重要环节。这时候可以是使用Scrapy.shell。inspect_response函数。

? ? ? ? (1)首先创建项目test2。

scrapy startproject test

? ? ? ? (2)创建文件spider.py,并保存在spiders目录下。

import scrapy

class MySpider(scrapy.Spider):
    name =  "myspider"
    start_urls = [
        "http://example.com",
        "http://example.org",
        "http://example.net"
    ]

    def parse(self,response):
        if ".org" in response.url:
            from scrapy.shell import inspect_response
            inspect_response(response,self)

? ? ? ? (3)在test2目录下(scrapy.cfg所在的那层目录),运行爬虫

scrapy crawl myspider

?????????爬虫运行的时候,shell同样会被调用。?

? ? ? ? 然后可以通过操作response对相关检查各项参数或者提取数据。如response.url查看response对象的url。

11.3使用Scrapy爬取qutoes

? ? ? ? 现在开始建立自己的爬虫项目去爬取quotestoscrape.com,名人名言网站。建立项目需要完成以下简单几个步骤:

? ? ? ? (1)创建自己的Scrapy项目。

? ? ? ? (2)编写一个网页爬虫并抓取数据。

? ? ? ? (3)通过命令行输入数据

? ? ? ? (4)让爬虫自动爬取下一页内容

? ? ? ? (5)学会使用爬虫参数

11.3.1 创建Scrapy项目并新建爬虫

? ? ? ? 在开始爬取之前,需要新建一个scrapy的项目。在当前目录下运行中福安输入命令:?

scrapy startproject tutorial

? ? ? ? ?spider是定义的爬虫类,用来编写爬取网页的逻辑。编写爬虫的类的class是必须继承scrapy.Spider。同时需要定义最初的URL,可以通过列表形式的start_urls,也可以通过start_requests()函数来定义。发起的请求会回调到parse函数。在parse函数下选择如何进入下一页,还有如何解析下载回来的网页内容以便提取数据,这是第一个爬虫代码,命名为quotes_spider.py保存在tutorial/spiders目录下。(quotes-1,quotes-1是我已经运行过代码所得到的网页源码)

? ? ? ? ?quotes_spider.py文件代码如下:

import scrapy
from scrapy import Request
class QuotesSpider(scrapy.Spider):
    name = "quotes"
    def start_requests(self):
        urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/'
        ]
        for url in urls:
            yield Request(url=url,callback=self.parse)

    def parse(self, response):
        page = response.url.split("/")[-2]
        filename = 'quotes-%s.html' %page
        with open(filename,'wb') as f :
            f.write(response.body)
        self.log('Saved file %s' %filename)


"""
class QuotesSpider(scrapy.Spider):
    name = "quotes"

    def start_requests(self):
        start_urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/'
        ]

        def parse(self, response):
            page = response.url.split("/")[-2]
            filename = 'quotes-%s.html' % page
            with open(filename, 'wb') as f:
                f.write(response.body)
"""

? ? ? ? ?从代码中可以看到爬虫继承列scrapy.Spider并且定义列一些参数和方法:

? ? ? ? name:是爬虫的名字,必须是唯一的。

? ? ? ? start_requests():你可以返回一个请求的列表,里面是URL,或者自己写一个生成器的功能。这是爬虫开始爬取的一个或多个连接。

? ? ? ? urls:存储爬取连接的列表,遍历列表,yeid可以不中断函数并发起下一个请求。

? ? ? ? parse():从start_requests()下载回来的网页内容回调到parse()。下载回来的内容是一个response对象,然后从中提取数据并找到新的URL进行下一页的爬取。

11.3.2爬取和提取数据

? ? ? ? 运行爬虫需要在项目的目录最顶层运行命令(在scrapy.cfg的同层目录)就下面这个目录。输入命令:scrapy crawl quotes.

? ? ? ? 然后爬虫会运行刚刚新建的名字为quotes的爬虫,它会发送请求到网站quotes.toscrape.com?

这时候当前目录下有两个新文件被创建列:quotes-1.html和quotes-2.html,里面的内容是刚才爬取的两个网页的源代码。

? ? ? ? 除了使用start_requests()这个函数来请求开始请求URL,还可以使用更简单的方式定义start_urls列表。上面多行注释掉的代码。

"""
class QuotesSpider(scrapy.Spider):
    name = "quotes"

    def start_requests(self):
        start_urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/'
        ]

        def parse(self, response):
            page = response.url.split("/")[-2]
            filename = 'quotes-%s.html' % page
            with open(filename, 'wb') as f:
                f.write(response.body)
"""

? ? ? ? 请求每一个URL返回的response会默认回调到parse方法中。对入门者来说提取数据是一个比较头疼的问题。因为对工具和网页源码的不熟悉,很难准确定位到数据的位置。通过shell来学习数据提取是一个不错的选择。

? ? ? ? 在终端输入命令:

scrapy shell "http://quotes.toscrape.com/page/1/"

? ? ? ? ?通过shell可以使用css选择器来选择对象里的元素。

? ? ? ? ?这里返回的是一个类似列表的对象,但我们需要的是从列表对象中提取文本内容。这里我们‘::text’,意思是只选择文本内容,如果没有这个的话,它会返回连标签页一起返回。

? ? ? ? 这里返回的对象还是个列表,列表有时候会有多个文本内容,如:

['<title>Quotes to scrape1<title> '],
'<title>Quotes to scrape1<title> '],'<title>Quotes to scrape2<title> '],'<title>Quotes to scrape4<title> ']

? ? ? ? ?但如果确定返回的文本内容就是列表中的第一个元素Quotes? to Scrape1,可以直接用:

11.4 setting基本设置

? ? ? ? Scrapy中有一个setting.py的文件,里面是Scrapy的爬取配置。如果打开可以发现,里面很多配置都被注释掉了没有使用。所以Scrapy在爬取过程中很多功能并没有被激活。

? ? ? ? 重新开始创建一个Scrapy项目

scrapy startproject myproject

? ? ? ? ?settings.py文件,Scrapy的配置就写在里面。不管是禁用功能还是激活功能都在配置中执行。

? ? ? ? (1)在配置中默认激活的有:

? ? ? ? ?BOT_NAME这个很好理解,指爬虫爬虫的名字。而爬虫模块myproject.spiders是编写爬虫爬取逻辑的所在。机器人守则ROBOTSTXT,有一些网站是存在ROBOTSTXT的。在守则中网站 站长会告诉你它不允许你爬取他的网站,或者网站中哪些地方不希望被爬取。所以,爬虫其实不是什么内容都能爬的。常用的搜索引擎百度、谷歌就是个大爬虫。但是如此强大的搜索网站,也有搜索不到的内容。比如说QQ空间的日志,因为QQ空间ROBOTSTXT告诉列这些搜索网站的爬虫,自己不希望被爬取。所以无法通过搜索获取到的内容的。

? ? ? ? (2)如果已经对Scrapy的基础有所了解,那应该记得在使用Scrapy爬取数据的过程中会使用到item。item使一个存放数据的容器,通过item.py进行定义。然后爬虫模块通过import进行使用。但是最后数据流转到哪个模块中进行清洗或者保存,需要在ITEM_PIPELINES中进行配置。

ITEM_PIPELINES = {'myproject.pipelines.YOURCLASS':300}

? ? ? ? 例如上面的myproject.pipelines.YOURCLASS指在myproject项目下pipeline模块中的YOURCLASS类需要使用到item,后面的数字300代表优先级,数字越小优先级越高。

? ? ? ? (3)DEFAULT_REQUEST_HEADERS默认使用的请求头。爬虫伪装最简单的手段,伪装请求头。scrapy使用的请求头:

DEFAULT_REQUEST_HEADERS = {
    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language':'en',
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'
}

? ? ? ? 细心观察,这个请求头中没有USER_AGENT。那是因为Scrapy基本配置有着独立的USER_AGENT参数。

USER_AGENT = 'myproject(+http://www.yourdomain.com)'

? ? ? ? 这个USER_AGENT由项目名+爬取目标URL构成,这个很奇怪。平时使用的USER_AGENT是各种浏览器的请求头信息。对方湾站是根据请求头信息来获取你的系统浏览器信息,然后返回数据。请求头分不同浏览器,如火狐,谷歌,Opear,不同的系统:pc和手机。有时候有些网站你想要获取他的手机页面的数据,必须使用手机请求头才能成功。

? ? ? ? (4)DOWNLOAD_DELAY下载延迟。爬虫爬取的过程是一个不断向目标网站发起请求的过程,过快的爬取速度会给对方服务器造成负担,变成一种共计行为。所以DOWNLOAD_DELAY这个参数的存在,设置了爬取的间隔时间。

? ? ? ? (5)CONCURRENT_REQUESTS控制下载并发数,默认为个并发。如果完成一次操作要的时间是0.25秒,16个并发每秒会产生64个请求。

? ? ? ? (6)CONCURENT_REQUESTS_PER_IP对单个进行并发请求的最大值,这个设定为非0的时候,DOWNLOAD_DELAY延迟作用在IP上而不是网站上。

? ? ? ? (7)CONCURENT_REQUESTS_PER_DOMAIN对 单个网站进行并发请求的最大值

11.5Pipeline模块

? ? ? ? Pipeline翻译成中文是管道的意思,是抓取数据通往数据库的通道。而在这个管道里,我们可以对抓取的数据进行处理。数据抓取过程中,数据会保存在Item模块,然后流转到Pipeline模块中进行处理。在Pipeline模块中,可以通过自己编写的方法对数据进行保存、下载等操作。

11.5.1 爬取文字板块

? ? ? ? 上一节中已经创建列一个myproject的项目,现在可以直接在这个项目上编写爬虫,用来爬取糗事百科的文字板块。

? ? ? ? (1)进入myproject/spiders目录下新建爬虫spider.py文件。

import scrapy
from myproject.items import MyprojectItem

class MySpider(scrapy.Spider):
    name = "qiushibaike"

    start_urls = ["https://www.qiushibaike.com/text"]

    def parse(self, response):
        
        items = MyprojectItem()

        self.log('A response from %s just arrived!' % response.url)

? ? ? ? 编写列一个简单的爬虫逻辑,从start_urls进行爬取,结果返回到parse函数当中,这时候在顶层目录中打开终端运行爬虫的话会不成功,因为我们还没设置一些东西可能。然后我们接着配置我们的setting.py文件,关闭机器人守则,并且设置请求头

?????????然后在顶层目录下打开终端输入命令:scrapy crawl qiushibaike

? ? ? ? 请求成功后,糗事百科的源码保存在列response对象中,接下来就要从源码中提取数据并保存到容器中。

? ? ? ? (3)打开item.py文件,代码如下

import scrapy


class MyprojectItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    content = scrapy.Field()

? ? ? ? 定义列一个字段-内容。spider.py在import之后,可以直接使用MyprojectItem保存数据

? ? ? ? (4)编辑spider.py文件

import scrapy
from myproject.items import MyprojectItem

class MySpider(scrapy.Spider):
#通过xpath提取内容
    name = "qiushibaike"

    start_urls = ["https://www.qiushibaike.com/text"]

    def parse(self, response):
        contents = response.selector.xpath('//div[@class="content"]/span/text()').extract()
        #定义items作为数据暂存容器
        items = MyprojectItem()
        for i in contents:
            items['content'] = i.strip()
            yield items
           #通过生成器yield将数据传送到Pipeline进一步处理

        self.log('A response from %s just arrived!' % response.url)

? ? ? ? 打开终端,输入命令:scrapy crawl qiushibaike

? ? ? ? ?从控制台打印的内容可以看到items变量已经成功获得内容并将内容提交到pipeline当中。但是现在还没写pipeline,所以当前数据没有做任何处理。

11.5.2编写pipeline模块

? ? ? ? 已经从源代码中抓取列数据,现在要通过Pipeline模块来对数据进行处理。进入myproject项目,打开pipelines.py然后将其中代码改成一下代码。

? ? ? ? 代码的意思是得到数据之后,我们要写入到data.json这个文件中,代码是写好了,但是还没激活啊。我们需要到settings.py文件进行激活处理。进入settings.py文件中添加下面的代码:

ITEM_PIPELINES = {'myproject.pipelines.MyprojectPipeline':300}

? ? ? ? 然后进入目录顶层输入运行命令:scrapy? crawl qiushibaike?

? ? ? ? 运行完成之后我们就可以看到data.json文件了,打开文件就可以看到我们抓取的内容。

? ? ? ? ?在MyprojectPipeline()中,process_item()是必须的方法,在爬取过程调用对数据进行处理,处理完之后必须将item返回。另外open_spider()和close_spider()两个方法,前者是爬虫运行时调用,后者是爬虫关闭时调用。他们都只会运行一次。这两个方法不是必须的,可以根据自己的需求添加功能。

11.5.3通过pipeline将数据写入MongoDB数据库中

? ? ? ? 了解Pipeline模块的使用方法之后,继续拓展将数据写入MongoDB数据库上中。上一届提到MyprojectPipeline(),还有open_spider()和close_spider()两个方法,分别是爬虫运行时和爬虫运行结束后进行调用的。可以使用open_spider来链接数据,而clos_spider来关闭数据库链接。另外还需要增加一个from_crawler()的方法,主要功能为从配置文件settings.py中获取参数。当然也可以将参数写在Pipeline模块中,但是开发流程里所有参数都会放到一个配置文件中。

? ? ? ? (1)打开配置文件settings.py添加如下代码

MONGO_URI = 'localhost:27017'
MONGO_DB = 'scrapy_data'

ITEM_PIPELINES = {'myproject.pipelines.MyprojectPipeline':300,
                  'myproject.pipelines.Mongopipeline':350
                  }

? ? ? ? 最终的代码如下

? ? ? ? ?(2)打开pipeline.py文件添加如下代码,这个类在上面的setting中是已经激活了的。

class Mongopipeline(object):
    def __init__(self,mongouri,mongodb):
        self.mongouri = mongouri
        self.mongodb = mongodb
    @classmethod
    def from_crawler(cls,crawler):
        return cls(
            mongouri = crawler.settings.get("MONGO_URI"),
            mongodb = crawler.settings.get("MONGO_DB")
        )
    def process_item(self,item,spider):
        self.db.qiushibaike.insert(dict(item))
        return item
    def open_spider(self,spider):
        self.client = pymongo.MongoClient(self.mongouri)
        self.db = self.client[self.mongodb]
    def close_spider(self,spider):
        self.client.close()

? ? ? ? ?在控制台终端输入运行爬虫命令:scrapy crawl qiushibaike

? ? ? ? 进入数据库进行查看

? ? ? ? ?今天的scrapy框架先写到这里,后续会对他更新一下,因为有好几个板块需要更新的。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 08:02:49  更:2021-09-19 08:05:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:20:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码