点击上方「蓝字」关注 testing
01
引言
hello,好久不见!最近接了几个兼职,然后都涉及到了爬虫,在这里简单介绍下Scrapy框架的使用。
那么,爬虫除了Scrapy框架外,还有pyspider框架,当然了,也可以利用基础去实现这些框架的功能。为什么这里单单就介绍Scrapy框架呢?
我们来说说pyspider框架。我们可以利用pyspider框架可以快速的完成爬虫的编写。除了快捷性外,pyspider也有一些缺点,比如可配置化程度不高,异常处理能力有限等。它对于一些反爬程度非常强的网站爬取显得力不从心。
而Scrapy框架的功能是非常强大的,爬取效率高,扩展组件多。可配置和可扩展程度相对来说是非常高的,Scrapy几乎可以应对所有反爬网站,它是目前 Python使用最广泛的爬虫框架。
说到这里,就知道testing为什么单独介绍Scrapy框架了吧!对pyspider有兴趣的也可以自己百度了解下。下面进入正题~
02
Scrapy介绍
Scrapy是基于Twisted的异步处理框架,是纯Python实现的爬虫框架,Scrapy的架构清晰,模块之间的耦合程度低,可扩展性极强。可以灵活完成各种需求, 我们只需要定制开发几个模块就可以轻松实现一个爬虫。
下面我们来看看Scrapy框架的架构图
Engine引擎:处理整个系统的数据流处理、触发事务,是整个框架的核心。
Item:项它定义了爬取结果的数据结构,爬取的数据会被赋值成该Item对象。
Scheduler调度器:接受引擎发过来的请求并将其加入队列中,在引擎再次请求的时候将请求提供给引擎。
Downloader下载器:下载网页内容,并将网页内容返回给蜘蛛。
Spiders蜘蛛:其内定义了爬取的逻辑和网页的解析规则 ,它主要负责解析响应并生成提取结果和新的请求。
Item Pipeline项目管道:负责处理由蜘蛛从网页中抽取的项目,它的主要任务是清洗、验证和存储数据。
Downloader Middlewares下载器中间件:位于引擎和下载器之间的钩子框架,主要处理引擎与下载器之间的请求及响应。
Spider Middlewares蜘蛛中间件:位于引擎和蜘蛛 之间的钩子框架,主要处理蜘蛛输入的响应和输出的结果及新的请求。
我们可以根据上面图来看看Scrapy的详细数据流走向。
1、爬虫引擎获得初始请求开始抓取。
2、爬虫引擎开始请求调度程序,并准备对下一次的请求进行抓取。
3、爬虫调度器返回下一个请求给爬虫引擎。
4、引擎请求发送到下载器,通过下载中间件下载网络数据。
5、一旦下载器完成页面下载,将下载结果返回给爬虫引擎。
6、引擎将下载器的响应通过中间件返回给爬虫进行处理。
7、爬虫处理响应,并通过中间件返回处理后的items,以及新的请求给引擎。
8、引擎发送处理后的items到项目管道,然后把处理结果返回给调度器,调度器计划处理下一个请求抓取。
9、重复该过程(继续步骤1),直到爬取完所有的url请求。
通过多个组件的相互协作、不同组件完成工作的不同、组件对异步处理的支持, Scrapy最大限度地利用了网络带宽,大大提高了数据爬取和处理的效率。
03
Scrapy入门
创建项目及Spider
接下来,以某家五和地铁站附近租房房源为例说明Scrapy的使用。
Scrapy框架是通过命令行来创建项目的,代码编写还是需要IDE。下面,我们来创建下项目
scrapy startproject scrapy_test # scrapy-test为项目名D:\Python\WorkingInterval>scrapy startproject scrapy_testNew Scrapy project 'scrapy_test', using template directory 'd:\python\python37\lib\site-packages\scrapy\templates\project', created in: D:\Python\WorkingInterval\scrapy_testYou can start your first spider with: cd scrapy_test scrapy genspider example example.com
创建项目后用IDE打开项目,我们发现Scrapy的项目结构是这样的,下面介绍下Scrapy的项目结构:
scrapy.cfg:Scrapy项目的配置文件,其内定义了项目的配置文件路径、部署相关信息等内容。
items.py:定义 Item 数据结构,所有的Item的定义都可以放这里。
pipelines.py:定义了Item Pipeline的实现,所有的Item Pipeline的实现都可以放这里。
settings.py:定义项目的全局配置。
middlewares.py:定义Spider Middlewares和Downloader Middlewares的实现。
spiders:包含一个个Spider的实现,每个Spider都有一个文件。
好了,接下来创建项目完了后需要创建Spider。Spider是自己定义的类,Scrapy用它来从网页里抓取内容,并解析抓取的结果。不过这个类必须继承Scrapy提供的Spider类scrapy.Spider,还要定义Spider 的名称和起始请求,以及怎样处理爬取后的结果的方法。
当然了,也可以使用命令行创建一个Spider。比如要生成testing这个Spider,可以执行下面命令:
cd scrapy_testscrapy genspider testing(Spider名) sz.lianjia.com(域名) #创建一个Spid
创建成功后我们看看spiders中有什么变化,spiders中多了一个spider(testing.py)。它就是刚刚创建的 Spider。内容如下所示:
# -*- coding: utf-8 -*-import scrapyclass TestingSpider(scrapy.Spider): name = 'testing' allowed_domains = ['sz.lianjia.com'] start_urls = ['http://sz.lianjia.com/'] def parse(self, response): pass
我们发现,在Spider(testing.py)文件中有3个属性及1个方法。那么,这3个属性及1个方法表示什么呢?
name:每个项目唯一的名字,用来区分不同的Spiderallowed_domains:允许爬取的域名,如果初始或后续的请求链接不是这个域名下的,则请求链接会被过滤start_urls:包含了Spider在启动时爬取的url列表,初始请求是由它来定义的parse:Spider的一个方法,默认情况下,被调用时 start_urls 里面的链接构成的请求完成下载执行后,返回的响应就会作为唯一的参数传递给这个函数 该方法负责解析返回的响应、提取数据或者进一步生成要处理的请求。
其实,这个Spider(testing.py)我们现在就可以运行了,我们可以通过scrapy crawl Spider_name去运行一个Spider。我们来看看效果:
# Spider代码# -*- coding: utf-8 -*-import scrapyclass TestingSpider(scrapy.Spider): name = 'testing' allowed_domains = ['sz.lianjia.com'] start_urls = ['https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/'] def parse(self, response): print(response.text)
scrapy crawl testing # 运行Spider,testing为Spider
# 结果,只截取了部分2020-10-08 21:28:52 [scrapy.utils.log] INFO: Scrapy 2.3.0 started (bot: scrapy_test)2020-10-08 21:28:52 [scrapy.utils.log] INFO: Versions: lxml 4.5.2.0, libxml2 2.9.5, cssselect 1.1.0, parsel 1.6.0, w3lib 1.22.0, Twisted 20.3.0, Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)], pyOpenSSL 19.1.0 (OpenSSL 1.1.1h 22 Sep 2020), cryptography 3.1.1, Platform Windows-10-10.0.19041-SP02020-10-08 21:28:52 [scrapy.utils.log] DEBUG: Using reactor: twisted.internet.selectreactor.SelectReactor2020-10-08 21:28:52 [scrapy.crawler] INFO: Overridden settings:{'BOT_NAME': 'scrapy_test', 'NEWSPIDER_MODULE': 'scrapy_test.spiders', 'ROBOTSTXT_OBEY': True, 'SPIDER_MODULES': ['scrapy_test.spiders']}2020-10-08 21:28:52 [scrapy.extensions.telnet] INFO: Telnet Password: 503fe683dbe0c5282020-10-08 21:28:52 [scrapy.middleware] INFO: Enabled extensions:['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.logstats.LogStats']2020-10-08 21:28:52 [scrapy.middleware] INFO: Enabled downloader middlewares:['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats']2020-10-08 21:28:52 [scrapy.middleware] INFO: Enabled spider middlewares:['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware']2020-10-08 21:28:52 [scrapy.middleware] INFO: Enabled item pipelines:[]2020-10-08 21:28:52 [scrapy.core.engine] INFO: Spider opened2020-10-08 21:28:52 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)2020-10-08 21:28:52 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:60232020-10-08 21:28:53 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None)2020-10-08 21:28:53 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None) 深圳租房信息_深圳出租房源|房屋出租价格【深圳贝壳租房】title>
我们可以看到上面是把整个网页都爬下来了。那么,我们怎么爬我想要爬的呢?爬下来之后我又该怎么保存呢?接下来介绍下Item及怎么解析response。
Item
Item 是保存爬取数据的容器,它的使用方法和字典类似;不过,相比字典, Item 多了额外的保护机制,可以避免拼写错误或者定义字段错误。
创建 Item需要继承scrapy.Item 类,并且定义类型为scrapy.Field的字段。我们来观察目标网站,我们可以获取到到内容有标题、标签、图片、价格,分别定义为:title、label、picture、price。
定义Item ,此时将items.py修改如下:
# -*- coding: utf-8 -*-# Define here the models for your scraped items## See documentation in:# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass ScrapyTestItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() # 标题 label = scrapy.Field() # 标签 picture = scrapy.Field() # 图片 price = scrapy.Field() # 价格
接下来爬取时我们会使用到这个 Item
response解析
在前面Spider提到过,Spider(testing.py)文件中有一个parse方法。方法中默认有一个resposne的参数。resposne就是start_urls列表里面的链接爬取后的结果。所以在parse方法中,我们可以直接对response变量包含的内容进行解析,我们可以浏览请求结果的网页源代码及进一步解析源代码内容,拿到我们想要的数据。
那么,我们现在来看看我们需要提取的内容,也就是html文件源码。F12打开开发者模式进行元素定位,发现房源列表都在下面这个标签下:
class="content w1150" id="content"># 接下来我们就可以进入这个标签下,然后提取到
class="content__list">节点下的每个房源的title、label、picture、pric
那么,具体怎么提呢?我们可以选择使用CSS或者Xpath提取,具体如下:
# -*- coding: utf-8 -*-import scrapyclass TestingSpider(scrapy.Spider): name = 'testing' allowed_domains = ['sz.lianjia.com'] start_urls = ['https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/'] def parse(self, response): picture_url = 'https://sz.lianjia.com' for contents in response.css('.content.w1150'): for content_list in contents.css('.content__list'): for content in content_list.css('.content__list--item'): print(content.css('.content__list--item--aside::attr(title)').extract_first()) print(picture_url + str(content.css('.content__list--item--aside::attr(href)').extract_first())) for label_list in content.css('.content__list--item--main'): print(label_list.css('.content__list--item--des a::text').extract_first()) print(label_list.css('.content__list--item-price em::text').extract_first())
这里利用了css选择器选取所有的contents然后依次往下循环,最后拿到房源列表。拿到房源列表后在取对应的字段值。其实和下面代码一样直接拿到房源列表也是可以的,我这里采用先取最外层元素的方式是为了更任意理解。
# -*- coding: utf-8 -*-import scrapyclass TestingSpider(scrapy.Spider): name = 'testing' allowed_domains = ['sz.lianjia.com'] start_urls = ['https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/'] def parse(self, response): picture_url = 'https://sz.lianjia.com' # 获取content__list--item节点下的全部标签,返回scrapy.selector.unified.Selector类型 for content in content_list.css('.content__list--item'): # 获取content__list--item--aside中的title属性。::后面是方法,属性是想获取的页面属性key,如title、href等 # content.css('.content__list--item--aside::attr(title)')返回的是一个列表,所以还需要extract_first()方法 # 获取第一个元素,如果需要获取所有标签可使用extract()方法 print(content.css('.content__list--item--aside::attr(title)').extract_first()) print(picture_url + str(content.css('.content__list--item--aside::attr(href)').extract_first())) for label_list in content.css('.content__list--item--main'): # 获取content__list--item--des标签节点下a标签的文本值,如: # 3500 元/月 # label_list.css('.content__list--item-price em::text').extract_first()取出来的值就是3500 print(label_list.css('.content__list--item--des a::text').extract_first()) print(label_list.css('.content__list--item-price em::text').extract_first())
使用item
写好之后我们来运行一下,使用print打印出来发现结果是:
整租·泓瀚苑 2室1厅 东南https://sz.lianjia.com/zufang/SZ2399746901261164544.html龙岗区3500整租·佳华领汇广场king公馆 1室1厅 东南https://sz.lianjia.com/zufang/SZ2493457203546570752.html龙岗区4500整租·绿怡居 1室1厅 北https://sz.lianjia.com/zufang/SZ2529042762431733760.html龙岗区3500整租·祥龙花园 1室1厅 南https://sz.lianjia.com/zufang/SZ2579510967029202944.html龙岗区1600整租·阳明公寓 2室1厅 西北https://sz.lianjia.com/zufang/SZ2546299208399323136.html龙岗区3600整租·万家华庭 1室0厅 南https://sz.lianjia.com/zufang/SZ2601424595965976576.html龙岗区1600整租·德润荣君府 1室1厅 西南https://sz.lianjia.com/zufang/SZ2557857645281419264.html龙岗区3500整租·佳华领汇广场king公馆 1室1厅 复式 东https://sz.lianjia.com/zufang/SZ2565981889160814592.html龙岗区4200# 上面结果只截取了一部分
上文定义了 Item ,接下来就要使用它了。Item 可以理解为一个字典,我们在声明时需要实例化。然后用刚刚解析出来的数据赋给对应item的每一个字段,然后yield返回即可。代码如下:
# -*- coding: utf-8 -*-import scrapyfrom scrapy_test.items import ScrapyTestItemclass TestingSpider(scrapy.Spider): name = 'testing' allowed_domains = ['sz.lianjia.com'] start_urls = ['https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/'] def parse(self, response): picture_url = 'https://sz.lianjia.com' for contents in response.css('.content.w1150'): for content_list in contents.css('.content__list'): # 获取content__list--item节点下的全部标签,返回scrapy.selector.unified.Selector类型 for content in content_list.css('.content__list--item'): item = ScrapyTestItem() # 获取content__list--item--aside中的title属性。::后面是方法,属性是想获取的页面属性key,如title、href等 # content.css('.content__list--item--aside::attr(title)')返回的是一个列表,所以还需要extract_first()方法 # 获取第一个元素,如果需要获取所有标签可使用extract()方法 item['title'] = content.css('.content__list--item--aside::attr(title)').extract_first() item['picture'] = picture_url + str(content.css('.content__list--item--aside::attr(href)').extract_first()) for label_list in content.css('.content__list--item--main'): # 获取content__list--item--des标签节点下a标签的文本值,如: # 3500 元/月 # label_list.css('.content__list--item-price em::text').extract_first()取出来的值就是3500 item['label'] = label_list.css('.content__list--item--des a::text').extract_first() item['price'] = label_list.css('.content__list--item-price em::text').extract_first()
这样item就封装完成了。那么,我们来看看结果。
2020-10-11 13:15:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2272373282206384128.html', 'price': '2160', 'title': '合租·信义嘉御山 5居室 东卧'}2020-10-11 13:15:48 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2203357333265063936.html', 'price': '1530', 'title': '合租·富豪花园 3居室 南卧'}
在爬取网页的时候肯定不止一页内容,肯定有很多页内容。那么,我们怎么爬取下一页内容呢?下面我们说一说scrapy的Request方法。
scrapy.Request方法
完整代码:
# -*- coding: utf-8 -*-import scrapyfrom scrapy_test.items import ScrapyTestItemclass TestingSpider(scrapy.Spider): name = 'testing' allowed_domains = ['sz.lianjia.com'] start_urls = ['https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/'] def parse(self, response): picture_url = 'https://sz.lianjia.com' for contents in response.css('.content.w1150'): for content_list in contents.css('.content__list'): # 获取content__list--item节点下的全部标签,返回scrapy.selector.unified.Selector类型 for content in content_list.css('.content__list--item'): item = ScrapyTestItem() # 获取content__list--item--aside中的title属性。::后面是方法,属性是想获取的页面属性key,如title、href等 # content.css('.content__list--item--aside::attr(title)')返回的是一个列表,所以还需要extract_first()方法 # 获取第一个元素,如果需要获取所有标签可使用extract()方法 item['title'] = content.css('.content__list--item--aside::attr(title)').extract_first() item['picture'] = picture_url + str(content.css('.content__list--item--aside::attr(href)').extract_first()) for label_list in content.css('.content__list--item--main'): # 获取content__list--item--des标签节点下a标签的文本值,如: # 3500 元/月 # label_list.css('.content__list--item-price em::text').extract_first()取出来的值就是3500 item['label'] = label_list.css('.content__list--item--des a::text').extract_first() item['price'] = label_list.css('.content__list--item-price em::text').extract_first() yield item url = response.css('.content__pg .next::attr(href)').extract_first() url = response.urljoin(url) # scrapy.Request有二个参数,通过 url callback 构造一个新的请求,callback表示回调函数,这里还是使用 parse() # 方法。当运行yield scrapy.Request(url=url, callback=self.parse)时,响应会重新经过parse方法处理,得 # 到第二页的解析结果,然后爬取下一页的数据。这样脚本就进入了一个循环,会爬到最后一页才结束 yield scrapy.Request(url=url, callback=self.parse)
结语
接下来,我们一个简单的爬虫脚本就完成。我们 来运行一下看看
2020-10-11 13:22:47 [scrapy.utils.log] INFO: Scrapy 2.3.0 started (bot: scrapy_test)2020-10-11 13:22:47 [scrapy.utils.log] INFO: Versions: lxml 4.5.2.0, libxml2 2.9.5, cssselect 1.1.0, parsel 1.6.0, w3lib 1.22.0, Twisted 20.3.0, Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)], pyOpenSSL 19.1.0 (OpenSSL 1.1.1h 22 Sep 2020), cryptography 3.1.1, Platform Windows-10-10.0.19041-SP02020-10-11 13:22:47 [scrapy.utils.log] DEBUG: Using reactor: twisted.internet.selectreactor.SelectReactor2020-10-11 13:22:47 [scrapy.crawler] INFO: Overridden settings:{
'BOT_NAME': 'scrapy_test', 'NEWSPIDER_MODULE': 'scrapy_test.spiders', 'ROBOTSTXT_OBEY': True, 'SPIDER_MODULES': ['scrapy_test.spiders']}2020-10-11 13:22:47 [scrapy.extensions.telnet] INFO: Telnet Password: 4562180fedffa7842020-10-11 13:22:47 [scrapy.middleware] INFO: Enabled extensions:['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.logstats.LogStats']2020-10-11 13:22:47 [scrapy.middleware] INFO: Enabled downloader middlewares:['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats']2020-10-11 13:22:47 [scrapy.middleware] INFO: Enabled spider middlewares:['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware']2020-10-11 13:22:47 [scrapy.middleware] INFO: Enabled item pipelines:[]2020-10-11 13:22:47 [scrapy.core.engine] INFO: Spider opened2020-10-11 13:22:47 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)2020-10-11 13:22:47 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:60232020-10-11 13:22:48 [scrapy.core.engine] DEBUG: Crawled (200) //sz.lianjia.com/robots.txt> (referer: None)2020-10-11 13:22:48 [scrapy.core.engine] DEBUG: Crawled (200) //sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/> (referer: None)2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2399746901261164544.html', 'price': '3500', 'title': '整租·泓瀚苑 2室1厅 东南'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2558567086729740288.html', 'price': '2650', 'title': '整租·星窝青年创享社区(五和店) 1室1厅 东/东南/南'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2529042762431733760.html', 'price': '3500', 'title': '整租·绿怡居 1室1厅 北'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2557769429706883072.html', 'price': '2150', 'title': '整租·星窝青年创享社区(五和店) 1室1厅 东'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2546299208399323136.html', 'price': '3600', 'title': '整租·阳明公寓 2室1厅 西北'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2558648762940014592.html', 'price': '1980', 'title': '整租·星窝青年创享社区(五和店) 1室1厅 南'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2557857645281419264.html', 'price': '3500', 'title': '整租·德润荣君府 1室1厅 西南'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2565981889160814592.html', 'price': '4200', 'title': '整租·佳华领汇广场king公馆 1室1厅 复式 东'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2357150381735690240.html', 'price': '4300', 'title': '整租·佳华领汇广场king公馆 1室1厅 东'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2502001268382236672.html', 'price': '4800', 'title': '整租·润创兴时代公寓 2室1厅 南'}2020-10-11 13:22:49 [scrapy.core.scraper] DEBUG: Scraped from <200 https://sz.lianjia.com/zufang/rs%E4%BA%94%E5%92%8C/>{
'label': '龙岗区', 'picture': 'https://sz.lianjia.com/zufang/SZ2561359607196811264.html', 'price': '7000', 'title': '整租·万科四季花城六期 3室2厅 南'}
好了,因为时间问题,关于scrapy框架的内容本篇文章就说到这里。下期在说爬取后数据的保存及scrapy框架各组件的一个使用,886~
04
番外-往期推荐
性能测试系列:聊一聊性能测试、聊一聊性能测试指标一、聊一聊性能测试指标二、聊一聊性能测试计划、聊一聊性能测试方案
grafana系列:基于Docker搭建Grafana监控数据库资源、基于Docker搭建Grafana监控Linux服务器资源
docker系列:docker介绍、docker入门及使用、docker深入一
2T免费学习资源:2T免费各领域学习资源