200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 爬虫(21)crawlspider讲解古诗文案例补充+小程序社区案例+汽车之家案例+scrapy内置的下

爬虫(21)crawlspider讲解古诗文案例补充+小程序社区案例+汽车之家案例+scrapy内置的下

时间:2022-08-13 05:11:44

相关推荐

爬虫(21)crawlspider讲解古诗文案例补充+小程序社区案例+汽车之家案例+scrapy内置的下

文章目录

第十九章 crawlspider讲解1. 古诗文案例crawlspider1.1 需求1.2 处理1.3 解析2. 小程序社区案例2.1 创建项目2.2 项目配置2.3 解析详情页的数据3. 汽车之家案例(二进制数据爬取)3.1 创建项目3.2 项目配置3.3 定位图片3.4 配置settings3.5 创建开始文件3.6 打开管道3.7 在管道中操作3.8 图片存储路径代码解释3.9 解决报错问题3.10 翻页4. 其他方法爬取图片4.1 在items文件中创建两个字段4.2 导入items文件中的类并在爬虫文件中引用字段4.3 定义自己的管道4.4 完整代码4.4.1 items4.4.2 byd爬虫文件4.4.3 settings4.5 总结

第十九章 crawlspider讲解

今天我们来讲一下crawlspider,我们原则上先掌握最基础的,然后是高级一点的。我们将上一次的古诗文案例用crawspider来处理一下。

1. 古诗文案例crawlspider

创建项目文件:

终端输入:scrapy startproject gs0217 回车

创建crawlspider爬虫项目,语句:

cd 到gs0217文件夹中,终端输入:

scrapy genspider -t crawl 爬虫的名字 域名

然后输入创建项目语句,创建项目:

scrapy genspider -t crawl cgs /

Use "scrapy" to see available commandsD:\work\爬虫\Day21\my_code>scrapy startproject gs0217New Scrapy project 'gs0217', using template directory 'd:\python38\lib\site-packages\scrapy\templates\project', created in:D:\work\爬虫\Day21\my_code\gs0217You can start your first spider with:cd gs0217scrapy genspider example D:\work\爬虫\Day21\my_code>cd gs0217D:\work\爬虫\Day21\my_code\gs0217>scrapy genspider -t crawl cgs /Created spider 'cgs' using template 'crawl' in module:gs0217.spiders.cgsD:\work\爬虫\Day21\my_code\gs0217>

项目创建成功。

我们可以看到crawlspider比scrapyspider,继承的父类发生了变化,导入的模块多了一个。造类里面多了一个Rules:

class CgsSpider(CrawlSpider):name = 'cgs'allowed_domains = ['/']start_urls = ['http:////']rules = (Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),)

Rule定义提取url的规则,LinkExtractor是链接提取器。

allow=r’Items/'这个用来存放url (用到正则表达式)callback='parse_item’是回调函数,处理请求结果。follow=True继续跟进下一页

下面我们通过案例来学习。

1.1 需求

仍然是爬取古诗文的详情。我们需要处理的事情一个是翻页,第二个是爬取译文。

我们需要列表页的url地址

/ # 第一页/default_1.aspx # 第一页/default_2.aspx # 第二页/default_3.aspx # 第三页

另一个是详情页的url地址

/shiwenv_7c14409ca751.aspx # 列表页第一页第一首诗的详情页/shiwenv_0184c31a9e01.aspx # 列表页第一页第二首诗的详情页

我们的顺序是先爬第一页,第一页的第一首,第二首,完了,翻页。。。

1.2 处理

下面注意看代码中的注释:

