周末折腾了好久,终于成功把拉钩网的招聘信息爬取下来了。现在总结一下!

环境: windows 8.1 + python 3.5.0

首先使用 scrapy 创建一个项目:

E:\mypy> scrapy startproject lgjob

创建后目录结构:

E:\mypy\lgjob
----scrapy.cfg
----lgjob
     |-------__pycache__
     |-------spiders
          |-------__pycache__
          |-------__init__.py
     |-------__init__.py
     |-------items.py
     |-------middlewares.py
     |-------pipelines.py
     |-------settings.py

网络上有一中方法是读取 json 格式的,如下图:

这种方法是比较完整的,每个公司的招聘信息都很完整。拉钩网默认每页显示15个公司,最大30页。json格式比较规范,但是测试过程中一直读取不到网页记录,提示 “ 操作频繁 ” 。所以打算用传统的方法,即找出每页的规律,确认页码的位置。而内容则是直接读取 html 格式的节点取记录。

我们从拉钩首页点击某一个分类,比如我点击了 “java” ,接下来就跳转到各个公司的招聘信息列表,拉钩每页显示15个公司。看看网址为 : https://www.lagou.com/zhaopin/Java/?labelWords=label,网址中看到关键字 “java” 了吗?替换成 “DBA” 回车查询也是可以的。再点击分页,也发现分页页码显示规律了!

如下为搜索 DBA 的第二页 和第五页: 

https://www.lagou.com/zhaopin/DBA/2/?filterOption=3

https://www.lagou.com/zhaopin/DBA/5/?filterOption=3

按 F12 再右键某个职位名称:

每页15个公司的招聘信息都显示出来了,这里不需要要查看职位的详细信息,所以在查找职位页面就可以把基础的信息爬取下来。职位在列表标签 “li” 显示是有规律和固定格式的,所以等下爬取也是每页去爬取,每页循环读取网页标签 “<li class="con_list_item default_list"…………” 的各个元素记录。

主要的项目文件,默认都已经创建了:(E:\mypy\lgjob\lgjob\)

items.py : 爬取的主要目标就是从非结构性的数据源提取结构性数据,例如网页。 Scrapy提供 Item 类来满足这样的需求。

pipelines.py :  当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理(如保持到数据库)。

settings.py : 设定为代码提供了提取以key-value映射的配置值的的全局命名空间(namespace)。 设定可以通过下面介绍的多种机制进行设置。

还有一个主要的解析主文件,需要手动创建,放到项目的 spiders (E:\mypy\lgjob\lgjob\spiders)目录中,本次测试创建的文件名为 : main.py

现在数据库创建一个表,本次测试使用的是 sql server 数据库保存爬取数据:

CREATE TABLE [dbo].[lgjob]([companyfullname] [varchar](50) NULL,[positionname] [varchar](30) NULL,[salary] [varchar](20) NULL,[workyear] [varchar](20) NULL,[education] [varchar](20) NULL,[city] [varchar](20) NULL,[district] [varchar](20) NULL,[financestage] [varchar](50) NULL,[industryfield] [varchar](100) NULL,[firsttype] [varchar](50) NULL,[positionlables] [varchar](100) NULL
) ON [PRIMARY]
GO

【items.py】 

# -*- coding: utf-8 -*-
# python 3.5import scrapyclass LgjobItem(scrapy.Item):companyfullname = scrapy.Field()positionname = scrapy.Field()salary = scrapy.Field()workyear = scrapy.Field()education = scrapy.Field()city = scrapy.Field()district = scrapy.Field()financestage = scrapy.Field()industryfield = scrapy.Field()firsttype = scrapy.Field()positionlables = scrapy.Field()

【pipelines.py】结果保持到数据库

