Python基础之Scrapy进阶 Python基础之Scrapy简介

在上一篇文章Python基础之Scrapy简介中,简述了Scrapy的基本原理,安装步骤,创建项目以及如何通过Scrapy进行简单的爬虫,同时遗留了两个问题,即分页爬取,和异步内容爬取。本文以一个简单的爬取某股票网站为例,简述Scrapy在分页和接口数据爬取的相关应用,仅供学习分享使用,如有不足之处,还请指正。

Scrapy架构图

关于Scrapy架构图,如下所示: 绿线是数据流向

 

 关于Scrapy架构各项说明,如下所示:

  • Scrapy Engine(引擎): 负责 Spider、ItemPipeline、Downloader、Scheduler 中间的通讯, 信号、数据传递等。
  • Scheduler(调度器): 它负责接受引擎发送过来的 Request 请求,并按照一定的方式进行 整理排列,入队,当引擎需要时,交还给引擎。
  • Downloader(下载器):负责下载 Scrapy Engine(引擎)发送的所有 Requests 请求,并将 其获取到的 Responses 交还给 Scrapy Engine(引擎),由引擎交给 Spider 来处理,
  • Spider(爬虫):它负责处理所有 Responses,从中分析提取数据,获取 Item 字段需要的 数据,并将需要跟进的 URL 提交给引擎,再次进入 Scheduler(调度器),
  • Item Pipeline(管道):它负责处理 Spider 中获取到的 Item,并进行进行后期处理(详细 分析、过滤、存储等)的地方。
  • Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能 的组件。
  • Spider Middlewares(Spider 中间件):你可以理解为是一个可以自定扩展和操作引擎和 Spider 中间通信的功能组件(比如进入 Spider 的 Responses;和从 Spider 出去的 Requests)

目标分析

本次爬取的是某财富网站的沪深A股,共232页,如下所示:

在Chrome浏览器,通过开发者工具(F12),进行分析,发现我们需要爬取的内容,均在id为table_wraper_table中,如下所示:

 通过以上分析,似乎已经胜利在望,但通过查询源代码,发现网址请求到的页面中,table是空的,并没有我们想要的股票数据内容,如下所示:

 通过以上步骤的排查,说明所见即所得,有时也不一定通用。既然页面不是一次请求获取的,那么就可能是通过ajax的方式异步获取的,需要进一步排查Network,即网络请求信息。继续排查跟踪网络请求信息,发现股票信息是通过以下接口获取的,返回的是json格式的字符串,我们获取对应内容后,只需要解析json即可获取相应的数据,如下所示:

 通过分析接口请求的url,发现对应的页码和每页请求条数,即可以变化的量,对于多页,则轮询并替换即可,如下所示:

创建爬虫

在之前stockstar项目的基础上,再次创建一个爬虫,如下所示:

Scrapy爬虫开发

通过命令行创建项目后,基本Scrapy爬虫框架已经形成,剩下的就是业务代码填充。

定义爬取内容

定义需要爬取哪些字段内容,如下所示:

 1 # Define here the models for your scraped items
 2 #
 3  See documentation in:
 4  https://docs.scrapy.org/en/latest/topics/items.html
 5 
 6 import scrapy
 7 
 8 
 9 class StockstarItem(scrapy.Item):
