Python爬虫框架Scrapy实战之批量抓取招聘信息


Posted in Python onAugust 07, 2015

网络爬虫抓取特定网站网页的html数据,但是一个网站有上千上万条数据,我们不可能知道网站网页的url地址,所以,要有个技巧去抓取网站的所有html页面。Scrapy是纯Python实现的爬虫框架,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便~

   Scrapy 使用wisted这个异步网络库来处理网络通讯,架构清晰,并且包含了各种中间件接口,可以灵活的完成各种需求。整体架构如下图所示:

Python爬虫框架Scrapy实战之批量抓取招聘信息

    绿线是数据流向,首先从初始URL 开始,Scheduler 会将其交给 Downloader 进行下载,下载之后会交给 Spider 进行分析,Spider分析出来的结果有两种:一种是需要进一步抓取的链接,例如之前分析的“下一页”的链接,这些东西会被传回 Scheduler ;另一种是需要保存的数据,它们则被送到Item Pipeline 那里,那是对数据进行后期处理(详细分析、过滤、存储等)的地方。另外,在数据流动的通道里还可以安装各种中间件,进行必要的处理。

我假定你已经安装了Scrapy。假如你没有安装,你可以参考这篇文章。

在本文中,我们将学会如何使用Scrapy建立一个爬虫程序,并爬取指定网站上的内容

1. 创建一个新的Scrapy Project
2. 定义你需要从网页中提取的元素Item
3.实现一个Spider类,通过接口完成爬取URL和提取Item的功能
4. 实现一个Item PipeLine类,完成Item的存储功能

我将会用腾讯招聘官网作为例子。
Github源码:https://github.com/maxliaops/scrapy-itzhaopin

Python爬虫框架Scrapy实战之批量抓取招聘信息

目标:抓取腾讯招聘官网职位招聘信息并保存为JSON格式。

新建工程

首先,为我们的爬虫新建一个工程,首先进入一个目录(任意一个我们用来保存代码的目录),执行:

scrapy startprojectitzhaopin

最后的itzhaopin就是项目名称。这个命令会在当前目录下创建一个新目录itzhaopin,结构如下:

├── itzhaopin
│   ├── itzhaopin
│   │   ├── __init__.py
│   │   ├── items.py
│   │   ├── pipelines.py
│   │   ├── settings.py
│   │   └── spiders
│   │      └── __init__.py
│   └── scrapy.cfg

scrapy.cfg: 项目配置文件
items.py: 需要提取的数据结构定义文件
pipelines.py:管道定义,用来对items里面提取的数据做进一步处理,如保存等
settings.py: 爬虫配置文件
spiders: 放置spider的目录

定义Item

在items.py里面定义我们要抓取的数据:

from scrapy.item import Item, Field 
class TencentItem(Item): 
  name = Field()        # 职位名称 
  catalog = Field()       # 职位类别 
  workLocation = Field()    # 工作地点 
  recruitNumber = Field()    # 招聘人数 
  detailLink = Field()     # 职位详情页链接 
  publishTime = Field()     # 发布时间

实现Spider

Spider是一个继承自scrapy.contrib.spiders.CrawlSpider的Python类,有三个必需的定义的成员

name: 名字,这个spider的标识

start_urls:一个url列表,spider从这些网页开始抓取

parse():一个方法,当start_urls里面的网页抓取下来之后需要调用这个方法解析网页内容,同时需要返回下一个需要抓取的网页,或者返回items列表

所以在spiders目录下新建一个spider,tencent_spider.py:

import re 
import json 
from scrapy.selector import Selector 
try: 
  from scrapy.spider import Spider 
except: 
  from scrapy.spider import BaseSpider as Spider 
