前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >pyspider使用教程

pyspider使用教程

作者头像
Remember_Ray
发布2021-04-05 11:21:38
3.6K0
发布2021-04-05 11:21:38
举报
文章被收录于专栏:Ray学习笔记

前言

pyspider 是一个用python实现的功能强大的网络爬虫系统,能在浏览器界面上进行脚本的编写,功能的调度和爬取结果的实时查看,后端使用常用的数据库进行爬取结果的存储,还能定时设置任务与任务优先级等。

本篇文章只是对这个框架使用的大体介绍,更多详细信息可见官方文档

安装

安装过程省略

注意:pyspider 与 python 版本存在关键词冲突等问题,推荐使用python 3.6

启动

在控制台输入命令

代码语言:javascript
复制
pyspider all

这样pyspider就算是跑起来了。

开始

拿这个网页来做例子:www.reeoo.com,爬取上面的数据。

新建任务

第一次跑起来的时候因为没有任务,界面的列表为空,右边有个Create按钮,点击新建任务。

  • Project Name:任务的名字,可以任意填
  • Start URL(s):爬取任务开始的地址,这里我们填目标网址的url

填写完成后,点击Create,便创建成功并跳转到了另一个界面,如下图所示

界面右边区域自动生成了初始默认的代码:

代码语言:javascript
复制
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2021-03-28 09:14:23
# Project: reo

from pyspider.libs.base_handler import *


class Handler(BaseHandler):
    crawl_config = {
    }

    @every(minutes=24 * 60)
    def on_start(self):
        self.crawl('www.reeoo.com', callback=self.index_page)

    @config(age=10 * 24 * 60 * 60)
    def index_page(self, response):
        for each in response.doc('a[href^="http"]').items():
            self.crawl(each.attr.href, callback=self.detail_page)

    @config(priority=2)
    def detail_page(self, response):
        return {
            "url": response.url,
            "title": response.doc('title').text(),
        }
  • on_start(self) 程序的入口,当点击左侧绿色区域右上角的 run 按钮时首先会调用这个函数
  • self.crawl(url, callback) pyspider库主要的API,用于创建一个爬取任务,url 为目标地址,这里为我们刚刚创建任务指定的起始地址,callback 为抓取到数据后的回调函数
  • index_page(self, response) 参数为 Response 对象,response.doc 为 pyquery 对象(具体使用可见pyquery官方文档),pyquery和jQuery类似,主要用来方便地抓取返回的html文档中对应标签的数据
  • detail_page(self, response) 返回一个 dict 对象作为结果,结果会自动保存到默认的 resultdb 中,也可以通过重载方法来讲结果数据存储到指定的数据库,后面会再提到具体的实现 其他一些参数
  • @every(minutes=24 * 60) 通知 scheduler(框架的模块) 每天运行一次
  • @config(age=10 * 24 * 60 * 60) 设置任务的有效期限,在这个期限内目标爬取的网页被认为不会进行修改
  • @config(priority=2) 设定任务优先级

运行

点击左边绿色区域右上角的 run 按钮,这时候调用的是 on_start 方法,运行之后页面下册的 follows 按钮出现红色角标

选中 follows 按钮,点击行右侧的运行按钮,这时候调用的是 index_page 方法

运行完成后显示如下图,即 www.reeoo.com 页面上所有的url

此时我们可以任意选择一个结果运行,这时候调用的是 detail_page 方法,返回最终的结果。

结果为json格式的数据,这里我们保存的是网页的 titleurl,见左侧黑色的区域

回到主页面,此时看到任务列表显示了我们刚刚创建的任务,设置 status 为 running,然后点击 Run 按钮执行

执行过程中可以看到整个过程的打印输出

执行完成后,点击 Results 按钮,进入到爬取结果的页面

右上方的按钮选择将结果数据保存成对应的格式,例如:JSON格式的数据为:

以上则为pyspider的基本使用方式。

爬取指定数据