# -*- coding: utf-8 -*-
# python 3.5import pymssql
from scrapy.conf import settingsclass LgjobPipeline(object):def __init__(self):self.conn = pymssql.connect(host = settings['MSSQL_HOST'],  user = settings['MSSQL_USER'],  password = settings['MSSQL_PASSWD'],  database = settings['MSSQL_DBNAME'] )self.cursor = self.conn.cursor()self.cursor.execute('truncate table lgjob;')self.conn.commit()def process_item(self, item, spider):try:self.cursor.execute("""INSERT INTO lgjob( companyfullname , positionname, salary, workyear, education, city,district, financestage, industryfield, firsttype, positionlables)VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",(item['companyfullname'],item['positionname'],item['salary'],item['workyear'],item['education'],item['city'],item['district'],item['financestage'],item['industryfield'],item['firsttype'],item['positionlables']))self.conn.commit()except pymssql.Error as e:print(e)return item

【settings.py】配置参数(如数据库连接信息)

# -*- coding: utf-8 -*-# Scrapy settings for lgjob project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
#     http://doc.scrapy.org/en/latest/topics/settings.html
#     http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html
#     http://scrapy.readthedocs.org/en/latest/topics/spider-middleware.htmlBOT_NAME = 'lgjob'SPIDER_MODULES = ['lgjob.spiders']
NEWSPIDER_MODULE = 'lgjob.spiders'MSSQL_HOST = 'HZC'
MSSQL_USER = 'kk'
MSSQL_PASSWD = 'kk'
MSSQL_DBNAME = 'Myspider'ITEM_PIPELINES = {'lgjob.pipelines.LgjobPipeline': 300,
}

【main.py】 (自建的)

# -*- coding: utf-8 -*-
# python 3.5
# file path ../lgjob/lgjob/spiders/main.py
# perform:  scrapy crawl lgjobimport json
import scrapy
from lgjob.items import LgjobItem
from bs4 import BeautifulSoupclass MainLgjob(scrapy.Spider):name = 'lgjob'domain = ['lagou.com']start_url = ['https://www.lagou.com/zhaopin/']curpage = 1totalPageCount = 6keyword = "DBA"cururl = "https://www.lagou.com/zhaopin/%s/%s/?filterOption=3"%(keyword,curpage)def start_requests(self):return [scrapy.http.FormRequest(self.cururl,callback=self.parse)]def parse(self, response):soup = BeautifulSoup(response.body,'html.parser',from_encoding='utf-8')body_ul = soup.find_all("li" ,class_="con_list_item default_list")  for li in body_ul:item = LgjobItem()arg1 = li.find("div",class_="position").find("div",class_="p_top").find("em").get_text(strip=True)arg2 = li.find("div",class_="position").find("div",class_="li_b_l").get_text(" / ",strip=True)arg3 = li.find("div",class_="company").find("div",class_="industry").get_text(strip=True)arg4 = li.find("div",class_="list_item_bot").find("div",class_="li_b_r").get_text(strip=True)item['companyfullname'] = li.find("div",class_="company").find("div",class_="company_name").find("a").get_text(strip=True)item['positionname'] = li.find("div",class_="position").find("div",class_="p_top").find("h3").get_text(strip=True)item['salary'] = ((arg2 + "/").split('/')[0]).strip()item['workyear'] = ((arg2 + "/").split('/')[1]).strip()item['education'] = ((arg2 + "/").split('/')[2]).strip()item['city'] = (arg1+'·'+arg1).split('·')[0]item['district'] = (arg1+'·'+arg1).split('·')[1]item['industryfield'] = ((arg3 + "/").split('/')[0]).strip()item['financestage'] = ((arg3 + "/").split('/')[1]).strip()item['positionlables'] = arg4.strip('“').strip('”')item['firsttype'] = li.find("div",class_="list_item_bot").find("div",class_="li_b_l").get_text(",",strip=True)yield itemif self.curpage < self.totalPageCount:self.curpage += 1self.cururl = "https://www.lagou.com/zhaopin/%s/%s/?filterOption=3"%(self.keyword,self.curpage)yield scrapy.http.FormRequest(self.cururl,callback=self.parse)

main.py 这个脚本有几个缺点,还没完善:

1. 总的页码需要手动定义(可以参考第一张图中的总记录计算总页码)

2. 其他筛选条件没有(只有搜索的岗位名称,城市则是在拉钩上设置的默认地方)

3. 访问到第6页时,则出现 302 重定向,爬虫终止结束了!

现在解决 1和3 的问题。


1. 总页数可以从web显示的页码那里获取(或者底部),如下图




定位到标签中,获取总页码:

page_num= soup.find("div" ,class_="page-number").find("span" ,class_="span totalNum").get_text(strip=True)

self.totalPageCount = int(page_num)

 302 的问题,请求时添加 cookie,使其可以访问更多页。

登录之后找到cookie,cookie内有很多 “属性=值,属性=值…”,稍后都改为“键: 值,键: 值…” 。同样也可以看到其他 headers 信息。

【settings.py】此时的配置文件内容改为如下(cookie都改为“key-value”格式,顺便也添加了header)

# -*- coding: utf-8 -*-# Scrapy settings for lgjob projectBOT_NAME = 'lgjob'SPIDER_MODULES = ['lgjob.spiders']
NEWSPIDER_MODULE = 'lgjob.spiders'MSSQL_HOST = 'HZC'
MSSQL_USER = 'kk'
MSSQL_PASSWD = 'kk'
MSSQL_DBNAME = 'Myspider'ITEM_PIPELINES = {'lgjob.pipelines.LgjobPipeline': 300,
}USER_AGENT = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36"#以下为使用 cookie 时添加. 不使用的话在文件 MainLgjob 注释
ROBOTSTXT_OBEY = False #不遵守Robot协议
DOWNLOAD_DELAY = 3 #延迟
COOKIES_ENABLED = True #启用 cookieHEADERS = {'Connection': 'keep-alive','User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36'
}
META = {'dont_redirect': True,'handle_httpstatus_list': [301, 302]
}
COOKIES = {'user_trace_token': 'xxxxxxxxxxxxxxxxxxxxxxxxxx','LGUID': 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'sensorsdata2015jssdkcross': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx','_qddaz': 'QD.vr42sh.xxxxxxxxxxxxx.xxxxxxxxxxxxx','JSESSIONID': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx','_putrc': 'xxxxxxxxxxxxxxxxxxxxxxxxxx','login': 'true','unick': 'xxxxxxxxxxxxxxxxxxxxxxxxxx','showExpriedIndex': '1','showExpriedCompanyHome': '1','showExpriedMyPublish': '1','hasDeliver': '49','SEARCH_ID': 'xxxxxxxxxxxxxxxxxxxxxxxxxx','index_location_city': 'xxxxxxxxxxxxx','Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6': 'xxxxxxxxxxxxx','Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6': 'xxxxxxxxxxxxx','_ga': 'GA1.2.437277179','LGRID': 'xxxxxxxxxxxxx'
}

【main.py】请求信息 scrapy.http.FormRequest 把 cookie 和 header 也加上去

# -*- coding: utf-8 -*-
# python 3.5
# file path ../lgjob/lgjob/spiders/main.py
# perform:  scrapy crawl lgjobimport json
import scrapy
from lgjob.items import LgjobItem
from bs4 import BeautifulSoup
from scrapy.conf import settingsclass MainLgjob(scrapy.Spider):name = 'lgjob'domain = ['.lagou.com']start_url = ['https://www.lagou.com/zhaopin/']#不使用cookie,注释 Request的 ,headers=self.headers, cookies=self.cookies, meta=self.metameta = settings['META']cookies = settings['COOKIES']headers = settings['HEADERS']curpage = 1totalPageCount = 1keyword = u"DBA"cururl = "https://www.lagou.com/zhaopin/%s/%s/?filterOption=3"%(keyword,curpage)def start_requests(self):return [scrapy.http.FormRequest(self.cururl,callback=self.parse,headers=self.headers, cookies=self.cookies, meta=self.meta)]def parse(self, response):soup = BeautifulSoup(response.body,'html.parser',from_encoding='utf-8')body_ul = soup.find_all("li" ,class_="con_list_item default_list")#每次获取总页码page_num= soup.find("div" ,class_="page-number").find("span" ,class_="span totalNum").get_text(strip=True)self.totalPageCount = int(page_num)for li in body_ul:item = LgjobItem()arg1 = li.find("div",class_="position").find("div",class_="p_top").find("em").get_text(strip=True)arg2 = li.find("div",class_="position").find("div",class_="li_b_l").get_text(" / ",strip=True)arg3 = li.find("div",class_="company").find("div",class_="industry").get_text(strip=True)arg4 = li.find("div",class_="list_item_bot").find("div",class_="li_b_r").get_text(strip=True)item['companyfullname'] = li.find("div",class_="company").find("div",class_="company_name").find("a").get_text(strip=True)item['positionname'] = li.find("div",class_="position").find("div",class_="p_top").find("h3").get_text(strip=True)item['salary'] = ((arg2 + "/").split('/')[0]).strip()item['workyear'] = ((arg2 + "/").split('/')[1]).strip()item['education'] = ((arg2 + "/").split('/')[2]).strip()item['city'] = (arg1+'·'+arg1).split('·')[0]item['district'] = (arg1+'·'+arg1).split('·')[1]item['industryfield'] = ((arg3 + "/").split('/')[0]).strip()item['financestage'] = ((arg3 + "/").split('/')[1]).strip()item['positionlables'] = arg4.strip('“').strip('”')item['firsttype'] = li.find("div",class_="list_item_bot").find("div",class_="li_b_l").get_text(",",strip=True)yield itemif self.curpage < self.totalPageCount:self.curpage += 1self.cururl = "https://www.lagou.com/zhaopin/%s/%s/?filterOption=3"%(self.keyword,self.curpage)yield scrapy.http.FormRequest(self.cururl,callback=self.parse,headers=self.headers, cookies=self.cookies, meta=self.meta)

执行爬取命令: scrapy startproject lgjob

爬取过程中命令行页面会显示每个属性值,本人电脑执行大约每5秒完成拉钩一页15个公司的数据处理。

最终结果如下:

参考:

Beautiful Soup 4.2.0 文档

Scrapy 0.24 文档

【python爬虫02】使用Scrapy框架爬取拉勾网招聘信息

【图文详解】scrapy爬虫与动态页面——爬取拉勾网职位信息(1)

Python爬虫系列之----Scrapy(八)爬取豆瓣读书某个tag下的所有书籍并保存到Mysql数据库中去

Scrapy中使用cookie免于验证登录和模拟登录

Python scrapy 爬取拉勾网招聘信息相关推荐

  1. 【python爬虫02】使用Scrapy框架爬取拉勾网招聘信息

    使用Scrapy框架爬取拉勾网招聘信息 最近接触了Scrapy爬虫框架,简单写了个爬虫爬取拉钩网的招聘信息,加深对Scrapy框架的理解,不得不说Scrapy框架其实还是蛮方便的,就像爬虫流水线一样, ...

  2. Python搭建代理池爬取拉勾网招聘信息

    先来看一张图了解下爬虫 实现功能 多线程爬取拉勾网招聘信息 维护代理 ip 池 搭建 node 服务器 Taro 使用 echarts 做数据分析 1.多线程爬取拉勾网招聘信息 Tip:涉及知识 1. ...

  3. Python爬虫实战之一 - 基于Requests爬取拉勾网招聘信息,并保存至本地csv文件

    Python爬虫实战之二 - 基于Requests抓取拉勾网招聘信息 ---------------readme--------------- 简介:本人产品汪一枚,Python自学数月,对于小白,本 ...

  4. 什么你还不知道招聘信息,小唐来教你——最新2021爬取拉勾网招聘信息(一)

    文章目录 前言 一.准备我们的库 二.分析分析 三. 代码 四.数据展示 小唐的心路历程 上一篇:没有啦! 下一篇:什么你还不知道招聘信息,小唐来教你--最新2021爬取拉勾网招聘信息(二) 前言 有 ...

  5. scrapy爬取——阿里招聘信息

    scrapy爬取--阿里招聘信息 爬取网站地址: https://job.alibaba.com/zhaopin/positionList.htm 1.创建项目 进入项目目录 输入cmd进入都是窗口创 ...

  6. 什么你还不知道招聘信息,小唐来教你——最新2021爬取拉勾网招聘信息(二)

    文章目录 前言 一.准备我们的库 二.数据清洗 三.核密度图及词云制作 四.完整代码 五.扩展 上一篇:什么你还不知道招聘信息,小唐来教你--最新2021爬取拉勾网招聘信息(一) 下一篇:没有拉! 前 ...

  7. scrapy 爬取拉勾网职位信息

    需求:1.使用python爬虫框架,爬取拉勾网职位信息, 2.将爬取的职位信息存储到json格式的文件中 3.将爬取的数据进行数据分析 1.图片中的链接是职位列表页的链接,进行翻页,该链接没有变化,无 ...

  8. Python爬取拉勾网招聘信息

    此代码运行建议Python3,省却中文编码的麻烦 遇到的几个问题: (1)拉钩网的数据是通过js的ajax动态生成,所以不能直接爬取,而是通过post'http://www.lagou.com/job ...

  9. 什么样的人才能做互联网产品经理【爬取拉勾网招聘信息】

    分析目的 在这个校招如火如荼的季节,相信大家对各种招聘网站已经再熟(yan)悉(fan)不过了,各种java开发.算法.前端.后端岗位真的是琳琅满目,而我觉得其中与我的个人兴趣和专业匹配度最高的就是产 ...

  10. 使用python scrapy爬取全国小区信息(包括小区价格,经纬度,面积,户数等),并保存到mysql和excel

    目标 此次爬取的网站是楼盘网,因为只爬取小区信息,所以先从深圳小区(http://sz.loupan.com/community/)网页入手分析,然后发散爬取至全国. 爬取的信息包括 省,所属市,所属 ...

最新文章

  1. 在Python中使用lightgbm
  2. 三十九、@staticmethod、@classmethod和@property类装饰器
  3. 8月语言排行:C#继续呈现增长态势
  4. jQuery选择器案例之——index.js
  5. vue学习经验分享,在这个大前端时代,你再不会vue就out啦
  6. android sugar框架 使用,数据库框架Sugar的使用
  7. 苹果iOS 11.3.1正式发布,修复iPhone 8触屏bug
  8. 如何看药博士系统服务器的站点,药博士系列管理软件
  9. 机器翻译和自动译后编辑
  10. 管理“项目”之人际关系篇
  11. 小码哥学习感想第一天
  12. 四极管:京东物流“后牌照”战略:8月底开放 或分拆
  13. openjudge 1.9.14 铺地毯
  14. MongoDB笔记之简单的增删改查
  15. word2016:使用多级列表+样式表,自动生成插图清单
  16. 机器学习中的启发式算法(heuristic algorithm)
  17. 阿里云主机Linux服务器配置步骤
  18. 给大家分享下做短视频运营的干货
  19. 秋雨,在迷乱的思绪中飞扬
  20. c语言oj猜灯谜,元宵节灯谜——文学典籍类

热门文章

  1. gcd euclid_使用EUCLID的算法找到两个数字的GCD(最大公约数)
  2. Unity初识之阿语显示
  3. 机器学习实战(Machine Learning in Action)学习笔记————08.使用FPgrowth算法来高效发现频繁项集...
  4. 室内定位蓝牙信标安装规划问题
  5. Arno,第一个NFV开源平台
  6. 1002内容预告:软件中国年度大盘点
  7. IC卡,ID卡,M1卡等各种卡扫盲篇
  8. 30天自制操作系统 学习笔记1
  9. BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组
  10. 零基础搭建电影网站教程——一、域名与服务器