10     """
11     定义需要爬取的字段名称
12     13      define the fields for your item here like:
14      name = scrapy.Field()
15     stock_type = scrapy.Field()   股票类型
16     stock_id = scrapy.Field()   股票ID
17     stock_name = scrapy.Field()   股票名称
18     stock_price = scrapy.Field()   股票价格
19     stock_chg = scrapy.Field()    涨跌幅

定制业务逻辑

Scrapy的爬虫结构是固定的,定义一个类,继承自scrapy.Spider,类中定义属性【爬虫名称,域名,起始url】,重写父类方法【parse】,根据需要爬取的页面逻辑不同,在parse中定制不同的爬虫代码,如下所示:

 EastmoneySpider(scrapy.Spider):
 2     name = 'eastmoney'
 3     allowed_domains = [eastmoney.com/']
 4     start_urls = [
 5         http://**.****.********.com/api/qt/clist/get?cb=jQuery112405581218321729968_1630076590847&pn=1&pz=20&po=1&np=1&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f136,f115,f152&_=1630076590848 6     index = 1
 8     def parse(self,response):
 9         item = StockstarItem()
10         text = response.text
11         text = text[text.find((') + 1:]   去掉小括号前面的
12         text = text[0:-2]   去掉小括号后面的
13          print(text)  #  此处用于打印处理好的原始字符
14         obj = json.loads(text)
15         print(********************本次抓取第' + str(self.index) + 页股票********************)
16         data = obj[data17         total = data[total18         diffs = data[diff19         total_page = total / 20
20         if total % 20 > 0:
21             total_page += 1   如果求模大于0,则也码加1
22         for diff in diffs:
23             item[stock_type'] = 沪深A股24             item[stock_id'] = str(diff[f12])
25             item[stock_namef1426             item[stock_pricef227             item[stock_chgf3']) + %28             yield item
29          当第一页解析完,进行下一页解析
30         self.index += 1
31         总页码:' + str(total_page))
32         if self.index <= total_page:
33             next_page = http://**.****.******.com/api/qt/clist/get?cb=jQuery112405581218321729968_1630076590847&pn= str(
34                 self.index) + &pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fields=f1,f11,f62,f128,1)">35             yield scrapy.Request(next_page,callback=self.parse,dont_filter=True)
36         else:
37             当前是最后一页')

注意:为了不泄露目标网站,爬取地址做了模糊处理

数据处理

在Pipeline中,对抓取的数据进行处理,本例为简便,在控制进行输出,如下所示:

 StockstarPipeline:
 2      process_item(self,item,spider):
 3         str_item = 股票类型:'+item[']+    股票代码:    股票名称:    股票价格:    股票涨跌幅: 4         print(str_item)   打印
 5         self.save_data(str_item)   保存
 6         return save_data(self,str_item):
 9         10         保存数据
        :param str_item: 保存的内容文件
12         :return:
13         14         with open(stocks.txt',autf-8) as f:
15             f.write(str_item+\n')

注意:在对item进行赋值时,只能通过item['key']=value的方式进行赋值,不可以通过item.key=value的方式赋值。

Scrapy运行

因scrapy是各个独立的页面,只能通过终端命令行的方式运行,格式为:scrapy crawl 爬虫名称,如下所示:

1 scrapy crawl eastmoney

结果展示

本文爬取的内容,存储在文本文件中,可以用于后续的进一步分析,如下所示:

 

 备注

以上就是Scrapy爬取异步内容,及多页爬取的简单介绍,希望能够抛转引玉,共同学习。

夏日南亭怀辛大

【作者】孟浩然 【朝代】唐
 
山光忽西落,池月渐东上。
散发乘夕凉,开轩卧闲敞。
荷风送香气,竹露滴清响。
欲取鸣琴弹,恨无知音赏。
感此怀故人,中宵劳梦想。

原文地址:https://www.cnblogs.com/hsiang

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Python中的函数(二) 在上一篇文章中提到了Python中函数的定义和使用,在这篇文章里我们来讨论下关于函数的一些更深的话题。在学习C语言函数的时候,遇到的问题主要有形参实参的区别、参数的传递和改变、变量的作用域。同样在Python中,关于对函数的理解和使用也存在这些问题。下面来逐一讲解。一.函
Python中的字符串 可能大多数人在学习C语言的时候,最先接触的数据类型就是字符串,因为大多教程都是以&quot;Hello world&quot;这个程序作为入门程序,这个程序中要打印的&quot;Hello world&quot;就是字符串。如果你做过自然语言处理方面的研究,并且用Python
Python 面向对象编程(一) 虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程。下面就来了解一下如何在Python中进行对象编程。一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法。 类是对现实世界中一些事物的封装,
Python面向对象编程(二) 在前面一篇文章中谈到了类的基本定义和使用方法,这只体现了面向对象编程的三大特点之一:封装。下面就来了解一下另外两大特征:继承和多态。 在Python中,如果需要的话,可以让一个类去继承一个类,被继承的类称为父类或者超类、也可以称作基类,继承的类称为子类。并且Pytho
Python中的函数(一) 接触过C语言的朋友对函数这个词肯定非常熟悉,无论在哪门编程语言当中,函数(当然在某些语言里称作方法,意义是相同的)都扮演着至关重要的角色。今天就来了解一下Python中的函数用法。一.函数的定义 在某些编程语言当中,函数声明和函数定义是区分开的(在这些编程语言当中函数声明
在windows下如何快速搭建web.py开发框架 用Python进行web开发的话有很多框架供选择,比如最出名的Django,tornado等,除了这些框架之外,有一个轻量级的框架使用起来也是非常方便和顺手,就是web.py。它由一名黑客所创建,但是不幸的是这位创建者于2013年自杀了。据说现在由
将Sublime Text 2搭建成一个好用的IDE 说起编辑器,可能大部分人要推荐的是Vim和Emacs,本人用过Vim,功能确实强大,但是不是很习惯,之前一直有朋友推荐SUblime Text 2这款编辑器,然后这段时间就试了一下,就深深地喜欢上这款编辑器了...
Python中的模块 有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句&quot;#include&lt;math.h&gt;&quot;引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些内置的函数,该怎么处理呢?在Python中
Python的基础语法 在对Python有了基础的认识之后,下面来了解一下Python的基础语法,看看它和C语言、java之间的基础语法差异。一.变量、表达式和语句 Python中的语句也称作命令,比如print &quot;hello python&quot;这就是一条语句。 表达式,顾名思义,是
Eclipse+PyDevʽjango+Mysql搭建Python web开发环境 Python的web框架有很多,目前主流的有Django、Tornado、Web.py等,最流行的要属Django了,也是被大家最看好的框架之一。下面就来讲讲如何搭建Django的开发环境。一.准备工作 需要下载的
在windows下安装配置Ulipad 今天推荐一款轻便的文本编辑器Ulipad,用来写一些小的Python脚本非常方便。 Ulipad下载地址: https://github.com/limodou/ulipad http://files.cnblogs.com/dolphin0520/u...
Python中的函数(三) 在前面两篇文章中已经探讨了函数的一些相关用法,下面一起来了解一下函数参数类型的问题。在C语言中,调用函数时必须依照函数定义时的参数个数以及类型来传递参数,否则将会发生错误,这个是严格进行规定的。然而在Python中函数参数定义和传递的方式相比而言就灵活多了。一.函数参数的
在Notepad++中搭配Python开发环境 Python在最近几年一度成为最流行的语言之一,不仅仅是因为它简洁明了,更在于它的功能之强大。它不仅能够完成一般脚本语言所能做的事情,还能很方便快捷地进行大规模的项目开发。在学习Python之前我们来看一下Python的历史由来,&quot;Pytho
Python中的条件选择和循环语句 同C语言、Java一样,Python中也存在条件选择和循环语句,其风格和C语言、java的很类似,但是在写法和用法上还是有一些区别。今天就让我们一起来了解一下。一.条件选择语句 Python中条件选择语句的关键字为:if 、elif 、else这三个。其基本形式如
关于raw_input( )和sys.stdin.readline( )的区别 之前一直认为用raw_input( )和sys.stdin.readline( )来获取输入的效果完全相同,但是最近在写程序时有类似这样一段代码:import sysline = sys.stdin.readline()
初识Python 跟学习所有的编程语言一样,首先得了解这门语言的编程风格和最基础的语法。下面就让我们一起来了解一下Python的编程风格。1.逻辑行与物理行 在Python中有逻辑行和物理行这个概念,物理行是指在编辑器中实际看到的一行,逻辑行是指一条Python语句。在Python中提倡一个物理行只
当我们的代码是有访问网络相关的操作时,比如http请求或者访问远程数据库,经常可能会发生一些错误,有些错误可能重新去发送请求就会成功,本文分析常见可能需要重试的场景,并最后给出python代码实现。
1.经典迭代器 2.将Sentence中的__iter__改成生成器函数 改成生成器后用法不变,但更加简洁。 3.惰性实现 当列表比较大,占内存较大时,我们可以采用惰性实现,每次只读取一个元素到内存。 或者使用更简洁的生成器表达式 4.yield from itertools模块含有大量生成器函数可
本文介绍简单介绍socket的常用函数,并以python-kafka中的源码socketpair为例,来讲解python socket的运用
python实践中经常出现编码相关的异常,大多网上找资料而没有理解原理,导致一次次重复错误。本文对常用Unicode、UTF-8、GB2312编码的原理进行介绍,接着介绍了python字符类型unicode和str以及常见编解码错误UnicodeEncodeError和UnicodeDEcodeEr