接下来我们通过自定义来抓取我们需要的数据,目标为抓取这个页面中,每个详情页内容的标题、标签、描述、图片的url、点击图片所跳转的url。

点击首页中的 Create,新建一个新的脚本myReo并跳转到脚本的编辑界面

获取所有详情页面的url

index_page(self, response) 函数为获取到 www.reeoo.com 页面所有信息之后的回调,我们需要在该函数中对 response 进行处理,提取出详情页的url。

通过查看源码,可以发现 class 为 thum 的 div 标签里,所包含的 a 标签的 href 值即为我们需要提取的数据,如下图

代码的实现

代码语言:javascript
复制
@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
    for each in response.doc('div[class="thumb"]').items():
        detail_url = each('a').attr.href
        print(detail_url)
        self.crawl(detail_url, callback=self.detail_page)
  • response.doc(‘div[class=”thumb”]’).items() 返回的是所有 class 为 thumb 的 div 标签,可以通过循环 for…in 进行遍历。
  • each(‘a’).attr.href 对于每个 div 标签,获取它的 a 标签的 href 属性。
  • 可以将最终获取到的url打印,并传入 crawl 中进行下一步的抓取。 点击代码区域右上方的 save 按钮保存,并运行起来之后的结果如下图,中间的灰色区域为打印的结果

注意左侧区域下方的几个按钮,可以展示当前所爬取页面的一些信息,web 按钮可以查看当前页面,html 显示当前页面的源码,enable css selector helper 可以通过选中当前页面的元素自动生成对应的 css 选择器方便的插入到脚本代码中,不过并不是总有效,在我们的demo中就是无效的~

抓取详情页中指定的信息

接下来开始抓取详情页中的信息,任意选择一条当前的结果,点击运行,如选择第三个

修改 detail_page 函数

代码语言:javascript
复制
@config(priority=2)
def detail_page(self, response):
    
    header = response.doc('body > article > section > article > header')
    title = header('h1').text()
    
    time = header('time').text()
    
    tags = []
    for each in header.items('a'):
        tags.append(each.text())
        
    content = response.doc('div[id="post_content"]')
    description = content('blockquote > p').text()
    
    website_url = content('a').attr.href
    
    image_url_list = []
    for each in content.items('img[data-src]'):
        image_url_list.append(each.attr('data-src'))
    
    return {
        "title": title,
        "time": time,
        "tags": tags,
        "description": description,
        "image_url_list": image_url_list,
        "website_url": website_url,
    }
  • response.doc(‘body > article > section > article > header’) 参数和CSS的选择器类似,获取到 header 标签, .doc 函数返回的是一个 pyquery 对象。
  • header(‘h1’).text() 通过参数 h1 获取到标签,text() 函数获取到标签中的文本内容,通过查看源码可知道,我们所需的标题数据为 h1 的文本。
  • 标签页包含在 header 中,a 的文本内容即为标签,因为标签有可能不止一个,所以通过一个数组去存储遍历的结果 header.items(‘a’)
  • response.doc(‘div[id=”post_content”]’) 获取 id 值为 post_content 的 div 标签,并从中取得详情页的描述内容,有的页面这部分内容可能为空。

具体html的源码如下图:

其余数据分析抓取的思路基本一致。

最终将需要的数据作为一个 dict 对象返回,即为最终的抓取结果

代码语言:javascript
复制
{
    "title": title,
    "time": time,
    "tags": tags,
    "description": description,
    "image_url_list": image_url_list,
    "website_url": website_url,
}

保存之后直接点击左边区域的 run 按钮运行起来,结果如图,中间灰色区域为分析抓取到的结果。

完整代码

代码语言:javascript
复制
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2021-03-28 09:24:37
# Project: myReo

from pyspider.libs.base_handler import *


