1. scrapy运行过程概述

scrapy是一个基于python的网络爬虫框架,它读取对指定域名的网页request请求,截取对应域名的返回体,开发者可以编写解析函数,从返回体中抓取自己需要的数据,并对数据进行清洗处理或存入数据库。

scrapy工程的爬虫全部存放于工程二级目录下的scrapy文件夹中,使用genspider命令可以构建新的爬虫脚本,使用crawl命令可以使指定爬虫脚本运行。下面简述scrapy爬虫代码的运行过程。

实际上,scrapy有一个被提前定义好的方法start_requests(self)。在没有被重构的情况下,该方法会读取start_urls列表中的url字符串,默认使用get请求方式访问这些url,并默认回调解析函数parse。parse函数以请求得到的返回体response为参数,进行对应的解析数据操作。采用genspider命令生成的scrapy爬虫初始状态如下:

2. scrapy的使用技巧和注意事项

2.1 对多个数据源进行不同的解析处理

显然,start_urls方法和parse方法都是可以被重构的。重构parse方法,就可以更改对网页返回体的处理方式。解析函数并不是唯一的,可以自行定义多个解析函数,也并不是必须命名为parse,重构start_requests函数就能指定使用哪个函数对数据进行处理,实例如下:

如图所示,重构start_requests方法后,对于带有baidu字符的url,callback指向第一个解析函数parse_baidu,否则指向第二个解析函数parse_jd,也就是说,start_urls中定义的两个url,会在爬虫执行的过程中经过不同的处理方式,这就是对多个不同的数据源采用不同解析方式的实现方法。

2.2 数据元素的定位

找到正确的网页元素位置是爬虫获取数据的关键。对于结构单一的静态网页,只需要采用devtools(快捷键F12)自带的元素检查功能,就能定位到元素所在的位置,根据其采用的网页设计样式,使用scrapy自带的selector进行筛选,常用的筛选器有xpath和css,这是scrapy爬虫曾经常用的传统方法。

但实际操作中,并非所有网页元素都可以通过元素检查功能进行正确定位,一些错误的理解会导致数据无法真正的定位。下面举一个例子:

如图所见,如果使用devtools的元素检查功能定位“总计费用”字段的80.00数值,可以发现,数值80.00被放在了标签为“em”的网页样式中。如果单纯地认为数据已经被正确定位到html中的某个标签下,那么就大错特错了,我们打开网页源码,查找一下80.00字符串:

可以看到,80.00在网页源码中并不存在。

这是为什么呢?实际上,元素检查功能会将静态页面下的网页版式和所有动态生成的数据展示为一个“页面”。这个页面上的源码实际上是多个不同的网页格式和网页脚本共同生成的,它的代码并不是真正的网页源码。这种不存在于html网页的数据,实际上就是一种“动态数据”。

时下比较常用的存储动态数据的方式,一般是通过javascript脚本生成,或使用ajax异步加载。在已知数据加载类型的前提下,使用devtools的过滤器进行元素检查是更好的方式。

如果数据通过ajax异步加载,则过滤器设置为XHR,如果数据采用javascript脚本直接生成,则过滤器设置为JS。还有一个比较常用的过滤器是DOC,它是用来选择静态页面的。一些数据量较小的网站可能会将页面数据直接写在html中,DOC过滤器主要应对这种小型的网站。

而我们要查找的80.00字段,它实际上是通过ajax异步加载的数据,既然是异步加载的数据,就可以通过异步请求得到,因此,反复点击页面的一些按钮,如果整个页面没有被刷新,只有一部分刷新,那么这些刷新出来的数据就可以通过设置过滤器为XHR找到。

经过查找可以发现,80.00这个数据是一个异步请求的返回体中携带的两个数据20和60的加和,如图所示:

它的返回体是一个json,并不是网页标签包含下的数据,因此处理方式不能使用selector,而是需要引用json库,按包含键值对的字典操作进行处理。而它的url也不是原网页html,而是下图中红框圈出的Request URL:

用户浏览网页时,被加载的网页会自动向其它url中获取数据,因此可以得到来自很多不同的url的数据。但是爬虫不能享受这样的待遇,因此爬虫的撰写者需要额外费一番心思查找数据,依靠反复搜索,甚至需要结合html编码的经验才行。 2.3 scrapy的并发性与程序逻辑

scrapy是并行爬取框架,在默认的情况下不能用来做指定时序的爬虫。

scrapy会瞬间将start_urls列表内的数个url放入爬取队列中,爬取队列最多同时处理8个url的request请求,哪个url的请求最先得到回应,哪个url的parse方法就最先被执行,(多个parse方法不会交叉执行)。在多个url的页面结构相近的前提下,哪个页面最先返回,几乎是随机的。因此,在start_urls中定义的列表顺序某种意义上是无效的。如果一定想要scrapy顺序爬取,该怎么办呢?实际上这是一个并不常见的需求,如下几个思路可以考虑一下:

思路一,可以在settings.py中指定并发上限CONCURRENT_REQUESTS_PER_DOMAIN,默认值为8,如果设置为1,则scrapy变为顺序爬虫,按start_urls列表内各个url的排布顺序爬取,失去并发性。其效果如下图所示:

图一是并发上限为8的情况下,反复多次对5个新闻标题的爬取结果,图二是并发上限为调整为1之后的结果,可以看到,并发上限设置为1时,新闻的多个标题爬取顺序是固定的,和start_urls的列表顺序一致。

这种方法虽然能让爬虫按照程序内的逻辑顺序执行爬取,但会使爬虫的效率降低。首先,scrapy并不擅长单页面的爬取。其次,如果将请求并发数置为1,一旦其中的某个页面由于各种原因被阻塞,则整个爬虫都会受到影响,效率大大降低。另外,settings.py是一个全局设置,更改了settings.py会使整个工程所有的爬虫发生变化。

