博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python | 数据分析实战Ⅰ
阅读量:6701 次
发布时间:2019-06-25

本文共 4698 字,大约阅读时间需要 15 分钟。

“Talk is cheap,Show me the code.”翻译为中文是“废话少说,放码过来。”我觉得可谓信达雅。

在编程之路上,实践的重要性无可比拟。这也是很多同学感觉学了很多,但还是不会写代码的原因;也是很多有意转行的人士,自学了大半年,仍不见起色的缘故。

leoxin在知识星球发起一项活动:目标是爬取拉钩网的招聘信息以及链家的房产信息,然后对数据进行清洗和存储,并分析其数据下的价值,最后用可视化的形式表现出来。 我觉得难度适中,循序渐进,对于不同身份角色的学习人群都大有裨益。

下面我来写一写在第一阶段的一些学习操作总结和感受。

爬虫

构思/准备部分

首先打开,我初步选择的是Java-上海

Step1

打开浏览器开发者工具,观察Network部分的内容,首先点进Doc部分,看看服务器给我们返回了哪些文本内容。

在Preview预览中,我们可以看到,大部分都是一些公共视图框架和公共JS代码,没有核心数据。

那么这时我们就应该猜测,网站可能是首先渲染一个公共框架,然后再通过Ajax发送请求去获得数据,再在页面上显示获取的数据。

Step2

通过Step1的思考和猜测,大致确定了数据是异步获取的。做过一点web的应该都想得到这一点,因为即使是反爬,也要按照基本法啊!应该不会使用多么多么匪夷所思的黑科技(如果真的出现了,那是我太菜了的原因(っ °Д °;)っ)

这时点开XHR按钮,XHR全称XMLHttpRequest,有什么作用呢?Ajax通过XMLHttpRequest对象发出HTTP请求,得到服务器返回的数据。

通过预览我们可以发现,我们需要的数据都出现在positionAjax请求下返回的数据中,参见content-positionResult-result中。

那么该如何伪造请求?

点进Headers,首先发现Request Method的值是POST,确定了我们提交请求的方式。然后看看Request Headers中的字段。

发现有好多条。