class Handler(BaseHandler):
    crawl_config = {
    }

    @every(minutes=24 * 60)
    def on_start(self):
        self.crawl('http://reeoo.com/', callback=self.index_page)

    @config(age=10 * 24 * 60 * 60)
    def index_page(self, response):
        for each in response.doc('div[class="thumb"]').items():
            detail_url = each('a').attr.href
            print(detail_url)
            self.crawl(detail_url, callback=self.detail_page)

    @config(priority=2)
    def detail_page(self, response):
        
        header = response.doc('body > article > section > article > header')
        title = header('h1').text()
        
        time = header('time').text()
        
        tags = []
        for each in header.items('a'):
            tags.append(each.text())
            
        content = response.doc('div[id="post_content"]')
        description = content('blockquote > p').text()
        
        website_url = content('a').attr.href
        
        image_url_list = []
        for each in content.items('img[data-src]'):
            image_url_list.append(each.attr('data-src'))
        
        return {
            "title": title,
            "time": time,
            "tags": tags,
            "description": description,
            "image_url_list": image_url_list,
            "website_url": website_url,
        }

在主页把任务重新跑起来,查看运行结果

可以看到我们需要的数据都抓取下来

持久化数据

抓取到的数据默认存储到 resultdb 中,虽然很方便通过浏览器进行浏览和下载,但却不太适合进行大规模的数据存储。

所以最好的处理方式还是将数据保存在常用的数据库系统中,本例采用的数据库为 mongodb。

参数的配置

新建一个文件,命名为 config.json,放在 F: 盘下,以 JSON 格式存储配置信息。文件到时候作为 pyspider 配置命令的参数。

文件具体内容如下:

代码语言:javascript
复制
{
	"taskdb": "mongodb+taskdb://127.0.0.1:27017/pyspider_taskdb",
  	"projectdb": "mongodb+projectdb://127.0.0.1:27017/pyspider_projectdb",
  	"resultdb": "mongodb+resultdb://127.0.0.1:27017/pyspider_resultdb",
  	"message_queue": "redis://127.0.0.1:6379/db"
}

Ps. 在运行之前,你得保证打开本地的数据库 mongodb 和 redis,如果pyspider缺失模块,安装即可。具体怎么玩自行搜索~

通过设置参数的命令重新运行起来:

代码语言:javascript
复制
pyspider -c f:config.json

数据库存储的实现

通过重载 on_result(self, result) 函数,将结果保存到 mongodb 中,具体代码实现

代码语言:javascript
复制
def on_result(self, result):
    if not result:
        return

    client = pymongo.MongoClient(host='127.0.0.1', port=27017)
    db = client['pyspyspider_projectdb']
    coll = db['website']

    data = {
        'title': result['title'],
        'tags': result['tags'],
        'time': result['time'],
        'description': result['description'],
        'website_url': result['website_url'],
        'image_url_list': result['image_url_list']
    }

    data_id = coll.insert(data)
    print (data_id)
  • on_result(self, result) 在每一步抓取中都会调用,但只在 detail_page 函数调用后参数中的 result 才会不为 None,所以需要在开始的地方加上判断。
  • db = client[‘pyspyspider_projectdb’] 中数据库的名字 pyspyspider_projectdb 为之前在 config.json 配置文件中的值。
  • coll = db[‘website’] 在数据库中创建了一张名为 website 的表。
  • data_id = coll.insert(data) 将数据以我们制定的模式存储到 mongodb 中。 (除了重载on_result方法外,也可以通过重载ResultWorker类来实行结果的处理,需要在配置文件中加上对应的参数。) 重新新建一个任务,将完整的代码拷进去,在主界面完成的跑一遍。

运行完成后,浏览器查看结果,因为设置了数据库的存储,不再存储在默认的 resultdb 中,此时浏览器的result界面是没有数据的

数据库查看数据

这里直接使用MongoDB安装完成后自带的MongoDBCompass查看数据

查看项目持久化

查看项目结果持久化

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-04-04|,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 安装
  • 启动
  • 开始
    • 新建任务
      • 运行
      • 爬取指定数据
        • 获取所有详情页面的url
          • 抓取详情页中指定的信息
          • 持久化数据
            • 参数的配置
              • 数据库存储的实现
                • 数据库查看数据
                相关产品与服务
                对象存储
                对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档