思路二,可以手动定义多个解析函数,令这些解析函数互相显式调用。这种方法过于笨重,不推荐使用。思路三,引入其他能瞬时发出request请求的库(如requests),在解析函数中进行爬取逻辑设计。这种方法虽然看起来有点“犯规”,但不失为一种很有效的解决方式。只要不破坏scrapy框架本身的结构,进行这样的设计是完全没有问题的。

这些设计思路都是为了解决scrapy按顺序爬取多个数据源的问题,但是这也必然会引发“单通道阻塞”的传统问题。这是一个逻辑问题,与框架结构无关,因此不可避免。需要注意的是,scrapy依然是以多线程并行处理能力见长的爬虫框架,设计爬虫时要尽可能扬长避短。

scrapy 中不同页面的拼接_scrapy使用技巧总结相关推荐

  1. scrapy 中不同页面的拼接_scrapy官方文档提供的常见使用问题

    Scrapy与BeautifulSoup或lxml相比如何? BeautifulSoup和lxml是用于解析HTML和XML的库.Scrapy是一个用于编写Web爬虫的应用程序框架,可以抓取网站并从中 ...

  2. scrapy中集成selenium+浏览器池实现selenium的并发爬取LCSC网站中非结构化表格数据+异步存储进mysql+完整代码

    爬取https://lcsc.com/products/Connectors_365.html这个网址下所有的表格数据. 蓝色的都是要爬取的子页面,要爬取子页面里面的表格数据 ,表格数据如下: 右上角 ...

  3. Scrapy框架的学习(9.Scrapy中的CrawlSpider类的作用以及使用,实现优化的翻页爬虫)

    1.CrawlSpider类通过一些规则(rules),使对于链接(网页)的爬取更具有通用性, 换句话说,CrawlSpider爬虫为通用性的爬虫, 而Spider爬虫更像是为一些特殊网站制定的爬虫. ...

  4. js中定义用字符串拼接起来的变量名的变量

    转载:https://www.cnblogs.com/vlone/p/4602072.html js中定义用字符串拼接起来的变量名的变量 今天在写js的时候碰到了难题,我又一个页面需要生成很多的变量. ...

  5. Scrapy中CrawlSpider

    Scrapy中CrawlSpider 引入 之前的代码中,我们有很大一部分时间在寻找下一页的URL地址或者内容的URL地址上面,这个过程能够更简单一些吗? 思路 1.从response中提取所有的a标 ...

  6. 【python爬虫】在scrapy中利用代理IP(爬取BOSS直聘网)

    同学们好,我又滚回来更新了,这一次我们要爬取的目标是BOSS直聘,BOSS直聘可以说是反爬虫一个很好的例子了,主要在于如果你访问他的次数过多,他就会出现验证码,要求你通过验证才能继续看,这样还算可以, ...

  7. Scrapy中selenium的应用-----并通过京东图书书籍信息爬取项目进行实操!

    引言------ 在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载(ajax)的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值 ...

  8. scrapy中关于Splash的使用

    为什么要学习Splash? 我们经常使用scrapy框架编写爬虫代码,站在巨人的肩膀上感觉很好,但是一旦遇到网站用JavaScript动态渲染,scrapy就显得有些力不从心了,我们了解的seleni ...

  9. ASP.net 中的页面继承实现和通用页面的工厂模式的实现

    最近用.Net做web项目的时候遇到了一些问题,就是很多的页面的处理一样的,不一样的就是我们写的存储过程不同,为了考虑代码的重复利用和可维护性和可 扩展性,于是写了一个对于单据页面的工厂模式,采用界面 ...

最新文章

  1. 右键新建里面没有word和excel_Windows10系统下如何将Sublime Text3添加到右键快捷菜单?...
  2. Java Json API:Gson使用简单入门
  3. mysql v8 漏洞_mysql'密码安全 - osc_v8gts6gd的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. Keras【Deep Learning With Python】更优模型探索Keras实现CNN
  5. 由键盘下陷引起的奇怪事件
  6. MVC3"不允许启动新事务,因为有其他线程正在该会话中运行"错误解决方法
  7. Centos6.5硬盘故障修复
  8. DataWorks 如何撑起阿里99%的数据开发?
  9. Y2K Accounting Bug(poj2586)
  10. java wait 参数_java中wait()和join()方法的区别是什么
  11. 有没有网上python一对一-使用Python的Tornado框架实现一个一对一聊天的程序
  12. 主题:小菜一碟可以怎样说
  13. Java 强制删除文件或目录
  14. 在企业ceph运维中问题处理解决方案---持续更新
  15. “21 天好习惯”第一期-2 2021牛客暑期多校训练营10 F、Train Wreck
  16. 动态域名ddclient
  17. 2014手游渠道分成比例汇总
  18. dw01均衡电路_电池平衡电路工作原理
  19. 均值不等式中考_中考数学解题技巧方法
  20. HIVE常用参数配置

热门文章

  1. node作为php中转带参数,Nodejs中使用命令行如何进行传参(代码)
  2. 【MySQL原理解析】01. 一条SQL查询语句是如何执行的
  3. 设计模式(二) 模板方法
  4. 私钥公钥学习心得(二)比特币与支付宝
  5. Plugin org.apache.maven.plugins:maven-resources-plugin:2.6
  6. js 获取某年的某天是第几周
  7. 使用Combres 库 ASP.NET 网站优化
  8. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]51.基于ID的加密安全模型,描述IBE方案
  9. [Leetcode][第99题][JAVA][恢复二叉搜索树][中序遍历]
  10. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第51篇]什么是基于ID的加密的安全模型,描述一个IBE方案