import scrapyfrom scrapy.linkextractors import LinkExtractorfrom scrapy.spiders import CrawlSpider, Ruleclass CgsSpider(CrawlSpider):name = 'cgs'allowed_domains = ['/']start_urls = ['http:////']rules = (# 负责列表页Rule(LinkExtractor(allow=r'/default_1.aspx'), follow=True),# 负责详情页Rule(LinkExtractor(allow=r'/shiwenv_7c14409ca751.aspx'), callback='parse_item', )) # 详情页不需要翻页,所以去掉follow=True# 列表页不需要数据,只需要翻页,所以不需要回调函数,去掉callback='parse_item'def parse_item(self, response):item = {}#item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()#item['name'] = response.xpath('//div[@id="name"]').get()#item['description'] = response.xpath('//div[@id="description"]').get()return item

下面我们需要把url里面的跟随翻页变化的字符用正则表达式来匹配一下:

# 负责列表页 正则匹配1-10=>\d+Rule(LinkExtractor(allow=r'/default_\d+.aspx'), follow=True),# 负责详情页 正则匹配7c14409ca751 =>\w+Rule(LinkExtractor(allow=r'/shiwenv_\w+.aspx'), callback='parse_item', )

\d可以匹配0-9的数字,+表示至少匹配一次。\W可以匹配大小写字母和数字,+也是至少匹配一次。关于正则表达式的只是请参考我的博客[爬虫(05)正则表达式]。(/m0_46738467/article/details/111587355)

这样我们就将列表页和详情页的url用正则表达式匹配完成。crawlspider只适合简单一些的url,如果url构成比较复杂,就用一般的爬虫方式就可以了。

1.3 解析

我们只需要详情页的译文,我们把第19次博客案例解析译文的代码复制过来就可以了。

def parse_item(self, response):item = {}#item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()#item['name'] = response.xpath('//div[@id="name"]').get()#item['description'] = response.xpath('//div[@id="description"]').get()shang = response.xpath('//div[@class="contyishang"]/p/text()').extract()content_shang = ''.join(shang).strip() # 处理空格及换行符item['detail_content'] = content_shang # 加入itemsprint(item)return item

去settings里面设置一下:

LOG_LEVEL = 'WARNING'ROBOTSTXT_OBEY = FalseDEFAULT_REQUEST_HEADERS = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language': 'en',}

然后我们创建一个start文件:

from scrapy import cmdlinecmdline.execute('scrapy crawl cgs'.split())

我们运行一下:

{'detail_content': '译文富家的子弟不会饿死,清寒的读书人大多贻误自身。韦大人你可以静静地细听,我把自己的往事向你直陈。我在少年时候,早就充当参观王都的来宾。先后读熟万卷书籍,写起文章,下笔敏捷好像有神。我的辞赋能与扬雄匹敌,我的诗篇可跟曹植相近。李邕寻求机会要和我见面,王翰愿意与我结为近邻。自以为是一个超异突出的人,一定很快地身居要津。辅助君王使他在尧舜之上,要使社会风尚变得敦厚朴淳。平生的抱负全部落空,忧愁歌吟,决不是想优游退隐。骑驴行走了十三年,寄食长安度过不少的新春。早上\n\u3000\u3000在杜甫困守长安十年时期所写下的求人援引的诗篇中,要数这一首是最好的了。这类社交性的诗,带有明显的急功求利的企图。常人写来,不是曲意讨好对方,就是有意贬低自己,容易露出阿谀奉承、俯首乞怜的寒酸相。杜甫在这首诗中却能做到不卑不亢,直抒胸臆,吐出长期郁积下来的对封建统治者压制人材的悲愤不平。这是他超出常人之处。\u3000\u3000诗人主要运用了对比和顿挫曲折的表现手法,将胸中郁结的情思,抒写得如泣如诉,真切动人。这首诗应该说是体现杜诗“沉郁顿挫”风格的最早的一篇。\u3000\u3000诗中对比有两种情况,一是以他人和自己对比;一是以自己的今昔对比。先说以他人和自己对比。开端的“纨袴不饿死\n\u3000\u3000此诗作于公元748年(唐玄宗天宝七载),时37岁,居长安。公元747年(天宝六载),唐玄宗下诏天下有一技之长的人入京赴试,命尚书省试,对所有应试之人统统不予录取。杜甫这时应试落第,困守长安,心情落寞,想离京出游,于是就写了这首诗向韦济告别。'}{'detail_content': '译文你挥舞彩袖手捧酒杯殷勤劝酒,回想当年心甘情愿醉倒于颜红。舞姿曼妙,直舞到挂在杨柳树梢照到楼心的一轮明月低沉下去;歌女清歌婉转,直唱到扇底儿风消歇。自从那次离别后,我总是怀念那美好的相逢,多少回梦里与你共同欢聚。今夜里我举起银灯把你细看,唯恐这次相逢又是在梦中。注释鹧鸪天:词牌名,又名“思佳客”,五十五字。 此词黄升《花庵词选》题作《佳会》。彩袖:代指穿彩衣的歌女。玉钟:古时指珍贵的酒杯,是对酒杯的美称。拚(pàn)却:甘愿,不顾惜。却:语气助词。“舞低”二句:歌女舞姿曼妙,直舞到挂在\n\u3000\u3000言为心声,有至情之人,才能有至情之文。一首《鹧鸪天》,写悲感,写欢情,都是那样真挚深沉,撼人肺\u3000\u3000腑,具有强烈的感情色彩。虽然这首词的题材比较窄,不外乎伤离怨别,感悟怀旧,遣情遗恨之作,并没有超出晚唐五代词人的题材范围。小晏写情之作的动人处,在于它的委婉细腻,情深意浓而又风流妩媚,清新俊逸。白居易曰:“感人心者,莫先乎情。”古往今来,脍炙人口的诗词,大抵不仅有情,而且情真。所谓“真字是词骨。情真、景真,所作必佳,且易脱稿。”\u3000\u3000彩袖殷勤捧玉钟,当年拚却醉颜红。舞低杨柳楼新月,歌尽桃花扇低风。\u3000\u3000一个是殷勤地劝酒,一个是拼命地喝,为\n\u3000\u3000此词表现的是一对恋人的“爱情三部曲”:初盟,别离,重逢。全词不过五十几个字,而能造成两种境界,互相补充配合,或实或虚,既有彩色的绚烂,又有声音的谐美,足见作者词艺之高妙。\u3000\u3000“彩袖殷勤”二句,着笔于对方,落墨于自身,既展现了二人初识时的特定情境,也披露了二人一见倾心、愿托终身之际的曲折心态。“彩袖”,说明对方并非与自已门第相配的大家闺秀,而不过是侑酒于华宴的歌女。但此时伊人殷勤捧杯劝饮,却不仅仅是履行侑酒之责,而欲藉此暗通情愫。而心有屡犀的作者又何尝不谙其意?为了报答她于已独钟的深情,他开怀畅饮,不惜一醉。这就写出了感情的双向交流。\u3000\u3000“舞低杨柳”\n\u3000\u3000在仁宗至和二年(公元1055年)就已亡故,则因反对新法,逐渐失势,后于熙宁五年(1072)病故,这使失去了政治上的依靠,生活景况日趋恶化。晏几道采用忆昔思今对比手法写下了许多追溯当年回忆的词作,《鹧鸪天·彩袖殷勤捧玉钟》便是这其中的佼佼之作。\u3000\u3000这首词是晏几道与几个相熟的女子久别重逢之作。这个女子可能是晏几道自撰《小山词序》中所提到的他的朋友沈廉叔、陈君龙家歌女莲、鸿、蘋、云诸人中的一个。晏几道经常在这两位朋友家饮酒听歌,与这个女子是很熟的而且有相当爱惜之情的,离别之后,时常思念,哪知道现在忽然不期而重遇,又惊又喜,所以作了这首词。\u3000\u3000上半阕写当年相聚时欢乐之况,下半阕写今日重逢的惊喜之情。\u3000\u3000“彩袖殷勤捧玉钟,当年拚却醉颜红。舞低杨柳楼心月,歌尽桃花扇底风。”这首词上半阕是说,忆当年,你手捧玉鍾把酒敬,衣着华丽人多情;我举杯痛饮拼一醉,醉意熏熏脸通红。纵情跳舞,直到楼顶月挨着树梢向下行;'}... ... 后面的省略

我书了一下,一共一百个。十页的内容全部爬取了。

2. 小程序社区案例

网址:http://www.wxapp-/portal.php?mod=list&catid=2&page=1

我们爬取标题,作者,时间。

那这个项目是否满足我们的crawlscrapy的条件呢?

我们先看看url

http://www.wxapp-/portal.php?mod=list&catid=2&page=1 # 第一页http://www.wxapp-/portal.php?mod=list&catid=2&page=2 # 第二页http://www.wxapp-/article-6908-1.html # 第一页的第一个详情页http://www.wxapp-/article-6907-1.html # 第一页的第二个详情页http://www.wxapp-/article-6906-1.html # 第一页的第三个详情页

我们看到,url很简单,而且有规律性。

2.1 创建项目

先创建项目:

打开终端Terminal,回到根文件夹:

创建项目:

scrapy startproject sp

创建成功。cd到sp文件夹

D:\work\爬虫\Day21\my_code\sp>

创建crawlscrapy爬虫项目:

scrapy genspider -t crawl wxapp 'wxapp-'

2.2 项目配置

下面我们进行项目配置,列表页和详情页配置:

列表页 去掉callback=‘parse_item’,将url添加进去详情页 去掉,follow=True,将详情页的url添加进去正则匹配随页码变化的字符

rules = (# 列表页Rule(LinkExtractor(allow=r'http://www.wxapp-/portal.php\?mod=list&catid=2&page=\d+'), follow=True),# 详情页Rule(LinkExtractor(allow=r'http://www.wxapp-/article-\d+-1.html'), callback='parse_item'),)

特别注意,在列表页的url里面有一个问好,会被误认为正则匹配,一定要用反斜杠转义。

2.3 解析详情页的数据

item['标题:'] = response.xpath('//h1[@class="ph"]/text()').extract_first() # 标题item['作者:'] = response.xpath('//p[@class="authors"]/a/text()').extract_first() # 作者item['时间:'] = response.xpath('//p[@class="authors"]/span/text()').extract_first() # 时间print(item)

下面我们配置一下settings

LOG_LEVEL = 'WARNING'ROBOTSTXT_OBEY = FalseDEFAULT_REQUEST_HEADERS = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language': 'en',}

创建start文件

from scrapy import cmdlinecmdline.execute('scrapy crawl wxapp'.split())

运行一下:

{'标题:': '微信小程序-bindtap等事件传参 ', '作者:': 'Rolan', '时间:': '-2-9 23:48'}{'标题:': '微信小程序从登录到首页流程梳理 ', '作者:': 'Rolan', '时间:': '-2-8 10:12'}{'标题:': '微信小程序---自动化测试 ', '作者:': 'Rolan', '时间:': '-2-7 09:30'}{'标题:': '我用两周开发了一个图片类应用微信小程序(一) ', '作者:': 'Rolan', '时间:': '-2-8 10:02'}{'标题:': '微信小程序生命周期和页面的生命周期 ', '作者:': 'Rolan', '时间:': '-2-8 10:14'}{'标题:': '【微信小程序】自定义导航栏 ', '作者:': 'Rolan', '时间:': '-2-7 10:33'}{'标题:': '微信小程序支付(服务商模式)解决 ', '作者:': 'Rolan', '时间:': '-2-7 09:44'}{'标题:': '极速入门微信小程序 之 生命周期篇(2-页面) ', '作者:': 'Rolan', '时间:': '-2-8 09:39'}{'标题:': '聊一聊小程序如何换肤 ', '作者:': 'Rolan', '时间:': '-2-8 09:59'}{'标题:': '微信限量红包封面免费送,人人都能领! ', '作者:': 'Rolan', '时间:': '-2-8 18:34'}{'标题:': '小程序搜索功能:云开发搜索和小程序云开发模糊搜索,同时搜索多个字段 ... ', '作者:': 'Rolan', '时间:': '-2-9 09:19'}{'标题:': '微信小程序开发流程与核心概念 ', '作者:': 'Rolan', '时间:': '-2-9 18:31'}{'标题:': '微信小程序swiper实现 句子控app首页滑动卡片 ', '作者:': 'Rolan', '时间:': '-2-9 23:38'}

拿到了数据,不过只拿到13个数据,好像没有翻页。这是因为start_url=‘http://wxapp-/’不是起始url=‘http://www.wxapp-/portal.php?mod=list&catid=2&page=1’。我们把它换成后面的就可以了。

name = 'wxapp'allowed_domains = ['wxapp-']start_urls = ['http://www.wxapp-/portal.php?mod=list&catid=2&page=1']

再运行一下

{'标题:': '微信小程序开发流程与核心概念 ', '作者:': 'Rolan', '时间:': '-2-9 18:31'}{'标题:': '从微信小程序到鸿蒙js开发【05】——tabs组件&每日新闻 ', '作者:': 'Rolan', '时间:': '-2-7 09:16'}{'标题:': '从零开始的微信小程序入门教程(二),初识WXML与WXSS ', '作者:': 'Rolan', '时间:': '-2-5 09:34'}{'标题:': '微信小程序支付(服务商模式)解决 ', '作者:': 'Rolan', '时间:': '-2-7 09:44'}{'标题:': '小程序省市区选择器,对接公司的地址数据 ', '作者:': 'Rolan', '时间:': '-2-7 09:27'}{'标题:': '微信小程序---自动化测试 ', '作者:': 'Rolan', '时间:': '-2-7 09:30'}{'标题:': '【微信小程序】自定义导航栏 ', '作者:': 'Rolan', '时间:': '-2-7 10:33'}... ...{'标题:': '携程小程序初体验 ', '作者:': 'Rolan', '时间:': '-6-12 00:12'}{'标题:': '【微信小程序】编译 .wxss 文件异常解决 ', '作者:': 'Rolan', '时间:': '-6-29 00:21'}{'标题:': '微信小程序瀑布流最好最简单的解决方案 ', '作者:': 'Rolan', '时间:': '-6-11 00:45'}{'标题:': '利用css transition属性实现一个带动画显隐的微信小程序部件 ', '作者:': 'Rolan', '时间:': '-6-12 00:23'}{'标题:': '小程序js文件改变参数并在视图上及时更新 ', '作者:': 'Rolan', '时间:': '-6-12 00:28'}{'标题:': '微信小程序利用canvas生成海报分享图片 ', '作者:': 'Rolan', '时间:': '-6-29 00:12'}{'标题:': '微信小程序专题之setData ', '作者:': 'Rolan', '时间:': '-6-29 00:26'}

数据太多了,就省略了。

3. 汽车之家案例(二进制数据爬取)

下面我们练习爬取一下图片,我们以汽车之家的图片为例。这是比亚迪F3的图片地址,这个图片比较多,共356张图片。

网址:/photolist/series/407/p1/

找url规律:

/photolist/series/407/p1/ # 第一页/photolist/series/407/p2/ # 第二页/photolist/series/407/p3/ # 第三页/photolist/series/407/p4/ # 第四页

我们看到规律很明显。

再看看图片的位置,右键图片,检查:

我们看到图片在li标签里的img标签里,src的值。

3.1 创建项目

创建项目的步骤我们已经很熟悉了:

创建scrapy项目创建spider项目

我们创建一个picture的文件夹作为根目录文件夹。

我们cd到这个文件夹中,创建scrapy项目:

D:\work\爬虫\Day21\my_code\picture>scrapy startproject carhome

回车

D:\work\爬虫\Day21\my_code\picture>scrapy startproject carhomeNew Scrapy project 'carfamily', using template directory 'd:\python38\lib\site-packages\scrapy\templates\project', created in:D:\work\爬虫\Day21\my_code\picture\carhomeYou can start your first spider with:cd carhomescrapy genspider example D:\work\爬虫\Day21\my_code\picture>

先cd到carhome文件夹,然后创建spider项目:

scrapy genspider byd

回车

D:\work\爬虫\Day21\my_code\picture>scrapy startproject carhomeNew Scrapy project 'carhome', using template directory 'd:\python38\lib\site-packages\scrapy\templates\project', created in:D:\work\爬虫\Day21\my_code\picture\carhomeYou can start your first spider with:cd carhomescrapy genspider example D:\work\爬虫\Day21\my_code\picture>cd carhomeD:\work\爬虫\Day21\my_code\picture\carhome>scrapy genspider byd Created spider 'byd' using template 'basic' in module:carhome.spiders.bydD:\work\爬虫\Day21\my_code\picture\carhome>

3.2 项目配置

我们先把start_url改变一下:

import scrapyclass BydSpider(scrapy.Spider):name = 'byd'allowed_domains = ['']start_urls = ['/photolist/series/407/p1/']def parse(self, response):pass

3.3 定位图片

找图片的位置,用xpath定位:

def parse(self, response):ul = response.xpath('//ul[@id="imgList"]/li').extract() # 该页所有的图片for li in ul:pass

这里我们不仅要拿到图片的地址,还要给图片命名,为了避免重复,而我们可以截取图片的部分url作为图片名。

def parse(self, response):ul = response.xpath('//ul[@id="imgList"]/li').extract() # 该页所有的图片for li in ul:item = {} # 定义字典存储数据item['src'] = li.xpath('./a/img/@src').extract_first() # 图片urlprint(item)

3.4 配置settings

配置一下settings:

LOG_LEVEL = 'WARNING'ROBOTSTXT_OBEY = FalseDEFAULT_REQUEST_HEADERS = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language': 'en',}

3.5 创建开始文件

创建start文件

from scrapy import cmdlinecmdline.execute('scrapy crawl byd'.split())

我们先运行一下,看看能否取出数据:

{'src': '///cardfs/product/g24/M01/9A/87/240x180_0_q95_c42_autohomecar__ChwFjl7Ph8yAW5-NAAjdsZ5xYqw557.jpg'}{'src': '///cardfs/product/g2/M0B/7E/8B/240x180_0_q95_c42_autohomecar__ChwFql7Ph8qAS2o5AAkmafu7Hu8233.jpg'}{'src': '///cardfs/product/g2/M02/94/05/240x180_0_q95_c42_autohomecar__ChsEml7Ph8mAcGLTAAkqDMhAt7A709.jpg'}{'src': '///cardfs/product/g2/M01/7E/8B/240x180_0_q95_c42_autohomecar__ChwFql7Ph8eAaabjAAj6QWpEae4702.jpg'}后面的省略

我们随便复制一个到浏览器看看:

浏览器自动补全了网址,但我们在代码里要拼接完整:

item['src'] = 'https:'+li.xpath('./a/img/@src').extract_first() # 图片url

3.6 打开管道

下面我们打开管道,

ITEM_PIPELINES = {'carhome.pipelines.CarhomePipeline': 300,}

将上面的代码激活,然后把数据yield给管道

def parse(self, response):ul = response.xpath('//ul[@id="imgList"]/li') # 该页所有的图片for li in ul:item = {} # 定义字典存储数据item['src'] = 'https:'+li.xpath('./a/img/@src').extract_first() # 图片urlyield item

3.7 在管道中操作

在pipelines里面命名图片,我们截取src的一部分命名图片:

{'src': '/cardfs/product/g2/M01/7E/8B/240x180_0_q95_c42_autohomecar__ChwFql7Ph8eAaabjAAj6QWpEae4702.jpg'}# 我们可以截取后面这部分ChwFql7Ph8eAaabjAAj6QWpEae4702.jpg

下面是图片名的代码:

img_name = item['src'].split('__')[-1]

这个代码的意思是:用双下划线分割src,得到的两个元素返回成的列表中,取倒数第一个元素。

我们创建一个文件夹来存储图片。

下面我们导入一个模块urllib来处理图片存储的问题:

def process_item(self, item, spider):# 获取图片的urlsrc = item['src']# 切割src的一部分作为图片的名字img_name = item['src'].split('__')[-1]# D:\work\爬虫\Day21\my_code\picture\carhome\carhome\imagesfile_path = os.path.join(os.path.dirname(__file__),'images')request.urlretrieve(src,file_path+'/'+img_name)

3.8 图片存储路径代码解释

其中 file_path = os.path.join(os.path.dirname(file),‘images’)这行代码的意思我解释一下。

我们在my_code文件夹中创建一个新的demo文件来演示:

我们看到打印的结果是合成的一个路径。下面的代码看注释和执行结果,你可以明白的。

import os# os.path.join()把目录和文件名合成一个路径print(os.path.join('文件夹','新文件'))# os.path.dirname() 返回文件路径,就是往前退一步# 打印当前文件的路径的方法:print(__file__)# 打印结果:D:/work/爬虫/Day21/my_code/demo.py# 返回当前文件路径的方法print(os.path.dirname(__file__))# 打印结果:D:/work/爬虫/Day21/my_code

那么我们刚才的代码就是给图片创建一个存储路径:

file_path = os.path.join(os.path.dirname(__file__),'images')

就是当前文件往前退一步就是images文件夹所在的文件夹,然后再与’images’合成一个路径。

完整的存储代码是这样子的:

from urllib import requestimport osclass CarhomePipeline:def process_item(self, item, spider):# 获取图片的urlsrc = item['src']# 切割src的一部分作为图片的名字img_name = item['src'].split('__')[-1]# D:\work\爬虫\Day21\my_code\picture\carhome\carhome\imagesfile_path = os.path.join(os.path.dirname(__file__),'images')request.urlretrieve(src,file_path+'/'+img_name)return item

3.9 解决报错问题

运行的时候发现有gif格式的图片不能爬取,所以加入try语句解决问题:

def process_item(self, item, spider):# 获取图片的urlsrc = item['src']# 切割src的一部分作为图片的名字img_name = item['src'].split('__')[-1]# D:\work\爬虫\Day21\my_code\picture\carhome\carhome\imagesfile_path = os.path.join(os.path.dirname(__file__),'images')try:request.urlretrieve(src,file_path+'/'+img_name)print(img_name)except OSError:print('gif类型,跳过')passreturn item

这次运行爬取了30张图片,说明值爬取了一页。

ChwFjl7Ph8yAW5-NAAjdsZ5xYqw557.jpgChwFql7Ph8qAS2o5AAkmafu7Hu8233.jpgChsEml7Ph8mAcGLTAAkqDMhAt7A709.jpgChwFql7Ph8eAaabjAAj6QWpEae4702.jpg......中间的省略......ChsEe15WWuiAY8CrAATAcuXSwT4702.jpgChwFlV7PiJ2AV7ikAAgHgKLCjKM407.jpgChwFjl7PiJ2ADJMmAAf2h7UtNg0272.jpgChwFjl7PiJyAA531AAiaVL_FGsM021.jpggif类型,跳过gif类型,跳过gif类型,跳过gif类型,跳过gif类型,跳过

3.10 翻页

下面在byd文件里加上翻页处理:

import scrapyclass BydSpider(scrapy.Spider):name = 'byd'allowed_domains = ['']first_url = '/photolist/series/407/p{}/'start_urls = [first_url.format(1)]def parse(self, response):ul = response.xpath('//ul[@id="imgList"]/li') # 该页所有的图片for li in ul:item = {} # 定义字典存储数据item['src'] = 'https:'+li.xpath('./a/img/@src').extract_first() # 图片urlyield item# 处理翻页for i in range(2,7):next_url = self.first_url.format(i)yield scrapy.Request(next_url)pass

运行结果

一共爬取了156张图片。

4. 其他方法爬取图片

除了上述一般的爬取方式,也有别的爬取方式,比如选择使用scrapy内置的下载文件的方法:

下载文件的 Files Pipeline

使用Files Pipeline下载文件,按照以下步骤完成:

定义好一个Item,然后在这个item中定义两个属性,分别为file_urls以及files。files_urls是用来存储需要下载的文件的url链接,需要给一个列表当文件下载完成后,会把文件下载的相关信息存储到item的files属性中。如下载路径、下载的url和文件校验码等在配置文件settings.py中配置FILES_STORE,这个配置用来设置文件下载路径启动pipeline:在ITEM_PIPELINES中设置scrapy.piplines.files.FilesPipeline:1

下载图片的 Images Pipeline

使用images pipeline下载文件步骤:定义好一个Item,然后在这个item中定义两个属性,分别为image_urls以及images。image_urls是用来存储需要下载的文件的url链接,需要给一个列表当文件下载完成后,会把文件下载的相关信息存储到item的images属性中。如下载路径、下载的url和图片校验码等在配置文件settings.py中配置IMAGES_STORE,这个配置用来设置文件下载路径启动pipeline:在ITEM_PIPELINES中设置scrapy.pipelines.images.ImagesPipeline:1

下面我们操作一下下载图片的pipeline:

4.1 在items文件中创建两个字段

打开items文件,创建两个字段:

import scrapyclass CarhomeItem(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()image_urls = scrapy.Field() # 存放urlimages = scrapy.Field() # 存放图片pass

4.2 导入items文件中的类并在爬虫文件中引用字段

我们把该文件所在文件夹的上一级文件夹carhome定义为根目录,然后在byd项目文件中导入CarhomeItem类并实例化,把byd文件里面的url键名也改了:

import scrapyfrom carhome.items import CarhomeItem # 导入items文件中的CarhomeItemclass BydSpider(scrapy.Spider):name = 'byd'allowed_domains = ['']first_url = '/photolist/series/407/p{}/'start_urls = [first_url.format(1)]def parse(self, response):ul = response.xpath('//ul[@id="imgList"]/li') # 该页所有的图片for li in ul:item = CarhomeItem() # 实例化类item['image_urls'] = ['https:'+li.xpath('./a/img/@src').extract_first()] # 图片url# 上面的结果一定要以列表的形式返回yield item# 处理翻页for i in range(2,7):next_url = self.first_url.format(i)yield scrapy.Request(next_url)pass

4.3 定义自己的管道

然后打开settings配置它自己的一个pipeline

ITEM_PIPELINES = {# 'carhome.pipelines.CarhomePipeline': 300,'scrapy.pipelines.images.ImagesPipeline':1,}

注意:在byd项目文件中,最后返回的是一个列表。

在settings里添加存储路径:

这个路径是从pipelines文件里复制过来的,但是一定要把路径的名字改成IMAGES_STORE

下面我们运行一下:

IMAGES_STORE = os.path.join(os.path.dirname(__file__),'images')NameError: name 'os' is not defined

报错了,忘记在settings文件里引用os模块,下面引用一下:

import osIMAGES_STORE = os.path.join(os.path.dirname(__file__),'images')# 文件存储路径,这里的IMAGES_STORE名字不能改变

再次运行,没有报错

查看有没有下载下来:

我们打开看看吧

我们看到爬取结果是一样的。所有的存储程序全部内部处理了。包括装图片的文件夹名还有图片名都是内部处理的。

4.4 完整代码

下面把几个文件的完整代码罗列出来。

4.4.1 items

# Define here the models for your scraped items## See documentation in:# /en/latest/topics/items.htmlimport scrapyclass CarhomeItem(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()image_urls = scrapy.Field() # 存放urlimages = scrapy.Field() # 存放图片pass

4.4.2 byd爬虫文件

import scrapyfrom carhome.items import CarhomeItemclass BydSpider(scrapy.Spider):name = 'byd'allowed_domains = ['']first_url = '/photolist/series/407/p{}/'start_urls = [first_url.format(1)]def parse(self, response):ul = response.xpath('//ul[@id="imgList"]/li') # 该页所有的图片for li in ul:# item = {} # 定义字典存储数据item = CarhomeItem() # 实例化类item['image_urls'] = ['https:'+li.xpath('./a/img/@src').extract_first()] # 图片url# 注意:在使用自定义管道的时候,这里返回的是一个列表yield item# 处理翻页for i in range(2,7):next_url = self.first_url.format(i)yield scrapy.Request(next_url)pass

4.4.3 settings

BOT_NAME = 'carhome'SPIDER_MODULES = ['carhome.spiders']NEWSPIDER_MODULE = 'carhome.spiders'LOG_LEVEL = 'WARNING'# Obey robots.txt rulesROBOTSTXT_OBEY = False# Override the default request headers:DEFAULT_REQUEST_HEADERS = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language': 'en',}ITEM_PIPELINES = {# 'carhome.pipelines.CarhomePipeline': 300,'scrapy.pipelines.images.ImagesPipeline':1,}import osIMAGES_STORE = os.path.join(os.path.dirname(__file__),'images')# 文件存储路径,这里的IMAGES_STORE名字不能改变

4.5 总结

总结一下使用images pipeline下载文件步骤:

items文件中定义两个字段:

image_urls = scrapy.Field() # 存放urlimages = scrapy.Field() # 存放图片

并在爬虫文件中引入

settings文件中做了配置

指定了路径

import osIMAGES_STORE = os.path.join(os.path.dirname(__file__),'images')# 文件存储路径,这里的IMAGES_STORE名字不能改变

不用自带的管道,开启自己的管道

ITEM_PIPELINES = {# 'carhome.pipelines.CarhomePipeline': 300,'scrapy.pipelines.images.ImagesPipeline':1,}

注意爬虫文件中解析的数据返回的是列表

item['image_urls'] = ['https:'+li.xpath('./a/img/@src').extract_first()] # 图片url# 注意:在使用自定义管道的时候,这里返回的是一个列表

主要用一般方法下载,特殊情况用这种方法下载。

爬虫(21)crawlspider讲解古诗文案例补充+小程序社区案例+汽车之家案例+scrapy内置的下载文件的方法

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。