深入剖析拉钩网,小白也来玩数据(二)

谈拉钩网爬虫的源码分析、爬虫策略及问题解决

</br>
拉钩网因其json格式的结构化数据,
成为几乎所有“爬者”必经的练手场。

网上许多高手也分享了他们的经验和代码。

上一篇我们简单分析和展示了数据。
今天分几块来深入剖析拉钩网爬虫。
</br>

一、一般爬取策略

多说无益,以图为例,简要分析~

page1

page2
page3
page4
page5
page6
page7
page8
page9
page10

已经尽量解析的详细了,
一般爬取思路大概就是这样。

</br>

二 、爬虫新思路

上面我们谈了一般思路,相信很多爬友早就发现了。然而拉勾网的爬虫实在太多了,其反爬机制经常变动,爬取难度逐渐增加。

这一回我用上面的方法,结果返回这样:


懵了。
最初以为是user_agent等问题,又设随机数还是不见好。估计是拉钩修改了反爬机制。

试着模拟登录,然而,Form采用复杂的
暗文密码,成功吓退小白。

最后重新构造URL,get方式解决

那我是怎么做到的呢?
最初是盯着network发呆,后面留意到URL后面的needAddtionalResult=false

'needAdditionalResult',额外添加?好吧,那就随便加点东西。加什么好呢?

那就随便这个好咯,然后返回这样


直接构造URL,哈哈我简直聪明~ (_)!
纯属瞎撞,第二天想到onenote中一笔记:

我们用form提交的表单,其实最终会变成上面那样的格式。(用不用post基本差不多)

get方式获取数据,加个cookies即可。
代码如下,还是放个完整版:
# !usr/bin/env python
# --coding:utf-8 --
author='WYY'
date='2017.03.29'

#实战小项目:爬取拉钩网并作小型数据分析
import requests
import json
import xlwt
import time
import random

class Spider():
    def __init__(self):
        self.keyword=raw_input(u'请输入职位:')

    #获取数据
    def getData(self,url):
        user_agents=['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20130406 Firefox/23.0',
                   'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0',
                   'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533+ \(KHTML, like Gecko) Element Browser 5.0',
                   'IBM WebExplorer /v0.94', 'Galaxy/1.0 [en] (Mac OS X 10.5.6; U; en)',
                   'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',
                   'Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14',
                   'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) \Version/6.0 Mobile/10A5355d Safari/8536.25',
                   'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) \Chrome/28.0.1468.0 Safari/537.36',
                   'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; TheWorld)']
        index=random.randint(0, 9)
        user_agent=user_agents[index]
        headers={'User_agent':user_agent,
             'cookie':'user_trace_token=20170328171202-9af479cf-1396-11e7-a59b-525400f775ce; LGUID=20170328171202-9af4825b-1396-11e7-a59b-525400f775ce; showExpriedIndex=1; showExpriedCompanyHome=1; showExpriedMyPublish=1; hasDeliver=0; index_location_city=%E5%85%A8%E5%9B%BD; JSESSIONID=9E6568091D64AB8515B8E70D354BC10D; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1490692322,1490704679,1490704945,1490746875; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1490748769; _ga=GA1.2.407060577.1490692322; LGSID=20170329082118-a0c3b596-1415-11e7-a659-525400f775ce; LGRID=20170329085249-080c8c0b-141a-11e7-9574-5254005c3644; SEARCH_ID=9bc41c0071964f8c804e9f67a0a5c073'}
        html=requests.get(url,headers=headers)
        data=json.loads(html.text)
        return data

    #获取职位信息并存入列表
    def getPosition(self,url):
        data=self.getData(url)
        position=data['content']['positionResult']['result']
        po_list=[]
        if position is not None:
            for i in position:
                main=[]
                main.append(i['companyFullName'])
                main.append(i['financeStage'])
                main.append(i['positionName'])
                main.append(i['positionLables'])
                main.append(i['salary'])
                main.append(i['city'])
                main.append(i['education'])
                main.append(i['workYear'])
                main.append(i['jobNature'])
                main.append(i['createTime'])
                po_list.append(main)
        return po_list

    #获取数据,存入一个大的list
    def saveDetail(self):
        self.New=int(raw_input(u'请输入要爬取的页数:'))
        self.time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        print u'\n本地时间:',self.time
        print u'\n开始采集数据...'
        container=[]
        for page in range(1,self.New+1):
            self.url='https://www.lagou.com/jobs/positionAjax.json?px=new&first=true&pn='+str(page)+'&kd='+str(self.keyword)
            po_list=self.getPosition(self.url)
            time.sleep(3)
            print u'第',page,u'项完毕'
            container=container+po_list
        return container

    #将数据存入excel
    def saveAll(self):
        book=xlwt.Workbook()
        sheet =book.add_sheet(str(self.keyword), cell_overwrite_ok=True)
        container=self.saveDetail()
        print u'\n采集完毕'
        print u'\n准备将数据存入表格...'
        heads=[u'公司全名', u'融资状况', u'工作名称', u'标签', u'薪酬', u'城市', u'学历要求',u'经验要求',u'工作类型',u'数据创建时间']
        ii=0
        for head in heads:
            sheet.write(0,ii,head)
            ii+=1
        i=1
        for list in container:
            j=0
            for one in list:
                sheet.write(i, j, one)
                j+=1
            i+=1
        book.save(str(self.keyword)+'.xls')
        print u'\n录入成功!'

