Scrapy框架——使用CrawlSpider爬取数据

引言

本篇介绍Crawlspider,相比于Spider,Crawlspider更适用于批量爬取网页

Crawlspider

  • Crawlspider适用于对网站爬取批量网页,相对比Spider类,CrawSpider主要使用规则(rules)来提取链接,通过定义一组规则为跟踪链接提供了遍历的机制。
  • Crawlspider 的强大体现在自动爬取页面所有符合规则的链接并深入下去!

全站数据爬取

编码流程

  1. 新建一个工程
  2. cd 工程
  3. 创建爬虫文件: scrapy genspider -t crawl spiderName 地址 (crawlspider 继承 scrapy.Spider)
    • 链接提取器 LinkExtractor

      • 可以根据指定的规则对指定的链接进行提取

        • 提取的规则就是构造方法中的 allow(‘正则表达式’) 参数决定
    • 规则解析器 Rule
      • 可以将链接提取器提到的链接进行请求,可以根据指定的规则(callback)对请求到的数据进行解析

    Rule(link, callback=‘parse_item‘, follow=True)

    • follow = True 表示每一个页码都当作起始url 然后进行链接提取,如果为 false 只能提取到第一页的几个页码。
    • follow = True; 将链接提取器 继续作用到 连接提取器提取到的链接 所对应的 页码源码中。

scrapy中发送请求的几种方式:

  • start_url
  • self.Request()
  • 链接提取器

例子

使用CrawlSpider模板批量爬取(阳光热线问政平台的投诉帖子)的主题、状态和详细内容

地址为:http://wz.sun0769.com/html/top/reply.shtml

① 定义spider

scrapy genspider -t crawl sun 创建一个spider

在该spider文件中:

  • 定义 LinkExtractor 获取每个页面中的页码的url地址。
  • 定义 Rule ,放入 LinkExtractor 以及 callback ,对于 follow 值得话,如果为True得话,将继续作用到 LinkExtractor 提取到的链接 所对应的 页码源码中。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
# sun.py# -*- coding: utf-8 -*-import scrapyfrom scrapy.linkextractors import LinkExtractorfrom scrapy.spiders import CrawlSpider, Rulefrom sunPro.items import Item1, Item2