from scrapy.utils.response import get_base_url 
from scrapy.utils.url import urljoin_rfc 
from scrapy.contrib.spiders import CrawlSpider, Rule 
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor as sle 
from itzhaopin.items import * 
from itzhaopin.misc.log import * 
class TencentSpider(CrawlSpider): 
  name = "tencent" 
  allowed_domains = ["tencent.com"] 
  start_urls = [ 
    "http://hr.tencent.com/position.php" 
  ] 
  rules = [ # 定义爬取URL的规则 
    Rule(sle(allow=("/position.php\?&start=\d{,4}#a")), follow=True, callback='parse_item') 
  ] 
  def parse_item(self, response): # 提取数据到Items里面,主要用到XPath和CSS选择器提取网页数据 
    items = [] 
    sel = Selector(response) 
    base_url = get_base_url(response) 
    sites_even = sel.css('table.tablelist tr.even') 
    for site in sites_even: 
      item = TencentItem() 
      item['name'] = site.css('.l.square a').xpath('text()').extract() 
      relative_url = site.css('.l.square a').xpath('@href').extract()[0] 
      item['detailLink'] = urljoin_rfc(base_url, relative_url) 
      item['catalog'] = site.css('tr > td:nth-child(2)::text').extract() 
      item['workLocation'] = site.css('tr > td:nth-child(4)::text').extract() 
      item['recruitNumber'] = site.css('tr > td:nth-child(3)::text').extract() 
      item['publishTime'] = site.css('tr > td:nth-child(5)::text').extract() 
      items.append(item) 
      #print repr(item).decode("unicode-escape") + '\n' 
    sites_odd = sel.css('table.tablelist tr.odd') 
    for site in sites_odd: 
      item = TencentItem() 
      item['name'] = site.css('.l.square a').xpath('text()').extract() 
      relative_url = site.css('.l.square a').xpath('@href').extract()[0] 
      item['detailLink'] = urljoin_rfc(base_url, relative_url) 
      item['catalog'] = site.css('tr > td:nth-child(2)::text').extract() 
      item['workLocation'] = site.css('tr > td:nth-child(4)::text').extract() 
      item['recruitNumber'] = site.css('tr > td:nth-child(3)::text').extract() 
      item['publishTime'] = site.css('tr > td:nth-child(5)::text').extract() 
      items.append(item) 
      #print repr(item).decode("unicode-escape") + '\n' 
    info('parsed ' + str(response)) 
    return items 
  def _process_request(self, request): 
    info('process ' + str(request)) 
    return request

实现PipeLine

PipeLine用来对Spider返回的Item列表进行保存操作,可以写入到文件、或者数据库等。

PipeLine只有一个需要实现的方法:process_item,例如我们将Item保存到JSON格式文件中:

pipelines.py

from scrapy import signals 
import json 
import codecs 
class JsonWithEncodingTencentPipeline(object): 
  def __init__(self): 
    self.file = codecs.open('tencent.json', 'w', encoding='utf-8') 
  def process_item(self, item, spider): 
    line = json.dumps(dict(item), ensure_ascii=False) + "\n" 
    self.file.write(line) 
    return item 
  def spider_closed(self, spider): 
    self.file.close( 
)

到现在,我们就完成了一个基本的爬虫的实现,可以输入下面的命令来启动这个Spider

scrapy crawl tencent

爬虫运行结束后,在当前目录下将会生成一个名为tencent.json的文件,其中以JSON格式保存了职位招聘信息。
部分内容如下:

{"recruitNumber": ["1"], "name": ["SD5-资深手游策划(深圳)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15626&keywords=&tid=0&lid=0", "publishTime":
["2014-04-25"], "catalog": ["产品/项目类"], "workLocation": ["深圳"]}

{"recruitNumber": ["1"], "name": ["TEG13-后台开发工程师(深圳)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15666&keywords=&tid=0&lid=0",
"publishTime": ["2014-04-25"], "catalog": ["技术类"], "workLocation": ["深圳"]}

{"recruitNumber": ["2"], "name": ["TEG12-数据中心高级经理(深圳)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15698&keywords=&tid=0&lid=0",
"publishTime": ["2014-04-25"], "catalog": ["技术类"], "workLocation": ["深圳"]}

{"recruitNumber": ["1"], "name": ["GY1-微信支付品牌策划经理(深圳)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15710&keywords=&tid=0&lid=0",
"publishTime": ["2014-04-25"], "catalog": ["市场类"], "workLocation": ["深圳"]}

{"recruitNumber": ["2"], "name": ["SNG06-后台开发工程师(深圳)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15499&keywords=&tid=0&lid=0",
"publishTime": ["2014-04-25"], "catalog": ["技术类"], "workLocation": ["深圳"]}

{"recruitNumber": ["2"], "name": ["OMG01-腾讯时尚视频策划编辑(北京)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15694&keywords=&tid=0&lid=0",
"publishTime": ["2014-04-25"], "catalog": ["内容编辑类"], "workLocation": ["北京"]}

{"recruitNumber": ["1"], "name": ["HY08-QT客户端Windows开发工程师(深圳)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=11378&keywords=&tid=0&lid=0",
"publishTime": ["2014-04-25"], "catalog": ["技术类"], "workLocation": ["深圳"]}

{"recruitNumber": ["5"], "name": ["HY1-移动游戏测试经理(上海)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15607&keywords=&tid=0&lid=0", "publishTime": ["2014-04-25"], "catalog": ["技术类"], "workLocation": ["上海"]}

{"recruitNumber": ["1"], "name": ["HY6-网吧平台高级产品经理(深圳)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=10974&keywords=&tid=0&lid=0", "publishTime": ["2014-04-25"], "catalog": ["产品/项目类"], "workLocation": ["深圳"]}

{"recruitNumber": ["4"], "name": ["TEG14-云存储研发工程师(深圳)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15168&keywords=&tid=0&lid=0", "publishTime": ["2014-04-24"], "catalog": ["技术类"], "workLocation": ["深圳"]}

{"recruitNumber": ["1"], "name": ["CB-薪酬经理(深圳)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=2309&keywords=&tid=0&lid=0", "publishTime": ["2013-11-28"], "catalog": ["职能类"], "workLocation": ["深圳"]}

以上全部内容就是通过Python爬虫框架Scrapy实战之批量抓取招聘信息的全部内容,希望对大家有所帮助,欲了解更多编程知识,请锁定我们的网站,每天都有新的内容发布。

Python 相关文章推荐
处理Python中的URLError异常的方法
Apr 30 Python
python判断给定的字符串是否是有效日期的方法
May 13 Python
pandas数据框,统计某列数据对应的个数方法
Apr 11 Python
Python实现合并同一个文件夹下所有PDF文件的方法示例
Apr 28 Python
详解Python安装scrapy的正确姿势
Jun 26 Python
python实现对csv文件的列的内容读取
Jul 04 Python
实例讲解Python脚本成为Windows中运行的exe文件
Jan 24 Python
Python中的Socket 与 ScoketServer 通信及遇到问题解决方法
Apr 01 Python
Python基础之高级变量类型实例详解
Jan 03 Python
Keras模型转成tensorflow的.pb操作
Jul 06 Python
关于python3 opencv 图像二值化的问题(cv2.adaptiveThreshold函数)
Apr 04 Python
python开发制作好看的时钟效果
May 02 Python
深入理解Python中命名空间的查找规则LEGB
Aug 06 #Python
举例详解Python中yield生成器的用法
Aug 05 #Python
Python中return语句用法实例分析
Aug 04 #Python
python函数形参用法实例分析
Aug 04 #Python
Python简明入门教程
Aug 04 #Python
将Python代码打包为jar软件的简单方法
Aug 04 #Python
python函数局部变量用法实例分析
Aug 04 #Python
You might like
如何在centos8自定义目录安装php7.3
2019/11/28 PHP
php查看一个变量的占用内存的实例代码
2020/03/29 PHP
PHP开发API接口签名生成及验证操作示例
2020/05/27 PHP
Jquery 插件学习实例1 插件制作说明与tableUI优化
2010/04/02 Javascript
js实现点击文本框显示日期选择器特效代码分享
2020/05/21 Javascript
基于JavaScript实现动态创建表格和增加表格行数
2015/12/20 Javascript
Node.js模块封装及使用方法
2016/03/06 Javascript
JavaScript核心语法总结(推荐)
2016/06/02 Javascript
Bootstrap基本样式学习笔记之标签(5)
2016/12/07 Javascript
Bootstrap源码解读媒体对象、列表组和面板(10)
2016/12/26 Javascript
js实现符合国情的日期插件详解
2017/01/19 Javascript
详解vue-router 2.0 常用基础知识点之router.push()
2017/05/10 Javascript
去掉vue 中的代码规范检测两种方法(Eslint验证)
2018/03/21 Javascript
JavaScript捕捉事件和阻止冒泡事件实例分析
2018/08/03 Javascript
vue-cli整合vuex的时候,修改actions和mutations,实现热部署的方法
2018/09/19 Javascript
jQuery删除/清空指定元素的所有子节点实例代码
2019/07/04 jQuery
laypage+SpringMVC实现后端分页
2019/07/27 Javascript
vue-router路由模式详解(小结)
2019/08/26 Javascript
vue项目中微信登录的实现操作
2020/09/08 Javascript
通过实例解析js可枚举属性与不可枚举属性
2020/12/02 Javascript
[02:12]探秘2016国际邀请赛中国区预选赛选手房间
2016/06/25 DOTA
python打造爬虫代理池过程解析
2019/08/15 Python
Python 获取numpy.array索引值的实例
2019/12/06 Python
总结python 三种常见的内存泄漏场景
2020/11/20 Python
Glamest意大利:女性在线奢侈品零售店
2019/04/28 全球购物
澳大利亚当地社区首选的光学商店:1001 Optical
2019/08/24 全球购物
新学期开学寄语
2014/01/18 职场文书
大专生自我评价
2014/01/28 职场文书
家庭教育的心得体会
2014/09/01 职场文书
公司领导班子对照检查材料
2014/09/24 职场文书
搭讪开场白台词大全
2015/05/28 职场文书
八年级作文之友谊
2019/12/02 职场文书
mysql部分操作
2021/04/05 MySQL
Mysql 如何实现多张无关联表查询数据并分页
2021/06/05 MySQL
Python自动操作神器PyAutoGUI的使用教程
2022/06/16 Python
pytorch实现加载保存查看checkpoint文件
2022/07/15 Python