spider=Spider()
spider.saveAll()

有盆友可能会问了:随便设个New简单,
可怎么获得最大页数呀?

好吧,我坦白:手动试出来的
(先大概定个范围,每次取中间数,试个5、6次就出来了,也简单)

其实我也想过用个if position==[]或者if position=None就break结束循环,可却不知道为什么行不通,真是怪了。可是如果先遍历获取最大页数,后面又得遍历一次,抓取次数多了,难保不被网站发现被封IP
只好这样了(这里有待改进)。

可以看到,整个爬取过程仅用request、json、xlwt等几个关键库。

总结爬虫新思路:

直接用pn构造URL实现翻页,加上cookies伪装成浏览器,get方式获取####

是不是hin简单_
</br>
</br>

三、突破IP限制

爬虫爬到一半时,又出了幺蛾子


再上去一看

原来IP被封 了,难怪。
(这样的情况还是第一次)

查了一下,网上有说可以用代理池。
可又得设计爬虫抓代理,不免麻烦。
后面想到之前爬图片网站时,注册的vpn。

vpn不就是代理么,还可各种线路随便切换,哈哈哈我简直聪明~ (_)!

查了一点资料,有关反反爬及突破IP限制,
总结几个方法:
1、设置代理池(可以网上抓代理,不过稳定性是问题)
2、使用vpn(原理同上)
3、分布式抓取(这个我也没学到>_<)
4、设置等待时间,放慢抓取速度
5、修改请求头( user_agent、cookies)
6、模拟登录
当然,最有效当属123

</br>

四、数据分析 — 一些感悟

工具用的BDP(奇妙的分析软件)。
词云用的标签一栏,直接丢BDP自动生成。
后面发现有欠妥当,因为有些数据标签那一块什么都没有。对几个维度进行了粗略分析,效果还不错,比如这样

细心的盆友可能又发现了,怎么没有C# ?
其实,我也想的。。。


如图所示搜C#时,会搜出许多C\C++的内容,乱而麻烦,只好舍弃。

第一次亲自参与3万多数据的分析,新鲜。后面一想,其实爬虫程序不过只是个采集数据的手段(或者说工具)。

关键还是具体的数据分析以及应用转化 单单抓个几十万烂在excel表里,没有任何意义。
</br>
</br>

五、源码剖析 — 新发现

爬过拉钩的朋友肯定会发现一个现象:
打开一个页面,过一阵子再重新打开
发现不再是原来页面了,变成了别的

可是真的是这样么

放几个图


page one

page two

page three

get到了么?
只是顺序变了下,内容是不变的。

换汤不换药,特么全是 障眼法 啊!!!
难为了拉钩的前端工程师 [摊手]

看来也只有我这种** 既无聊又聪明又有耐心**的人才会发现了

84769047

</br>

这个小项目我也放到了github上了:https://github.com/LUCY78765580/Python-web-scraping/blob/master/LaGou/LaGou.py
最后总结本篇 几个要点:

1、拉钩爬虫一般方法:Post模拟浏览器
2、新思路:get方式+cookies伪装
直接pn构建URL实现翻页和遍历
3、突破IP限制(各种方法)
4、程序不过工具,关键策略、数据分析
5、源码剖析新发现:页面原来障眼法

为了对得起这个"深入剖析"的标题,小白已经尽她最大的努力啦~

(学习爬虫才一月左右,文章可能有不足之处,个中出入还请各位大神多多指正)

本篇就是这样啦~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容