class SunSpider(CrawlSpider):    name = ‘sun‘    # allowed_domains = [‘www.xxx.com‘]    start_urls = [‘http://wz.sun0769.com/html/top/reply.shtml‘]    # 链接提取器(如:获得每一个页码)    link = LinkExtractor(allow=r‘page=\d+‘)  # 空的话取所有url    link_1 = LinkExtractor(allow=r‘page=$‘)  # 拿到第一页数据    link_detail = LinkExtractor(allow=r‘question/\d+/\d+\.shtml‘)  # 拿到第一页数据 . 需要转义

    rules = (        # 实例化一个Rule(规则解析器)对象        Rule(link, callback=‘parse_item‘, follow=True),	        Rule(link_1, callback=‘parse_item‘),        Rule(link_detail, callback=‘parse_detail‘),        # follow = True; 将链接提取器 继续作用到 连接提取器提取到的链接 所对应的 页码源码中    )

    # 数据解析: 用来解析连接提取器提取到的链接所对应的页码    def parse_item(self, response):        # tr_list = response.xpath(‘/html/body/div[8]/table[2]/tbody/tr‘)   # xpath中不能含有tbody        tr_list = response.xpath(‘/html/body/div[8]/table[2]//tr‘)

        for tr in tr_list:            title = tr.xpath(‘./td[3]/a[1]/text()‘).extract_first()            status = tr.xpath(‘./td[4]/span/text()‘).extract_first()            num = tr.xpath(‘./td[1]/text()‘).extract_first()            # print(num, title,status)            item = Item2()            item[‘title‘] = title            item[‘status‘] = status            item[‘num‘] = num            yield item        # print(response)

    # 解析详情页中的新闻内容    def parse_detail(self, response):        content = response.xpath(‘/html/body/div[9]/table[2]//tr[1]/td//text()‘).extract()        if content:            content = ‘‘.join(content)            num = response.xpath(‘/html/body/div[9]/table[1]//tr/td[2]/span[2]‘).extract_first().split(‘:‘)[-1].replace(                r‘</span>‘, ‘‘)            # print(num, content)            item = Item1()            item[‘content‘] = content            item[‘num‘] = num            yield item

② 定义Item类

  1. 两个Rule是为了拿到所有页码的url,它对应着 Item2
  2. 另一个Rule是为了拿到所有详情页的url,它对应着 Item1
12345678910111213
# items.pyimport scrapy

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

class Item2(scrapy.Item):    # define the fields for your item here like:    title = scrapy.Field()    status = scrapy.Field()    num = scrapy.Field()

③ 定义pipeline

定义pipeline做持久化存储!

  1. open_spider 中开起连接
  2. close_spider 中关闭连接
  3. process_item 中执行数据库得插入操作。

遇到的问题:

  • 第一个问题:主题和状态与详细内容如何对应起来呢?

    • 通过对页面进行分析发现,使用在这两个页面中都有编号,所以增加一个新的字段变化,来连接这两块。
  • 两个数据解析函数不同于使用scrapy.Request进行手动传参,然后通过回调来进行连接。而现在只能定义两个 Item ,在管道中如何判断item类型:
    • item.__class__.__name__ 表示类名
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
# pipeline.pyimport pymysql

class SunproPipeline(object):    conn = None    cursor = None

    def open_spider(self, spider):        self.conn = pymysql.Connection(host=‘127.0.0.1‘, user=‘root‘, password="2296",                                       database=‘spider‘, charset=‘utf8‘)

    def process_item(self, item, spider):        self.cursor = self.conn.cursor()        if item.__class__.__name__ == ‘Item1‘:            content = item[‘content‘]            num = item[‘num‘]            query_sql = ‘select * from sun where num = %s‘            self.cursor.execute(query_sql, (num,))            ret = self.cursor.fetchall()            if ret:                insert_sql = f‘update sun set content = %s where num=%s‘                try:                    self.cursor.execute(insert_sql, (content, num))                    self.conn.commit()                except Exception as e:                    print(e)                    self.conn.rollback()            else:                insert_sql = f‘insert into sun(num,content) values (%s, %s)‘                try:                    self.cursor.execute(insert_sql, (num, content))                    self.conn.commit()                except Exception as e:                    print(e)                    self.conn.rollback()        else:            title = item[‘title‘]            status = item[‘status‘]            num = item[‘num‘]            query_sql = f‘select * from sun where num = %s‘            self.cursor.execute(query_sql, (num,))            ret = self.cursor.fetchall()            if ret:                insert_sql = f‘update sun set title = %s,status = %s where num=%s‘                try:                    self.cursor.execute(insert_sql, (title, status, num))                    self.conn.commit()                except Exception as e:                    print(e)                    self.conn.rollback()            else:                insert_sql = f‘insert into sun(num,title,status) values (%s, %s,%s)‘                try:                    self.cursor.execute(insert_sql, (num, title, status))                    self.conn.commit()                except Exception as e:                    print(e)                    self.conn.rollback()

        return item

    def close_spider(self, spider):        self.cursor.close()        self.conn.close()

原文地址:https://www.cnblogs.com/taosiyu/p/11710031.html

时间: 2024-10-04 10:33:55

Scrapy框架——使用CrawlSpider爬取数据的相关文章

爬虫5 scrapy框架2 全站爬取cnblogs, scarpy请求传参, 提高爬取效率, 下载中间件, 集成selenium, fake-useragent, 去重源码分析, 布隆过滤器, 分布式爬虫, java等语言概念补充, bilibili爬视频参考

1 全站爬取cnblogs # 1 scrapy startproject cnblogs_crawl # 2 scrapy genspider cnblogs www.cnblogs.com 示例: # cnblogs_crawl/cnblogs_crawl/spiders/cnblogs.py import scrapy from cnblogs_crawl.items import CnblogsCrawlItem from scrapy.http import Request class

jdango+scrapy结合使用并爬取数据入库

1. 创建django项目,并编写models.py,启动django项目 2. 配置Django嵌入 Django项目根目录下创建Scrapy项目(这是scrapy-djangoitem所需要的配置) 配置Django嵌入,在Scrapy的settings.py中加入以下代码: import os import sys sys.path.append(os.path.dirname(os.path.abspath('.'))) os.environ['DJANGO_SETTINGS_MODUL

Scrapy框架——CrawlSpider爬取某热线网站

CrawlSpider Scrapy框架中分两类爬虫,Spider类和CrawlSpider类. 它是Spider的派生类,Spider类的设计原则是只爬取start_url列表中的网页, 而CrawlSpider类定义了一些规则(rule)来提供跟进link的方便的机制,从爬取的网页中获取link并继续爬取的工作更适合. 创建项目指令: scrapy startproject sumPro CrawlSpider创建: scrapy genspider -t crawl sun "http:/

Python网络爬虫之Scrapy框架(CrawlSpider)

目录 Python网络爬虫之Scrapy框架(CrawlSpider) CrawlSpider使用 爬取糗事百科糗图板块的所有页码数据 Python网络爬虫之Scrapy框架(CrawlSpider) 提问:如果想要通过爬虫程序去爬取"糗百"全站数据新闻数据的话,有几种实现方法? 方法一:基于Scrapy框架中的Spider的递归爬取进行实现(Request模块递归回调parse方法). 方法二:基于CrawlSpider的自动爬取进行实现(更加简洁和高效). CrawlSpider使

爬虫学习 16.Python网络爬虫之Scrapy框架(CrawlSpider)

爬虫学习 16.Python网络爬虫之Scrapy框架(CrawlSpider) 引入 提问:如果想要通过爬虫程序去爬取"糗百"全站数据新闻数据的话,有几种实现方法? 方法一:基于Scrapy框架中的Spider的递归爬取进行实现(Request模块递归回调parse方法). 方法二:基于CrawlSpider的自动爬取进行实现(更加简洁和高效). 今日概要 CrawlSpider简介 CrawlSpider使用 基于CrawlSpider爬虫文件的创建 链接提取器 规则解析器 今日详

【个人】爬虫实践,利用xpath方式爬取数据之爬取虾米音乐排行榜

实验网站:虾米音乐排行榜 网站地址:http://www.xiami.com/chart 难度系数:★☆☆☆☆ 依赖库:request.lxml的etree (安装lxml:pip install lxml) IDEA开发工具:PyCharm_2017.3 Python版本:Python3 期望结果:爬取出排行版歌名以及对应歌手 运行效果图: 音乐排行榜: 爬取数据结果图: 像这种简单的爬取就没必要使用Scrapy框架进行处理,是在有点大材小用,不过如果你刚开始学Scrapy的话,拿这些简单的练

借助Chrome和插件爬取数据

工具 Chrome浏览器 TamperMonkey ReRes Chrome浏览器 chrome浏览器是目前最受欢迎的浏览器,没有之一,它兼容大部分的w3c标准和ecma标准,对于前端工程师在开发过程中提供了devtools和插件等工具,非常方便使用.在爬取数据的过程中,最常用的应该是开发工具中的Element.Source和Network功能,分别查看DOM结构,源码和网络请求.同时,有很多基于Chrome浏览器的插件又给我们赋予了浏览器级别的能力,来处理数据. TamperMonkey Ta

web scraper——简单的爬取数据【二】

web scraper——安装[一] 在上文中我们已经安装好了web scraper现在我们来进行简单的爬取,就来爬取百度的实时热点吧. http://top.baidu.com/buzz?b=1&fr=20811 文本太长,大部分是图片,所以上下操作视频吧,视频爬取的是昵称不是百度热点数据 链接:https://pan.baidu.com/s/1W-8kGDznZZjoQIk1e6ikfQ提取码:3dj7 爬取步骤 创建站点 打开百度热点,ctrl+shit+i进入检测工具,打开web scr

scrapy之360图片爬取

#今日目标 **scrapy之360图片爬取** 今天要爬取的是360美女图片,首先分析页面得知网页是动态加载,故需要先找到网页链接规律, 然后调用ImagesPipeline类实现图片爬取 *代码实现* so.py ``` # -*- coding: utf-8 -*- import scrapy import json from ..items import SoItem class SoSpider(scrapy.Spider): name = 'so' allowed_domains =