这里是通过爬取伯乐在线的全部文章为例子,让自己先对scrapy进行一个整理的理解

该例子中的详细代码会放到我的github地址:https://github.com/pythonsite/spider/tree/master/jobboleSpider

注:这个文章并不会对详细的用法进行讲解,是为了让对scrapy各个功能有个了解,建立整体的印象。

在学习Scrapy框架之前,我们先通过一个实际的爬虫例子来理解,后面我们会对每个功能进行详细的理解。
这里的例子是爬取http://blog.jobbole.com/all-posts/ 伯乐在线的全部文章数据

分析要爬去的目标站信息

先看如下图,首先我们要获取下图中所有文章的连接,然后是进入每个文章连接爬取每个文章的详细内容。
每个文章中需要爬取文章标题,发表日期,以及标签,赞赏收藏,评论数,文章内容。

对于该爬虫的一个整体思路

我们对这个爬虫进行一个思路整理,通过如下图表示:

以上是我们对这个爬虫需求了解,下面我们通过scrapy爬取我们想要爬取的数据,下面我们先对scrapy进行一个简单的了解

Scrapy的初步认识

Scrapy使用了Twisted作为框架,Twisted有些特殊的地方是它是事件驱动的,并且比较适合异步的代码。对于会阻塞线程的操作包含访问文件、数据库或者Web、产生新的进程并需要处理新进程的输出(如运行shell命令)、执行系统层次操作的代码(如等待系统队列),Twisted提供了允许执行上面的操作但不会阻塞代码执行的方法。
scrapy的项目结构:

items.py 负责数据模型的建立,类似于实体类。
middlewares.py 自己定义的中间件。
pipelines.py 负责对spider返回数据的处理。
settings.py 负责对整个爬虫的配置。
spiders目录 负责存放继承自scrapy的爬虫类。
scrapy.cfg scrapy基础配置

那么如何创建上述的目录,通过下面命令:

zhaofandeMBP:python_project zhaofan$ scrapy startproject test1
New Scrapy project 'test1', using template directory '/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/scrapy/templates/project', created in:/Users/zhaofan/Documents/python_project/test1You can start your first spider with:cd test1scrapy genspider example example.com
zhaofandeMBP:python_project zhaofan$
zhaofandeMBP:test1 zhaofan$ scrapy genspider shSpider hshfy.sh.cn
Created spider 'shSpider' using template 'basic' in module:test1.spiders.shSpider

相信上面这段话你肯定会觉得很无聊,所以直接分析爬虫代码。

代码的项目结构

items.py代码分析

items.py里存放的是我们要爬取数据的字段信息,代码如下:
我们分别要爬取的信息包括:文章标题,文件发布时间,文章url地址,url_object_id是我们会对地址进行md5加密,front_image_url 是文章下图片的url地址,front_image_path图片的存放路径

class JoBoleArticleItem(scrapy.Item):title = scrapy.Field()create_date = scrapy.Field()url = scrapy.Field()url_object_id = scrapy.Field()front_image_url = scrapy.Field()front_image_path = scrapy.Field()praise_nums = scrapy.Field()fav_nums = scrapy.Field()comment_nums = scrapy.Field()tag = scrapy.Field()content = scrapy.Field()

spiders/Article.py代码分析

spiders目录下的Article.py为主要的爬虫代码,包括了对页面的请求以及页面的处理,这里有几个知识点需要注意:
这些知识点我会在后面详细写一个文章整理,这里先有一个初步的印象。

1. 我们爬取的页面时http://blog.jobbole.com/all-posts/,所以parse的response,返回的是这个页面的信息,但是我们这个时候需要的是获取每个文章的地址继续访问,这里就用到了yield Request()这种用法,可以把获取到文章的url地址继续传递进来再次进行请求。
2. scrapy提供了response.css这种的css选择器以及response.xpath的xpath选择器方法,我们可以根据自己的需求获取我们想要的字段信息

