老早之前就听说过python的scrapy。这是一个分布式爬虫的框架,可以让你轻松写出高性能的分布式异步爬虫。使用框架的最大好处当然就是不同重复造轮子了,因为有很多东西框架当中都有了,直接拿过来使用就可以了。scrapy 就是一个很棒的框架。最近在看崔庆才老师的博客http://cuiqingcai.com/ 的时候,发现了几个写的非常好的scrapy教程(http://cuiqingcai.com/4380.html,http://cuiqingcai.com/3952.html等,还有很多,大家可以自己去看),我看了半个小时就把以前看的scrapy基础回忆起来了,而且又学到了很多新的东西,所以就手痒痒用scrapy写了一个自己的爬虫,记录在这里。

  脚本之家(http://www.jb51.net/)是我写代码查某个函数怎么怎么用(有时候忘了)经常去的地方,虽然站点界面像shi一样,又有许多杂七杂八的广告,不过说句公道话,还有有不少干货的,大部分也都附有源代码。今天我要爬取的就是脚本之家的文章。

  在开始之前,先简单介绍一下scrapy的常用命令吧。我不打算讲的非常详细,要想详细了解,可以参考文档(http://wiki.jikexueyuan.com/project/scrapy/)或者上面我说的几篇博客。scrapy 创建一个 项目 使用的命令是: scrapy crawl project_name (project_name是你的项目名称) 这个命令需要在cmd(windows)或者shell(linux)下键入,这就会在当前目录下创建名称为 project_name 的项目。然后 cd 到这个项目,输入命令 genspider your_spider_name 来快速创建一个爬虫,your_spider_name 为你的爬虫的名字,注意这个名字必须是唯一的,这个命令在 project_name/project_name/spiders/目录下 生成了一个 your_spider_name.py 文件,你的爬虫就写到这里啦。

  常见的几个文件作用如下:

  spiders 文件夹用来存放你写的爬虫的脚本

  items.py 用来定义你想要抓取的数据字段

  middlewares.py 用来给scrapy增加一些额外的自定义的功能(比如后面要讲的设置代理等等)

  piplines.py 用来定义抓取数据的储存方式

  settings.py 是用来设置爬虫参数的文件

  打开 爬虫文件,一般是已经给你 写好了一个 类,类似这样:

  1. class JbzjSpiderSpider(scrapy.Spider):
  2. name = "jbzj_spider"
  3. allowed_domains = ["www.jb51.net"]
  4. base_url = "http://www.jb51.net"
  5. start_urls = []
  6.  
  7. def parse(self, response):
  8. pass

  其中 name 是爬虫的名字(唯一),allowed_domains 为允许抓取的域名,start_urls 为 起始抓取的列表,如果没有特别指定抓取的url,就从start_urls列表中的地址抓取,类必须继承自 scrapy.Spider,这是所有爬虫都必须继承的一个类,parse 是 scrapy.Spider 的一个方法,我们有的时候需要将他覆写(override),这个方法是默认的回调函数(callback),如果没有指定函数的回调函数的话,就会默认调用 parse函数。response 是解析 url 得到的相应,里面包含响应头,响应网页源码,url等等,比如 response.body 得到 网页源码,response.url 得到响应的url。对于解析网页,scrapy默认使用的方法是xpath 解析。比如可以直接使用 response.xpath("//a[@id="id1"]/@href").extract()得到id = id1的a标签的href属性(xpath的用法大家自行搜索,入门很快),使用 extract 方法返回的是一个列表。当然,除了使用xpath,你可以得到 response.body 之后,再使用你习惯解析html的方法(正则,css,bs4等等)。最后,一般我们需要 yield 一个 scrapy.Request 即相当于返回一个请求,这个请求可以设置很多参数,比较重要的有 headers(头部信息),callback(回调函数),meta(传递额外信息,默认传递的只是response)。比如我们写 yield scrapy.Request(url,callback=self.parse_url),就是设定回调函数为 parse_url 函数,我们将 response 传递给parse_url 进行进一步解析。

  还有一点就是,在这里我们将爬取到的数据存入数据库,python 连接数据库一般有 MySQLdb 和 pymysql 两个驱动可以选择,我一般使用的是前者,但是比较坑爹的是

MySQLdb 好像只支持 32 位系统,反正我用64位的python 装了好多次都没成功。所以建议使用 pip install pymysql 来安装,pymysql 使用纯python写的驱动,用法和 mysqldb差不多。我们需要在piplines.py 中 写插入数据库的操作,代码大概像下面这样:

  1. import pymysql
  2.  
  3. class JbzjPipeline(object):
  4. def process_item(self, item, spider):
  5. url = item['article_url'] # 文章url
  6. title = item['article_title'] # 文章标题
  7. content = item['article_content'] # 内容
  8. # 建立数据库连接
  9. conn = pymysql.connect(host = 'localhost',user = 'root',passwd = 'passwd',db = 'your_db',charset = 'utf8')
  10. cursor = conn.cursor()
  11. sql = "insert into jbzj VALUES(NULL,%s,%s,%s)"
  12. cursor.execute(sql,(url,title,content)) # 执行sql语句
  13. cursor.close()
  14. conn.commit() # 提交数据库
  15. print(u"成功插入一条数据!")
  16. conn.close() # 关闭连接

我们需要覆写 JbzjPipeline 类的 process_item 方法,这个方法在 yield item 之后会自动调用,需要传入两个参数,一个是item(数据字段),一个是spider(哪个爬虫),我们在这个函数下写插入数据进入数据库的操作就可以了。

对了还有 items.py 文件,大概长下面这样:

  1. class JbzjItem(scrapy.Item):
  2. # define the fields for your item here like:
  3. # name = scrapy.Field()
  4. article_url = scrapy.Field() # 文章链接
  5. article_title = scrapy.Field() # 文章标题
  6. article_content = scrapy.Field() # 文章内容

我们采用 name = scrapy.Field()这样的形式来定义我们需要的字段,类需要继承自 scrapy.Item,在这里我就简单定义了文章链接、内容和标题三个字段。

总结一下:scrapy 抓取的基本步骤大概就是:从start_urls 中的url开始抓取,默认调用 start_requests ,然后将响应的请求传给 parse方法,parse方法再传递给它的回调函数,以此类推,直到最后一层 yield item,然后 piplines.py 开始处理数据的储存,当然我说的很简单,实际处理的过程比这个还要复杂一点,scrapy默认就是开启多线程的,整个过程不是顺序执行,如果想要彻底弄明白scrapy运行的机制,可以去找官方文档。

    最后 给出实际的代码:

jbzj_spider.py

  1. # -*- coding: utf-8 -*-
  2. '''
  3. scrapy 脚本之家爬虫实例:http://www.jb51.net/article/54323.htm
  4. '''
  5. import re
  6.  
  7. import scrapy
  8. from ..items import JbzjItem
  9. from scrapy.selector import Selector
  10.  
  11. class JbzjSpiderSpider(scrapy.Spider):
  12. name = "jbzj_spider"
  13. allowed_domains = ["www.jb51.net"]
  14. base_url = "http://www.jb51.net"
  15. start_urls = [
  16. 'http://www.jb51.net/article/109909.htm',
  17. 'http://www.jb51.net/article/110219.htm'
  18. ]
  19.  
  20. # def start_requests(self):
  21. # yield scrapy.Request(self.start_urls[0],callback=self.parse)
  22.  
  23. def parse(self, response):
  24. html = response.body # 网页源码
  25. urls_list = re.findall(re.compile(r'<a href="(/article/\d+\.htm)".+?</a>'),html)
  26. full_urls_list = [self.base_url + url for url in urls_list] # 完整列表
  27. for url in full_urls_list:
  28. yield scrapy.Request(url,callback=self.parse_url)
  29.  
  30. def parse_url(self,response):
  31. item = JbzjItem() # 实例化一个item
  32. selector = Selector(response) # 构造一个选择器
  33. title = selector.xpath("//div[@class='title']/h1/text()").extract()[0] # 标题
  34. content = selector.xpath("//div[@id='content']//text()").extract() # 内容
  35. item['article_url'] = response.url
  36. item['article_title'] = title
  37. item['article_content'] = "".join(content)
  38. yield item
  39. html = response.body # 网页源码
  40. urls_list = re.findall(re.compile(r'<a href="(/article/\d+\.htm)".+?</a>'),html)
  41. full_urls_list = [self.base_url + url for url in urls_list] # 完整列表
  42. for url in full_urls_list:
  43. yield scrapy.Request(url,callback=self.parse_url2)
  44.  
  45. def parse_url2(self,response):
  46. item = JbzjItem() # 实例化一个item
  47. selector = Selector(response) # 构造一个选择器
  48. title = selector.xpath("//div[@class='title']/h1/text()").extract()[0] # 标题
  49. content = selector.xpath("//div[@id='content']//text()").extract() # 内容
  50. item['article_url'] = response.url
  51. item['article_title'] = title
  52. item['article_content'] = "".join(content)
  53. yield item

对了,为了使用piplines.py,我们需要将 settings.py 中的 ITEM_PIPELINES 一项注释去掉,不然无法使用 piplines。

以上就是 本文的基本内容,后续有时间还会更新 scrapy的其他方面的内容。

python scrapy 抓取脚本之家文章(scrapy 入门使用简介)的更多相关文章

  1. C#.Net使用正则表达式抓取百度百家文章列表

    工作之余,学习了一下正则表达式,鉴于实践是检验真理的唯一标准,于是便写了一个利用正则表达式抓取百度百家文章的例子,具体过程请看下面源码: 一:获取百度百家网页内容 public List<str ...

  2. scrapy抓取拉勾网职位信息(一)——scrapy初识及lagou爬虫项目建立

    本次以scrapy抓取拉勾网职位信息作为scrapy学习的一个实战演练 python版本:3.7.1 框架:scrapy(pip直接安装可能会报错,如果是vc++环境不满足,建议直接安装一个visua ...

  3. python抓取月光博客的全部文章而且依照标题分词存入mongodb中

    猛击这里:python抓取月光博客的全部文章

  4. [python]乱码:python抓取脚本

    参考: http://www.zhxl.me/1409.html 使用 python urllib2 抓取网页时出现乱码的解决方案 发表回复 这里记录的是一个门外汉解决使用 urllib2 抓取网页时 ...

  5. 分布式爬虫:使用Scrapy抓取数据

    分布式爬虫:使用Scrapy抓取数据 Scrapy是Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据.Scrapy用途广泛,可以用于数据挖掘. ...

  6. python 爬虫抓取心得

    quanwei9958 转自 python 爬虫抓取心得分享 urllib.quote('要编码的字符串') 如果你要在url请求里面放入中文,对相应的中文进行编码的话,可以用: urllib.quo ...

  7. scrapy抓取淘宝女郎

    scrapy抓取淘宝女郎 准备工作 首先在淘宝女郎的首页这里查看,当然想要爬取更多的话,当然这里要查看翻页的url,不过这操蛋的地方就是这里的翻页是使用javascript加载的,这个就有点尴尬了,找 ...

  8. 【爬虫】利用Scrapy抓取京东商品、豆瓣电影、技术问题

    1.scrapy基本了解 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架.可以应用在包括数据挖掘, 信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取(更确切来说,网络抓 ...

  9. python requests抓取NBA球员数据,pandas进行数据分析,echarts进行可视化 (前言)

    python requests抓取NBA球员数据,pandas进行数据分析,echarts进行可视化 (前言) 感觉要总结总结了,希望这次能写个系列文章分享分享心得,和大神们交流交流,提升提升. 因为 ...

随机推荐

  1. FineUIMvc随笔(5)UIHelper是个什么梗?

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. UIHelper.Result 在 FineUIMvc 的每一个 HttpPost 的控制器方法里面,你都会看到 UIHelpe ...

  2. 串匹配模式中的BF算法和KMP算法

    考研的专业课以及找工作的笔试题,对于串匹配模式都会有一定的考察,写这篇博客的目的在于进行知识的回顾与复习,方便遇见类似的题目不会纠结太多. 传统的BF算法 传统算法讲的是串与串依次一对一的比较,举例设 ...

  3. 重回博客 谈一谈Node中的异步和单线程

    重回博客,这个帐号之前注册后就只发了一篇博客.听朋友建议,决定一周两次更新. 第一篇谈论一下最近想的比较多的异步的问题. 传统多线程异步 传统的异步是多线程的,当要同时做两件事的时候,他们是执行在不同 ...

  4. C++primer拾遗(第一章:开始)

    本系列将总结正在阅读的C++primer这本书中值得注意又容易忘记的知识点. 1. 当return语句包括一个值时,次返回值的类型必须与函数返回类型相同. 2. 操纵符 endl.写入该符号的效果是: ...

  5. 【运维监控】四款云服务监控工具介绍:Nagios 、 ganglia、zabbix、onealert

    在我们日常的工作中,有时候需要监控和管理平台的运行状况,而服务运行是否存在异常,是否有软硬件bug等,均需要第一时间知道.对服务状态了如指掌,是一个很重要的事情.那么这个如何做到呢,我们之前在进行私有 ...

  6. 《Machine Learning》系列学习笔记之第二周

    第二周 第一部分 Multivariate Linear Regression Multiple Features Note: [7:25 - θT is a 1 by (n+1) matrix an ...

  7. NOI全国赛(1998)——围巾裁剪

    裁缝有一块非常珍贵的丝绸围巾.可惜的是,围巾的某些部分已经被蛀虫给咬坏了.裁缝当然不愿意就这么把围巾给丢了,于是,他想把围巾给裁成两块小围巾送给他的两个女儿.自然,两块小围巾的面积之和越大越好.  这 ...

  8. Angular2之管道学习笔记

    管道.可以把一个输出流与另一个输入流连接起来.类似 linux.gulp都有应用. 在Angular2中使用管道非常方便.Angular2中本身提供了一些内置管道.当然也可以自定义管道. 文档链接:h ...

  9. 提交任务到Spark

    1.场景 在搭建好Hadoop+Spark环境后,现准备在此环境上提交简单的任务到Spark进行计算并输出结果.搭建过程:http://www.cnblogs.com/zengxiaoliang/p/ ...

  10. 学习CSS了解单位em和px的区别

    这里引用的是Jorux的“95%的中国网站需要重写CSS”的文章,题目有点吓人,但是确实是现在国内网页制作方面的一些缺陷.我一直也搞不清楚px与em之间的关系和特点,看过以后确实收获很大.平时都是用p ...