python网络爬虫(14)使用Scrapy搭建爬虫框架
python网络爬虫(14)使用Scrapy搭建爬虫框架
阅读目录
目的意义
说明
创建scrapy工程
一些介绍说明
创建爬虫模块-下载
强化爬虫模块-解析
强化爬虫模块-包装数据
强化爬虫模块-翻页
强化爬虫模块-存储
强化爬虫模块-图像下载保存
启动爬虫
修正
目的意义
爬虫框架也许能简化工作量,提高效率等。scrapy是一款方便好用,拓展方便的框架。
本文将使用scrapy框架,示例爬取自己博客中的文章内容。
说明
学习和模仿来源:https://book.douban.com/subject/27061630/。
创建scrapy工程
首先当然要确定好,有没有完成安装scrapy。在windows下,使用pip install scrapy,慢慢等所有依赖和scrapy安装完毕即可。然后输入scrapy到cmd中测试。
建立工程使用scrapy startproject myTestProject,会在工程下生成文件。
一些介绍说明
在生成的文件中,
创建爬虫模块-下载
在路径./myTestProject/spiders下,放置用户自定义爬虫模块,并定义好name,start_urls,parse()。
如在spiders目录下建立文件CnblogSpider.py,并填入以下:
1
2
3
4
5
6
import scrapy
class CnblogsSpider(scrapy.Spider):
name="cnblogs" start_urls=["https://www.cnblogs.com/bai2018/default.html?page=1"] def parse(self,response): pass
在cmd中,切换到./myTestProject/myTestProject下,再执行scrapy crawl cnblogs(name)测试,观察是否报错,响应代码是否为200。其中的parse中参数response用于解析数据,读取数据等。
强化爬虫模块-解析
在CnblogsSpider类中的parse方法下,添加解析功能。通过xpath、css、extract、re等方法,完成解析。
调取元素审查分析以后添加,成为以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
import scrapy
class CnblogsSpider(scrapy.Spider):
name="cnblogs" start_urls=["https://www.cnblogs.com/bai2018/"] def parse(self,response): papers=response.xpath(".//*[@class='day']") for paper in papers: url=paper.xpath(".//*[@class='postTitle']/a/@href").extract() title=paper.xpath(".//*[@class='postTitle']/a/text()").extract() time=paper.xpath(".//*[@class='dayTitle']/a/text()").extract() content=paper.xpath(".//*[@class='postCon']/div/text()").extract() print(url,title,time,content) pass
找到页面中,class为day的部分,然后再找到其中各个部分,提取出来,最后通过print方案输出用于测试。
在正确的目录下,使用cmd运行scrapy crawl cnblogs,完成测试,并观察显示信息中的print内容是否符合要求。
强化爬虫模块-包装数据
包装数据的目的是存储数据。scrapy使用Item类来满足这样的需求。
框架中的items.py用于定义存储数据的Item类。
在items.py中修改MytestprojectItem类,成为以下代码:
1
2
3
4
5
6
7
8
9
import scrapy
class MytestprojectItem(scrapy.Item):
# define the fields for your item here like: # name = scrapy.Field() url=scrapy.Field() time=scrapy.Field() title=scrapy.Field() content=scrapy.Field() pass
然后修改CnblogsSpider.py,成为以下内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import scrapy
from myTestProject.items import MytestprojectItem
class CnblogsSpider(scrapy.Spider):
name="cnblogs" start_urls=["https://www.cnblogs.com/bai2018/"] def parse(self,response): papers=response.xpath(".//*[@class='day']") for paper in papers: url=paper.xpath(".//*[@class='postTitle']/a/@href").extract() title=paper.xpath(".//*[@class='postTitle']/a/text()").extract() time=paper.xpath(".//*[@class='dayTitle']/a/text()").extract() content=paper.xpath(".//*[@class='postCon']/div/text()").extract() item=MytestprojectItem(url=url,title=title,time=time,content=content) yield item pass
将提取出的内容封装成Item对象,使用关键字yield提交。
强化爬虫模块-翻页
有时候就是需要翻页,以获取更多数据,然后解析。
修改CnblogsSpider.py,成为以下内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import scrapy
from scrapy import Selector
from myTestProject.items import MytestprojectItem
class CnblogsSpider(scrapy.Spider):
name="cnblogs" allowd_domains=["cnblogs.com"] start_urls=["https://www.cnblogs.com/bai2018/"] def parse(self,response): papers=response.xpath(".//*[@class='day']") for paper in papers: url=paper.xpath(".//*[@class='postTitle']/a/@href").extract() title=paper.xpath(".//*[@class='postTitle']/a/text()").extract() time=paper.xpath(".//*[@class='dayTitle']/a/text()").extract() content=paper.xpath(".//*[@class='postCon']/div/text()").extract() item=MytestprojectItem(url=url,title=title,time=time,content=content) yield item next_page=Selector(response).re(u'<a href="(\S*)">下一页</a>') if next_page: yield scrapy.Request(url=next_page[0],callback=self.parse) pass
在scrapy的选择器方面,使用xpath和css,可以直接将CnblogsSpider下的parse方法中的response参数使用,如response.xpath或response.css。
而更通用的方式是:使用Selector(response).xxx。针对re则为Selector(response).re。
关于yield的说明:https://blog.csdn.net/mieleizhi0522/article/details/82142856
强化爬虫模块-存储
当Item在Spider中被收集时候,会传递到Item Pipeline。
修改pipelines.py成为以下内容:
1
2
3
4
5
6
7
8
9
10
11
12
import json
from scrapy.exceptions import DropItem
class MytestprojectPipeline(object):
def __init__(self): self.file=open('papers.json','wb') def process_item(self, item, spider): if item['title']: line=json.dumps(dict(item))+"\n" self.file.write(line.encode()) return item else: raise DropItem("Missing title in %s"%item)
重新实现process_item方法,收集item和该item对应的spider。然后创建papers.json,转化item为字典,存储到json表中。
另外,根据提示打开pipelines.py的开关。在settings.py中,使能ITEM_PIPELINES的开关如下:
然后在cmd中执行scrapy crawl cnblogs即可
另外,还可以使用scrapy crawl cnblogs -o papers.csv进行存储为csv文件。
需要更改编码,将csv文件以记事本方式重新打开,更正编码后重新保存,查看即可。
强化爬虫模块-图像下载保存
设定setting.py
1
2
3
4
5
6
7
8
9
10
11
12
ITEM_PIPELINES = {
'myTestProject.pipelines.MytestprojectPipeline':300, 'scrapy.pipelines.images.ImagesPipeline':1
}
IAMGES_STORE='.//cnblogs'
IMAGES_URLS_FIELD = 'cimage_urls'
IMAGES_RESULT_FIELD = 'cimages'
IMAGES_EXPIRES = 30
IMAGES_THUMBS = {
'small': (50, 50), 'big': (270, 270)
}
修改items.py为:
1
2
3
4
5
6
7
8
9
10
11
12
import scrapy
class MytestprojectItem(scrapy.Item):
# define the fields for your item here like: # name = scrapy.Field() url=scrapy.Field() time=scrapy.Field() title=scrapy.Field() content=scrapy.Field() cimage_urls=scrapy.Field() cimages=scrapy.Field() pass
修改CnblogsSpider.py为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import scrapy
from scrapy import Selector
from myTestProject.items import MytestprojectItem
class CnblogsSpider(scrapy.Spider):
name="cnblogs" allowd_domains=["cnblogs.com"] start_urls=["https://www.cnblogs.com/bai2018/"] def parse(self,response): papers=response.xpath(".//*[@class='day']") for paper in papers: url=paper.xpath(".//*[@class='postTitle']/a/@href").extract()[0] title=paper.xpath(".//*[@class='postTitle']/a/text()").extract() time=paper.xpath(".//*[@class='dayTitle']/a/text()").extract() content=paper.xpath(".//*[@class='postCon']/div/text()").extract() item=MytestprojectItem(url=url,title=title,time=time,content=content) request=scrapy.Request(url=url, callback=self.parse_body) request.meta['item']=item yield request next_page=Selector(response).re(u'<a href="(\S*)">下一页</a>') if next_page: yield scrapy.Request(url=next_page[0],callback=self.parse) pass def parse_body(self, response): item = response.meta['item'] body = response.xpath(".//*[@class='postBody']") item['cimage_urls'] = body.xpath('.//img//@src').extract() yield item
总之,修改以上三个位置。在有时候配置正确的时候却出现图像等下载失败,则可能是由于setting.py的原因,需要重新修改。
启动爬虫
建立main函数,传递初始化信息,导入指定类。如:
1
2
3
4
5
6
7
8
9
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from myTestProject.spiders.CnblogSpider import CnblogsSpider
if __name__=='__main__':
process = CrawlerProcess(get_project_settings()) process.crawl('cnblogs') process.start()
修正
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import scrapy
from scrapy import Selector
from cnblogSpider.items import CnblogspiderItem
class CnblogsSpider(scrapy.Spider):
name="cnblogs" allowd_domains=["cnblogs.com"] start_urls=["https://www.cnblogs.com/bai2018/"] def parse(self,response): papers=response.xpath(".//*[@class='day']") for paper in papers: urls=paper.xpath(".//*[@class='postTitle']/a/@href").extract() titles=paper.xpath(".//*[@class='postTitle']/a/text()").extract() times=paper.xpath(".//*[@class='dayTitle']/a/text()").extract() contents=paper.xpath(".//*[@class='postCon']/div/text()").extract() for i in range(len(urls)): url=urls[i] title=titles[i] time=times[0] content=contents[i] item=CnblogspiderItem(url=url,title=title,time=time,content=content) request = scrapy.Request(url=url, callback=self.parse_body) request.meta['item'] = item yield request next_page=Selector(response).re(u'<a href="(\S*)">下一页</a>') if next_page: yield scrapy.Request(url=next_page[0],callback=self.parse) pass def parse_body(self, response): item = response.meta['item'] body = response.xpath(".//*[@class='postBody']") item['cimage_urls'] = body.xpath('.//img//@src').extract() yield item
感谢您能通过各种渠道找到我,并学习相关。
作文粗糙,有任何不明白或者因故过时,敬请留言。 感谢批评指正。
原文地址https://www.cnblogs.com/bai2018/p/11255185.html
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
jquery 操作HTML data全局属性缓存的坑
jquery 操作HTML data全局属性缓存的坑data-* 全局属性 是一类被称为自定义数据属性的属性,它赋予我们在所有 HTML 元素上嵌入自定义数据属性的能力,并可以通过脚本(一般指JavaScript) 与 HTML 之间进行专有数据的交换。 简单的说就是html元素可以通过data-*属性存一些数据,类似于一个map,如果我们想在html的元素上额外的存一些东西是非常方便的。 一:读取是没问题的比如我们读取div中data-num的数据: dataSet 分别用jquery和js的方法读取,结果都是1。 二:修改就有坑了但是修改的data-num的时候就有意思了: jquery设置data-num中的值为2jquery读取值的值是2js读取值的值是1,奇怪,查看下html元素 data-num的值还是1。。。 这个坑,坑了我一早上,后来百度下才知道,原来jquery设置的值是在缓存里。。。果断查看下jquery的源码,真相都在代码里: 三:正确的使用方式如果需要修改dom元素上的data必须用js的方式:document.getElementById("div1").da...
- 下一篇
【从入门到放弃-Java】并发编程-JUC-ConcurrentHashMap
前言 上文【从入门到放弃-Java】并发编程-锁-synchronized中,我们介绍了可以使用内置锁synchronized同步类或代码块儿,到达线程安全的目的。 jdk帮我们把常用的一些模块封装成同步容器,如Vector、Hashtable、Collections.synchronizedXxx等。实现方式主要是将常用的容器类加了Synchronized同步。但我们知道,synchronized的频繁使用及竞争较为激烈时,对性能的影响比较大。 jdk1.5之后为我们提供了多种并发容器类,来提升同步容器的性能,这些类主要在java.util.concurrent包(简称juc,包内还有很多其它的并发工具类)中。我们本文先来学习下最常用的并发容器-ConcurrentHashMap。 ConcurrentHashMap put /** *
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8安装Docker,最新的服务器搭配容器使用
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7安装Docker,走上虚拟化容器引擎之路