根据计划,今天接着跟scrapy课程,上篇博文【爬虫计划】Scrapy框架的学习及跟课学习 | csdn_Part 01 认识Scrapy框架学到创建新项目及对于两种命令(全局命令和项目命令)的查看及使用,这部分内容跟着练习一个小的“我爱我家”的网站处理项目,重点在于获取使用的基本方法,尽量预期在今天完成四个小时的视频课,并完成三篇以内的相关博文。
如有必要可进行下一步扩充,在网盘又查了一下应该还有存货。
话不多说先进行这部分的学习,之后再有选择的看。
3.Scrapy框架的学习
这部分 接上篇,先对目标url进行分析,https://hz.5i5j.com/zufang/,放一个思路。
在扫一眼大概流程后,还是需要实践来跟上,比如new一个新项目“myhome51”,这里有个小tip,开头不能用数字。
使用命令成功创建后可以看看项目目录结构,目录下分别对应的文件。
上图为标准下注释,下图为使用编译器Pycharm查看项目目录结构。其中“fang.py”文件是使用
针对几个出现的文件所对应的中间件及关键部件。主要写的是Item/spider/Item管道对爬出来的Item数据进行清理去重。
fang.py也就是爬虫文件可以创建多个,这里先修改fang.py文件中的parse函数中的pass 为 print(response.status),如图
测试一下,在命令行打开,使用两个命令查看一下执行当前修改的文件(别忘了执行前在编译器中保存):
太长了,这里作为两张图去放。
想解析爬到的页面可以在parse函数中修改代码,这里根据视频中老师的演示发现是对于目标网站2018年的采集,网站的改版导致相应的代码无法运行,这里根据现在访问的我爱我家项目进行修改,再次运行【截止2020 0208最后一次能运行,并获取结果】:
# -*- coding: utf-8 -*-
import scrapy
class FangSpider(scrapy.Spider):
name = 'fang'
allowed_domains = ['https://hz.5i5j.com/']
# 开始的url
start_urls = ['http://hz.5i5j.com/zufang//']
def parse(self, response):
# print(response.status)
# pass
hlist = response.css("div.listCon")
for vo in hlist:
print(vo.css("h3.listTit a::text").extract_first())
确实能够把网站上的特定信息爬取下来,由于这里网站的描述不算规范,将一些描述词加入,所以显得不干净。【有个小思路,如果将爬取到的结果进行分词,取出拎包入住、精装等形容词,如有需要进行得分,没有需要将清洗后的小区名字输出。】
这部分就完成了,接着往后走,就不单步完成,直接贴最后代码。关键思路使用注释完成。
第一部分修改根目录下的items.py文件:
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class Myhome51Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 相关变量使用scrapy的field方法获取
title = scrapy.Field()
address = scrapy.Field()
des = scrapy.Field()
click = scrapy.Field()
price = scrapy.Field()
rentWay = scrapy.Field()
# pass
第二部分修改根目录下的fang.py文件,(import方法多试几次,另外可以把根目录设为资源引用文件夹,pycharm编译器使用右键):
# -*- coding: utf-8 -*-
import scrapy
# 由于演示的 from myhome51.items import Myhome51Item 一直报错
# 采用下面这种方式
import myhome51
# import myhome51.items.Myhome51Item
from myhome51.items import Myhome51Item
class FangSpider(scrapy.Spider):
name = 'fang'
allowed_domains = ['https://hz.5i5j.com/']
# 开始的url
start_urls = ['http://hz.5i5j.com/ershoufang/']
# 在爬虫结果返回后的downloader返回给爬虫spidder的response中调用这个函数
def parse(self, response):
# print(response.status)
# pass
hlist = response.css("div.listCon")
for vo in hlist:
# 开始作为测试的结果直接输出
# print(vo.css("h3.listTit a::text").extract_first())
# 修改了items文件后 来设置各信息的抓取规则
item = myhome51.items.Myhome51Item() # 导入问题 所以这样用法
item['title'] = vo.css("h3.listTit a::text").extract_first()
# < p > < i class ="i_02" > < / i > 三墩 < a href="/xiaoqu/100000000005783.html" > 金地广场 < / a > < a href="/zufang/41225899.html#map_box" target="_blank" > < / a > < !-- · 地铁10号线 --> < / p >
item['address'] = vo.re('<i class="i_02"></i>.*?<a href=".*?">(.*?)</a><a href=".*?" target="_blank">')[0]
# 这里演示中出现使用正则表达式的例子 因改版后不符合
# 为了掌握 这里放一个 item['time'] = vo.re('<span>(.*?)开盘</span>')[0]
# <p><i class="i_01"></i>2 室 1 厅 · 65 平米 · 南 · 中楼层/13层 · 中装 · 2017年建</p>
item['des'] = vo.re('<i class="i_01"></i>(.*?)</p>')[0]
item['click'] = vo.re('<i class="i_03"></i>(.*?)</p>')[0]
# <p class="redC"><strong>3500</strong>元/月</p><p>出租方式:整租</p></div>
# <p class="redC"><strong>(.*?)</strong>元/月</p><p>出租方式:.*?</p></div>
item['price'] = vo.re('<strong>(.*?)</strong>.*?元/月')[0]
item['rentWay'] = vo.re('<p>出租方式:(.*?)</p>')[0]
print(item)
跑出来除了价格以外的都能取到,价格一直提示错误,然后测试几次以后提示状态码403,大概率被拒了。所以转过头了补充博客和视频,希望有所收获。以下是爬取结果的部分截图:
为了将抓取到的数据持久化存储,这里需要对setting文件进行修改:
存储的话,在运行过程中使用 -o 后跟文件类型,格式:
scrapy crawl fang -o fang.[json | xml]
最后再尝试一波发现还是不行,这里私以为是爬的问题,如有了解的帮助解答一下。今天的练习就到这里。
依旧是老话~
刻意练习,每日精进。
补充说明,第二天又开始了对于这部分的测试,因为之前json/xml/csv文件创建成功、写入失败,再次找答案。经过几个测试,在爬虫文件后加了行代码,终于爬出结果,并成功写入csv文件。加上之前对于价格正则的调整,再贴一次能完全爬到特征的代码【截止到20200229 15:09时有效】。
同时,和左边的命令行输出结果对比可以看到,在管道文件中写入的分隔符“+”也起了作用,把爬虫文件代码贴上来,以供参考。多次爬可能会有失败信息,等一段时间就会好。
# -*- coding: utf-8 -*-
import scrapy
# 由于演示的 from myhome51.items import Myhome51Item 一直报错
# 采用下面这种方式
import myhome51
# import myhome51.items.Myhome51Item
from myhome51.items import Myhome51Item
class FangSpider(scrapy.Spider):
name = 'fang'
allowed_domains = ['https://hz.5i5j.com/']
# 开始的url
start_urls = ['https://hz.5i5j.com/zufang/']
# 在爬虫结果返回后的downloader返回给爬虫spidder的response中调用这个函数
def parse(self, response):
# print(response.status)
# pass
hlist = response.css("div.listCon")
for vo in hlist:
# 开始作为测试的结果直接输出
# print(vo.css("h3.listTit a::text").extract_first())
# 修改了items文件后 来设置各信息的抓取规则
item = myhome51.items.Myhome51Item() # 导入问题 所以这样用法
item['title'] = vo.css("h3.listTit a::text").extract_first()
item['address'] = vo.re('<i class="i_02"></i>.*?<a href=".*?">(.*?)</a><a href=".*?" target="_blank">')[0]
# 这里演示中出现使用正则表达式的例子 因改版后不符合
# 为了掌握 这里放一个 item['time'] = vo.re('<span>(.*?)开盘</span>')[0]
item['des'] = vo.re('<i class="i_01"></i>(.*?)</p>')[0]
item['click'] = vo.re('<i class="i_03"></i>(.*?)</p>')[0]
# <p class="redC"><strong>2980</strong>
# 元/月
# </p>
# <p>出租方式:整租</p>
item['price'] = vo.re('<p class="redC"><strong>(.*?)</strong>')[0]
item['rentWay'] = vo.re('<p>出租方式:(.*?)</p>')[0]
print(item)
# 最开始一直没办法写入文件,创建动作成功了,文件内为空,使用这行代码将数据送入管道
yield item
使用yield item在命令行中出现的是DEBUG信息,这部分结束。