Accept:application/json, text/javascript, */*; q=0.01Accept-Encoding:gzip, deflate, brAccept-Language:zh-CN,zh;q=0.9Connection:keep-aliveContent-Length:23Content-Type:application/x-www-form-urlencoded; charset=UTF-8Cookie:XXXHost:www.lagou.comOrigin:https://www.lagou.comReferer:https://www.lagou.com/jobs/list_Java?px=default&city=%E4%B8%8A%E6%B5%B7User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36X-Anit-Forge-Code:0X-Anit-Forge-Token:NoneX-Requested-With:XMLHttpRequest复制代码

通过筛选,我们选取其中有用的几条,构建自己的请求头。(那么怎么知道哪些是有用的呢?首先筛除语言,编码之类的,这些的影响一般都是比较小的;接着在剩下的字段中进行尝试,等以后有经验了,自然能准确选取有价值的字段)

由于是POST的请求方式,那么势必会向服务器提交一些数据,可以看到表单信息:

first:truepn:1kd:Java复制代码

实现/代码部分

Step1

在进行上述分析后,基本已经准备得差不多了。这时可以先简单构建一下我们的Proxy类。

class Proxy():    def __init__(self):        self.MAX=5 #最大嗅探次数        self.headers={            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",            "Referer":"https://www.lagou.com/jobs/list_Java?px=default&city=%E4%B8%8A%E6%B5%B7",            "X-Anit-Forge-Code":"0",            "X-Anit-Forge-Token":"None",            "X-Requested-With":"XMLHttpRequest"        }    def getPage(self,url,data):        FAILTIME=0 #访问失败次数        try:            result=requests.post(url,headers=self.headers,data=data)            result.encoding = "utf-8"            return result        except:            FAILTIME+=1            if FAILTIME==self.MAX:                print("访问错误")                return ''复制代码

上文中提到,发现Ajaxposition返回的content-positionResult-result数据,数据格式是一个数组里有15条数据,每条数据的格式是一个字典,具体如下:

adWord:9appShow:0approve:1businessZones:["唐镇", "唐镇", "曹路", "曹路"]city:"上海"companyFullName:"招商银行股份有限公司信用卡中心"companyId:6796companyLabelList:["金融科技银行", "技术创新驱动", "奋斗独立改变", "一年两次调薪"]companyLogo:"i/image2/M00/25/D7/CgoB5lodmL2AJHxrAABieRjcJjU514.png"companyShortName:"招商银行信用卡中心"companySize:"2000人以上"createTime:"2018-03-09 09:14:30"deliver:0district:"浦东新区"education:"本科"explain:nullfinanceStage:"上市公司"firstType:"开发/测试/运维类"formatCreateTime:"09:14发布"gradeDescription:nullhitags:nullimState:"today"industryField:"移动互联网,金融"industryLables:[]isSchoolJob:0jobNature:"全职"lastLogin:1520581074000latitude:"31.247248"linestaion:nulllongitude:"121.673868"pcShow:0plus:nullpositionAdvantage:"五险一金,职位晋升,各类补贴"positionId:2762378positionLables:["项目管理", "j2ee", "架构"]positionName:"Java技术经理"promotionScoreExplain:nullpublisherId:73936resumeProcessDay:1resumeProcessRate:100salary:"30k-50k"score:0secondType:"管理岗"stationname:nullsubwayline:nullworkYear:"5-10年"复制代码

可见返回了大量的信息,那么我们如何去获得这些数据?此时可以写一个简单的Job类:

class Job:    def __init__(self):        self.datalist=[]    def getJob(self,url,data):        p=Proxy()        result=p.getPage(url,data)        result.encoding = "utf-8"        result_dict=result.json()        try:            job_info = result_dict['content']['positionResult']['result']            for info in job_info:                print(info)            return job_info        except:            print("发生解析错误")       复制代码

使用getJob方法获取的是所有的信息,这其实是不必要的,应该也有所选择,否则将给自己带来压力,对于后续步骤也将带来不便。

Step2

此时,一个简单的爬虫已经编写得差不多了,我们可以进行测试一下。 编写主函数

if __name__ == '__main__':    url="https://www.lagou.com/jobs/positionAjax.json?px=default&city=%E4%B8%8A%E6%B5%B7&needAddtionalResult=false&isSchoolJob=0"    job = Job()    all_page_info=[]    for x in range(1,31):        data = {            "first": "false",            "pn": x,            "kd": "Java"        }        current_page_info=job.getJob(url,data)        all_page_info.extend(current_page_info)        print("第%d页已经爬取成功"%x)        time.sleep(5)复制代码

可以看到控制台显示:

总结

到这里,一个简单的爬虫已经编写完毕了,数据以json格式返回,似乎已经大功告成。而事实是,对于为后面的数据分析做准备工作还差得远,对于爬取海量数据,下面有几点思考。

  • 拉钩网对于同一ip的大量请求行为肯定会进行封禁,所以需要准备代理池。
  • 为了实现高自动化,需要对一系列可能出现的异常情况进行处理,断点处理,确保程序不挂。
  • 为了提高效率,加入多线程。
  • 数据持久化,在持久化之前需要先进行清洗。
  • ......

针对以上问题,需要进一步学习。

转载地址:http://jdwlo.baihongyu.com/

你可能感兴趣的文章
六成黑客攻击与PDF漏洞有关 远超微软
查看>>
Gac代码库分析(3)智能指针
查看>>
如何做好技术串讲
查看>>
oracle的sql语句语法
查看>>
实例教程十三:拍照
查看>>
SCRIPT - to Tune the 'SESSION_CACHED_CURSORS' and 'OPEN_CURSORS' Parameters
查看>>
【转】MFC 字体LOGFONT
查看>>
iOS 图片填充 UIImageView
查看>>
spark2.3.0 配置spark sql 操作hive
查看>>
mysql常见错误解决方法
查看>>
【百度地图API】如何制作公交线路的搜索?如331路
查看>>
MusicXML 3.0 (30) - 和弦图表
查看>>
大话 char、varchar、 nchar、nvarchar之间"剪不断理还乱"的关系
查看>>
系统数据库
查看>>
JAVA: java产生随机数的几种方式
查看>>
调试发现的小错误
查看>>
c#中使用NetCDF存储二维数据的读写操作简单应用
查看>>
移动终端处理器构成和基带芯片概述
查看>>
Android 动态加载 (一) 态加载机制 案例一
查看>>
Oracle存储过程中异步调用的实际操作步骤
查看>>