class ArticleSpider(scrapy.Spider):name = "Article"allowed_domains = ["blog.jobbole.com"]start_urls = ['http://blog.jobbole.com/all-posts/']def parse(self, response):'''1.获取文章列表也中具体文章url,并交给scrapy进行下载后并进行解析2.获取下一页的url并交给scrapy进行下载,下载完成后,交给parse:param response::return:'''#解析列表页中所有文章的url,并交给scrapy下载后进行解析post_nodes = response.css("#archive .floated-thumb .post-thumb a")for post_node in post_nodes:#image_url是图片的地址image_url = post_node.css("img::attr(src)").extract_first("")post_url = post_node.css("::attr(href)").extract_first("")#这里通过meta参数将图片的url传递进来,这里用parse.urljoin的好处是如果有域名我前面的response.url不生效# 如果没有就会把response.url和post_url做拼接yield Request(url=parse.urljoin(response.url,post_url),meta={"front_image_url":parse.urljoin(response.url,image_url)},callback=self.parse_detail)#提取下一页并交给scrapy下载next_url = response.css(".next.page-numbers::attr(href)").extract_first("")if next_url:yield Request(url=next_url,callback=self.parse)def parse_detail(self,response):'''获取文章的详细内容:param response::return:'''article_item = JoBoleArticleItem()front_image_url = response.meta.get("front_image_url","")  #文章封面图地址title = response.xpath('//div[@class="entry-header"]/h1/text()').extract_first()create_date = response.xpath('//p[@class="entry-meta-hide-on-mobile"]/text()').extract()[0].strip().split()[0]tag_list = response.xpath('//p[@class="entry-meta-hide-on-mobile"]/a/text()').extract()tag_list = [element for element in tag_list if not element.strip().endswith("评论")]tag =",".join(tag_list)praise_nums = response.xpath('//span[contains(@class,"vote-post-up")]/h10/text()').extract()if len(praise_nums) == 0:praise_nums = 0else:praise_nums = int(praise_nums[0])fav_nums  = response.xpath('//span[contains(@class,"bookmark-btn")]/text()').extract()[0]match_re = re.match(".*(\d+).*",fav_nums)if match_re:fav_nums = int(match_re.group(1))else:fav_nums = 0comment_nums =response.xpath("//a[@href='#article-comment']/span/text()").extract()[0]match_com = re.match(".*(\d+).*",comment_nums)if match_com:comment_nums = int(match_com.group(1))else:comment_nums=0content = response.xpath('//div[@class="entry"]').extract()[0]article_item["url_object_id"] = get_md5(response.url) #这里对地址进行了md5变成定长article_item["title"] = titlearticle_item["url"] = response.urltry:create_date = datetime.datetime.strptime(create_date,'%Y/%m/%d').date()except Exception as e:create_date = datetime.datetime.now().date()article_item["create_date"] = create_datearticle_item["front_image_url"] = [front_image_url]article_item["praise_nums"] = int(praise_nums)article_item["fav_nums"] = fav_numsarticle_item["comment_nums"] = comment_numsarticle_item["tag"] = tagarticle_item['content'] = contentyield article_item

View Code

pipeline中代码的分析

pipeline主要是对spiders中爬虫的返回的数据的处理,这里我们可以让写入到数据库,也可以让写入到文件等等。
下面代码中主要包括的写入到json文件以及写入到数据库,包括异步插入到数据库,还有图片的处理,这里我们可以定义各种我们需要的pipeline,当然这里我们不同的pipeline是有一定的顺序的,需要的设置是在settings配置文件中,如下,后面的数字表示的是优先级,数字越小优先级越高。

class JobbolespiderPipeline(object):def process_item(self, item, spider):return itemclass JsonWithEncodingPipeline(object):'''返回json数据到文件'''def __init__(self):self.file = codecs.open("article.json",'w',encoding="utf-8")def process_item(self, item, spider):lines = json.dumps(dict(item),ensure_ascii=False) + "\n"self.file.write(lines)return itemdef spider_closed(self,spider):self.file.close()class MysqlPipeline(object):'''插入mysql数据库'''def __init__(self):self.conn =pymysql.connect(host='192.168.1.19',port=3306,user='root',passwd='123456',db='article_spider',use_unicode=True, charset="utf8")self.cursor = self.conn.cursor()def process_item(self,item,spider):insert_sql = '''insert into jobbole_article(title,create_date,url,url_object_id,front_image_url,front_image_path,comment_nums,fav_nums,praise_nums,tag,content) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'''self.cursor.execute(insert_sql,(item["title"],item["create_date"],item["url"],item["url_object_id"],item["front_image_url"],item["front_image_path"],item["comment_nums"],item["fav_nums"],item["praise_nums"],item["tag"],item["content"]))self.conn.commit()class MysqlTwistedPipline(object):'''采用异步的方式插入数据'''def __init__(self,dbpool):self.dbpool = dbpool@classmethoddef from_settings(cls,settings):dbparms = dict(host = settings["MYSQL_HOST"],port = settings["MYSQL_PORT"],user = settings["MYSQL_USER"],passwd = settings["MYSQL_PASSWD"],db = settings["MYSQL_DB"],use_unicode = True,charset="utf8",)dbpool = adbapi.ConnectionPool("pymysql",**dbparms)return cls(dbpool)def process_item(self,item,spider):'''使用twisted将mysql插入变成异步:param item::param spider::return:'''query = self.dbpool.runInteraction(self.do_insert,item)query.addErrback(self.handle_error)def handle_error(self,failure):#处理异步插入的异常print(failure)def do_insert(self,cursor,item):#具体插入数据insert_sql = '''insert into jobbole_article(title,create_date,url,url_object_id,front_image_url,front_image_path,comment_nums,fav_nums,praise_nums,tag,content) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'''cursor.execute(insert_sql,(item["title"],item["create_date"],item["url"],item["url_object_id"],item["front_image_url"],item["front_image_path"],item["comment_nums"],item["fav_nums"],item["praise_nums"],item["tag"],item["content"]))class ArticleImagePipeline(ImagesPipeline):'''对图片的处理'''def item_completed(self, results, item, info):for ok ,value in results:if ok:image_file_path = value["path"]item['front_image_path'] = image_file_pathelse:item['front_image_path'] = ""return item

