爬取智联招聘的网址:https://sou.zhaopin.com/?pageSize=60&jl=489&kw=python&kt=3

上一篇博客爬取了前程无忧的职位招聘信息,总体来说前程无忧的网站信息并不难爬取,前程无忧的网站并没有ajax,直接请求网站就能获得职位信息,但是智联招聘的页面涉及到ajax,直接get网站的url获取不到任何有用的信息,这也是反爬虫的一种手段,因此我们需要借助selenium模拟浏览器访问智联招聘网站。在爬取的过程中有一些非常有意思的问题,下面我会把这些问题以及解决的办法一一列举出来。

1.首先我在分析职位详情(注意不是职位列表页面)网页的结构的时候遇到的一个问题,在分析网页的源码构造xpath的时候,发现无论怎么修改xpath及css选择器,获得的数据都是空([ ])。原来使用爬虫获取到的网页源码与我们在网页上看到的源码不一样,使用scrapy请求网站的时候,网页会将class属性替换掉,所以直接通过网页上的源码来构造xpath和css选择器是不可行的。正确的做法是通过scrapy shell +""(请求的网址),打开浏览器查看正确的class属性,然后再构造xpath及css选择器。2.然后就是涉及到ajax的职位列表页面,细心一点的同学会发现当输入网址之后,下方的职位列表会加载一段时间才会展示出来,如果我们直接get网页的源码,不会得到任何有用的信息,使用scrapy shell + ""(职位列表页面) 可以看到在浏览器中不会显示查询之后的结果,因此我们需要使用selenium模拟获取职位列表页面的所有信息。3.编写使用selenium模拟点击下一页的中间件,职位的详细信息通过scrapy系统的中间件下载,这就会产生数据丢失的问题,因为点击下一页这个动作运行的非常快,那么在点击下一页之后,scrapy会接受该页面的所有职位链接,一个页面有60个职位链接,我试验的时候基本上当selenium中间件点击到将近30页的时候,第一页的所有职位链接才会爬取完,那么就有一个问题,现在scrapy已经接受了几百个职位的url,在请求这些url的时候很有可能会丢掉大部分的数据,造成很多页面没有爬取的漏洞,解决的办法也很简单,设置网页跳转的限制,当一个网页的数据爬取的差不多的时候,比如爬取了50多条数据的时候就能跳转到下一页。

代码思路:1.定义一个中间件处理两种不同的请求,点击下一页或者下载详情页。2.抽取职位列表的所有url,通过scrapy系统的中间件请求职位的详细信息页,防止覆盖掉senium的职位列表的url。3.判断该职位列表页的数据爬取了多少条,如果超过50页,那么点击到下一页。4.将数据保存到数据库

一.创建项目

(1)

scrapy startproject zhipinSpider

创建一个名称为zhipinSpider的项目

(2)手动创建job_detail.py文件,实现爬虫的主要逻辑

二.项目配置

(1)编写items文件