View Code

所有的努力都值得期许,每一份梦想都应该灌溉!

Python爬虫从入门到放弃(十一)之 Scrapy框架整体的一个了解相关推荐

  1. python爬虫从入门到放弃,含案例分析,超详细讲解(一)

    Python爬虫 1.认识爬虫 1.1.概述 网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者) 按照一定规律,自动地抓取万维网信息的程序或者脚本. 1.2.应用场景 ...

  2. Python爬虫从入门到放弃(十二)之 Scrapy框架的架构和原理

    原文地址https://www.cnblogs.com/zhaof/p/7173397.html 这一篇文章主要是为了对scrapy框架的工作流程以及各个组件功能的介绍 Scrapy目前已经可以很好的 ...

  3. python爬虫从入门到放弃(一)初识爬虫

    在家里呆了几个月,重新拾起python爬虫,想着搞点东西(爱情电影)看看,发现爬虫真的是好开心. 网络爬虫是什么呢? 网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者) ...

  4. 数据分析利器Python——爬虫(含爬取过程、Scrapy框架介绍)

    文章目录 一.基础知识 1.定义 2.基本架构 二.URL管理模块 三.网页下载模块 Python中的requests模块 四.网页解析模块 1.结构化网页解析 2.BeautifulSoup使用步骤 ...

  5. python爬虫从入门到放弃(三)之 Urllib库的基本使用

    官方文档地址:https://docs.python.org/3/library/urllib.html 什么是Urllib Urllib是python内置的HTTP请求库 包括以下模块 urllib ...

  6. python爬虫从入门到放弃(六)之 BeautifulSoup库的使用

    上一篇文章的正则,其实对很多人来说用起来是不方便的,加上需要记很多规则,所以用起来不是特别熟练,而这节我们提到的beautifulsoup就是一个非常强大的工具,爬虫利器. beautifulSoup ...

  7. Python爬虫从入门到放弃(十三)之 Scrapy框架的命令行详解

    这篇文章主要是对的scrapy命令行使用的一个介绍 创建爬虫项目 scrapy startproject 项目名 例子如下: localhost:spider zhaofan$ scrapy star ...

  8. python爬虫从入门到放弃(八)之 Selenium库的使用

    原文地址https://www.cnblogs.com/zhaof/p/6953241.html 一.什么是Selenium selenium 是一套完整的web应用程序测试系统,包含了测试的录制(s ...

  9. python爬虫从入门到放弃-python爬虫从入门到放弃(三)之 Urllib库的基本使用

    什么是Urllib Urllib是python内置的HTTP请求库 包括以下模块 urllib.request 请求模块 urllib.error 异常处理模块 urllib.parse url解析模 ...

最新文章

  1. 数据库读取image类型发送到前端显示图片
  2. 蓄电池及直流电源装置的运行维护——Fluke 345 多用途钳表的应用
  3. 实用--HTML的命名规范
  4. python是什么语言汇编_编程语言及python介绍
  5. SqlServer图形数据库初体验
  6. 用纯CSS禁止鼠标点击事件以及禁止鼠标样式
  7. php 判断网络图片是否存,PHP判断远程图片或文件或url是否存在-180
  8. K-近邻算法(KNN)概述
  9. C中使用汇编交换两个值
  10. 斐讯N1强制刷机-免拆版
  11. 微信小程序 版本更新及调试方法
  12. 前端面试题之浏览器系列
  13. 总结一下用面向对象写法调用借口
  14. Machine code description classes
  15. 验证tomcat安装成功
  16. 筑波大学sgu项目计算机修士,柠檬SGU|筑波大学英文授课修士CSE计算机课程
  17. 一款不错的流式布局LayoutManager-FlowLayout
  18. Android 自定义DatePick 只显示年月,日期选择年月
  19. GBASE南大通用为行业信创发展提速 亮相全国信创与人工智能发展博士后论坛
  20. Java破解图片防盗链

热门文章

  1. 解决Windows 7删除执行过的 EXE、Bat文件有延迟的问题
  2. 4.安卓基础之Activity跳转动画
  3. Spring Boot应用的打包和部署
  4. SQL关键字Pivot(行变列)
  5. php中heredoc的使用方法
  6. [原]问题解决办法:there are offline or missing virtual drivers with preserved cache
  7. 什么原因导致百度搜索比Google要少很多?
  8. where、having、group by、order by、limit的区别和使用顺序
  9. 使用LXCFS实现容器资源的视图隔离
  10. SpringCloud 微服务网关Gateway介绍及简单路由配置