import scrapyclass ZhipinspiderItem(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()title = scrapy.Field()salary = scrapy.Field()detail = scrapy.Field()

定义三个字段,分别用来保存职位的标题,薪资,职位的要求

(2)编写pipelines文件

import sqlite3
db = sqlite3.connect("./../../zhi.db")
cursor = db.cursor()class ZhipinspiderPipeline(object):def process_item(self, item, spider):cursor.execute("insert into jobs(title, salary, detail) values (?,?,?)",[item["title"],item["salary"],item["detail"]])db.commit()

将数据保存到sqlite数据库中,也可以保存到MySQL数据库中,写法类似

(3)编写selenium模拟中间件

class SeleniumMiddleware(object):def __init__(self):self.options = Options()# self.options.add_argument('-headless')self.browser = webdriver.Firefox(executable_path="D:\geckodriver\geckodriver.exe",firefox_options=self.options)# self.option = Options()# self.option.add_argument('-headless')# self.browser1 = webdriver.Firefox(executable_path="D:\geckodriver\geckodriver.exe",firefox_options=self.options)def process_request(self, request, spider):"""通过meta携带的数据判断应该跳转到下一页还是下载详情页这里没有处理详情页的函数,所以当下载详情页的时候会调用scrapy系统的中间件,也就不会覆盖跳                转页面的url:param request: :param spider: :return: """if int(request.meta["page"]) == 0:self.browser.get(request.url)self.browser.execute_script("window.scrollTo(0,document.body.scrollHeight)")time.sleep(1)pages = self.browser.find_element_by_css_selector('button.btn:nth-child(8)')pages.click()time.sleep(5)return HtmlResponse(url=self.browser.current_url,body=self.browser.page_source,encoding="utf-8",request=request)if int(request.meta["page"]) == 2:# 不需要get网页的url否则浏览器会在第一第二页之间来回跳转# self.browser.get(self.browser.current_url)self.browser.execute_script("window.scrollTo(0,document.body.scrollHeight)")time.sleep(1)pages = self.browser.find_element_by_css_selector('button.btn:nth-child(8)')pages.click()time.sleep(5)return HtmlResponse(url=self.browser.current_url,body=self.browser.page_source,encoding="utf-8",request=request)

(4)配置setting文件

启用selenium中间件

DOWNLOADER_MIDDLEWARES = {'zhipinSpider.middlewares.SeleniumMiddleware': 543,
}

启用管道文件

ITEM_PIPELINES = {'zhipinSpider.pipelines.ZhipinspiderPipeline': 300,
}

下载延迟

DOWNLOAD_DELAY = 3
RANDOMIZE_DOWNLOAD_DELAY = True

(5)编写spider文件

爬虫的主要逻辑

import scrapy
from scrapy import Request
import lxml.html
from zhipinSpider.items import ZhipinspiderItem
import sqlite3db = sqlite3.connect("./../../zhi.db")
cursor = db.cursor()i = 0def select_from_sql():""":return: 当前数据库中数据的总数"""count = cursor.execute("select * from jobs")return len(count.fetchall())class JobDetailSpider(scrapy.Spider):name = "jobSpider"def start_requests(self):url_str = "https://sou.zhaopin.com/?pageSize=60&jl=489&kw=python&kt=3"yield Request(url=url_str,callback=self.parse,meta={"page":"0"})def parse(self, response):"""抽取出包含职位url的html,并通过函数分离url:param response: :return: """html_str = response.xpath('//div[@class="listItemBox clearfix"]').extract()for html in html_str:job_url = self.parse_one_job(html)yield Request(url=job_url,callback=self.parse_job_text,meta={"page":"1"})def parse_one_job(self,html):"""分理处html中的职位url:param html: :return: """xtree = lxml.html.fromstring(html)job_url = xtree.xpath('//div[@class="jobName"]/a/@href')[0]return job_urldef parse_job_text(self,response):global icount = select_from_sql()# 使用selenium模拟的结果# title = response.xpath('//ul/li/h1/text()').extract()# detail = response.xpath('//div[@class="pos-ul"]/p/text()').extract()# salary = response.xpath('//div[@class="l info-money"]/strong/text()').extract()# 使用view(response)获得的结果title = response.xpath('//div[@class="inner-left fl"]/h1/text()').extract_first()salary = response.xpath('//ul[@class="terminal-ul clearfix"]/li/strong/text()').extract_first()detail = response.xpath('//div[@class="tab-inner-cont"]/*/text()').extract()detail_span = response.xpath('//div[@class="tab-inner-cont"]/p/span/text()').extract()if detail_span is not None:detail = detail_span + detailcontents = ""for content in detail:contents += contentcontents = ' '.join(contents.split())item = ZhipinspiderItem()item["title"] = titleitem["salary"] = salaryitem["detail"] = contents# 判断有没有爬取完当前页面的职位信息(是否达到分页的条件)if count - i > 58:i = countyield Request(url="http://www.baidu.com", callback=self.parse, meta={"page": "2"}, dont_filter=True)yield item

这里分析职位要求的xpath之所以有两个是因为智联招聘所有的职位要求信息,它的html标签会有个别不一样的情况,这里我直接定义了两个xpath处理两种情况,将两种情况得到的信息合并,这样就会减少爬取不到职位要求信息的情况。另外最后这个请求url之所以使用www.baidu.com是因为这里我们不需要使用其他的url,只需要点击下一页就行了,这里的url只作为占位使用。

总结:爬取智联招聘难点在于如何爬取ajax数据,如何使用selenium模拟区分职位列表页跟职位详情页,以及为了防止数据丢失而查询数据库数据的条数,判断是否达到了分页的条件。

scrapy由浅入深(三) selenium模拟爬取ajax动态页面(智联招聘)相关推荐

  1. 关于scrapy爬取51job网以及智联招聘信息存储文件的设置

    通过这两个文件,,可以存储数据(但是注意在爬虫文件中也在写相应的代码 具体参考51job网和智联招聘两个文件) 1.先设置items文件 # -*- coding: utf-8 -*-# Define ...

  2. scrapy实战5 POST方法抓取ajax动态页面(以慕课网APP为例子):

    在手机端打开慕课网,fiddler查看如图注意圈起来的位置 经过分析只有画线的page在变化 上代码: items.py 1 import scrapy 2 3 4 class ImoocItem(s ...

  3. python爬百度新闻_13、web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息...

    crapy爬取百度新闻,爬取Ajax动态生成的信息,抓取百度新闻首页的新闻rul地址 有多网站,当你浏览器访问时看到的信息,在html源文件里却找不到,由得信息还是滚动条滚动到对应的位置后才显示信息, ...

  4. 通过爬取天猫商品评论实例分析Python爬取ajax动态生成的数据

    本文主要通过爬取天猫商品kindle的评论为例来说明利用python爬取ajax动态生成的数据的方式,本文使用的工具如下: 工具 chrome浏览器[寻找评论的动态链接] python3.5[执行代码 ...

  5. C#利用phantomJS抓取AjAX动态页面

    在C#中,一般常用的请求方式,就是利用HttpWebRequest创建请求,返回报文.但是有时候遇到到动态加载的页面,却只能抓取部分内容,无法抓取到动态加载的内容. 如果遇到这种的话,推荐使用phan ...

  6. python爬取微博动态页面id、内容、评论点赞数存入MongoDB 详解

    目录 前情提要 一.具体操作及注意事项 1.获取解析json文件 2.获取微博内容 3.存入MongoDB数据库 总代码及结果展示 前情提要 本次爬取有未解决的问题 1.用urlencode合成的ur ...

  7. python翻页功能url不变_爬取Ajax动态加载和翻页时url不变的网页

    这两天投了一家公司的爬虫实习生,笔试题是完成一个爬虫的小需求.网站没有什么反爬的高级技巧.但是有非常常见的,并不是针对我们爬虫的,却让我们新手很难理解的ajax动态加载技术和乍一看不明白的翻页时不变的 ...

  8. python爬取ajax动态内容肯德基门店,Python爬虫如何爬取KFC地址

    随着人们生活水平的提高,肯德基这类的快餐消费的十分火爆,成为小朋友和年轻人的最爱,我们到一个地方想要找到肯德基店面,会根据导航获取肯德基地址,那你知道我们也可以使用python爬虫获取KFC地址吗?我 ...

  9. java使用htmlunit+Jsoup爬虫,爬取ajax动态数据

    先贴一段代码 WebClient web = new WebClient(BrowserVersion.FIREFOX_38);try {long startTime = System.current ...

最新文章

  1. 5个短小精悍的 Python 趣味脚本,太赞了,非常适合小白上手!
  2. 强制结束后台作业(SAP SM37 SM35 SM50)
  3. 在Windows 7 下使用Visual Studio 2010 编写自动申请管理员权限运行的程序
  4. 10万奖金!探索图像盲降噪新方式,旷视2022 MegCup炼丹大赛等你来战
  5. SAP UI5 scroll down to get more
  6. Educational Codeforces Round 94 (Rated for Div. 2)
  7. 今天的春天到了的p2psearcher
  8. java可以继承私有的,关于java:继承中的私有方法
  9. 加上mvc:resources后controller访问404
  10. spring 之 AOP 理解
  11. 保存同一个H264视频流,第一个文件能播放,第二个播放不了。为什么
  12. Java中String类型,int类型,double类型相互转换
  13. JS点击按钮打开新的独立页面
  14. Linux 中防火墙命令
  15. win10专业版无法安装更新解决方法
  16. ANSYS ICEM CFD三维非结构网络生成实例——教室全新风送风与排风
  17. ubuntu命令行查看dns_Dog-用于DNS查询的命令行工具
  18. win7-32位系统,不能运行flash,解决方法。
  19. 陌上花开,可缓缓归矣——2016年校招总结
  20. (记录)绝对值的实现

热门文章

  1. QCC51XX---KSP in MDE
  2. 美摄SDK玩转年轻潮拍,成视音频平台差异化黑马
  3. 杰理之批量生产通话效 果忽大忽小,有 电流声【篇】
  4. 公众号历史文章分类汇总
  5. Basware推出人工智能驱动的虚拟助理,便于自动化采购和处理订单
  6. 看了变形金刚的首映 ^_^
  7. Automapper如何全局配置map条件过滤null值空值对所有映射起效
  8. Unity 实现简单的发射子弹功能
  9. Git批量删除本地分支
  10. 植物风场运动模拟(Wind Animations for Trees)