成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

瀏覽:187日期:2022-07-17 15:05:36

本文實(shí)例為爬取拉勾網(wǎng)上的python相關(guān)的職位信息, 這些信息在職位詳情頁上, 如職位名, 薪資, 公司名等等.

分析思路

分析查詢結(jié)果頁

在拉勾網(wǎng)搜索框中搜索’python’關(guān)鍵字, 在瀏覽器地址欄可以看到搜索結(jié)果頁的url為: ’https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=’, 嘗試將?后的參數(shù)刪除, 發(fā)現(xiàn)訪問結(jié)果相同.

打開Chrome網(wǎng)頁調(diào)試工具(F12), 分析每條搜索結(jié)果(即每個(gè)職位)在html中所處的元素定位, 發(fā)現(xiàn)每條結(jié)果都在<ul class='item_con_list'>下的li標(biāo)簽中.

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

因?yàn)槲覀冃枰總€(gè)職位的具體信息, 因此需要獲取到每條搜索結(jié)果的詳情url, 即點(diǎn)擊搜索結(jié)果后進(jìn)入的詳情頁的url.

繼續(xù)查看li標(biāo)簽中的元素, 找到想要的詳情url, 找到后的url為: href=https://www.lagou.com/jobs/6945237.html?show=b6e8e778fcae4c2aa2111ba58f9ebfa0

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

查看其它搜索結(jié)果的詳情url, 發(fā)現(xiàn)其格式都為: rel='external nofollow'

對(duì)于第一個(gè)ID, 每條結(jié)果的id都不一樣, 猜想其為標(biāo)記每個(gè)職位的唯一id, 對(duì)于show_id, 每條結(jié)果的id都是一樣的, 嘗試刪除show參數(shù), 發(fā)現(xiàn)一樣可以訪問到具體結(jié)果詳情頁

那么我們直接通過xpath提取到每個(gè)職位的第一個(gè)ID即可, 但是調(diào)試工具的elements標(biāo)簽下的html是最終網(wǎng)頁展示的html, 并不一定就是我們訪問 https://www.lagou.com/jobs/list_python 返回的response的html, 因此點(diǎn)到Network標(biāo)簽, 重新刷新一下頁面, 找到 https://www.lagou.com/jobs/list_python 對(duì)應(yīng)的請(qǐng)求, 查看其對(duì)應(yīng)的response, 搜索 ’position_link’(即前面我們在elements中找到的每條搜索結(jié)果的詳情url), 發(fā)現(xiàn)確實(shí)返回了一個(gè)網(wǎng)址, 但是其重要的兩個(gè)ID并不是直接放回的, 而是通過js生成的, 說明我們想要的具體數(shù)據(jù)并不是這個(gè)這個(gè)請(qǐng)求返回的.

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

那么我們就需要找到具體是那個(gè)請(qǐng)求會(huì)返回搜索結(jié)果的信息, 一般這種情況首先考慮是不是通過ajax獲取的數(shù)據(jù), 篩選類型為XHR(ajax)的請(qǐng)求, 可以逐個(gè)點(diǎn)開查看response, 發(fā)現(xiàn) positionAjax.json 返回的數(shù)據(jù)中就存在我們想要的每條搜索結(jié)果的信息. 說明確實(shí)是通過ajax獲取的數(shù)據(jù), 其實(shí)點(diǎn)擊下一頁, 我們也可以發(fā)現(xiàn)地址欄url地址并沒有發(fā)生變化, 只是局部刷新了搜索結(jié)果的數(shù)據(jù), 也說明了搜索結(jié)果是通過ajax返回的.

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

分析上面ajax的response, 查看其中是否有我們想要的職位ID, 在preview中搜索之前在elements中找到的某個(gè)職位的url的兩個(gè)ID, 確實(shí)兩個(gè)ID都存在response中, 分析發(fā)現(xiàn)第一個(gè)ID即為positionId, 第二個(gè)即為showId, 我們還可以發(fā)現(xiàn)response中返回了當(dāng)前的頁碼數(shù)pageNo

因此我們只需要訪問上面ajax對(duì)應(yīng)的url: https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false 就可以拿到我們想要的ID, 然后填入詳情url模板: https://www.lagou.com/jobs/{position_id}.html?show={show_id}中即可訪問詳情頁了.

但是當(dāng)我們直接訪問 https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false 時(shí) ,返回的結(jié)果卻是: {'status':false,'msg':'您操作太頻繁,請(qǐng)稍后再訪問','clientIp':'139.226.66.44','state':2402}

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

經(jīng)過百度查詢后發(fā)現(xiàn)原來直接訪問上述地址是不行的, 這也是拉鉤的一個(gè)反爬策略, 需要我們帶上之前訪問查詢結(jié)果頁(https://www.lagou.com/jobs/list_python?)的cookie才行, 因?yàn)槲覀冞@里使用的是scrapy框架, 該框架是能夠自帶上次請(qǐng)求的cookie來訪問下一個(gè)請(qǐng)求的, 所以我們這里不需要手動(dòng)去添加cookie信息, 只需要首先訪問一下查詢結(jié)果頁就可以了. 即start_url = https://www.lagou.com/jobs/list_python

此外發(fā)現(xiàn)這個(gè)ajax請(qǐng)求是通過POST方式發(fā)送的, 因此還需要分析它提交的form數(shù)據(jù), 在第一頁中有三條數(shù)據(jù)信息, first為true, pn為1 kd為python , 第二頁中first為false, pn為2, kd同樣為python, 且多了一個(gè)sid

分析這四個(gè)參數(shù), 第一個(gè)first為表示是否是第一頁, 第二個(gè)pn為表示當(dāng)前頁碼數(shù), 第三個(gè)kd為表示搜索的關(guān)鍵字, 第四個(gè)sid經(jīng)過和上面showId對(duì)比發(fā)現(xiàn)其值就為showId

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

分析職位詳情頁

前面分析完后就可以拼接出職位詳情頁url了, 點(diǎn)開詳情頁, 同樣的思路分析我們想要的數(shù)據(jù)是不是就在詳情頁的url中, 這里想要職位名稱, 工資, 地點(diǎn), 經(jīng)驗(yàn), 關(guān)鍵字, 公司信息等

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

在network中查找對(duì)應(yīng)的response, 發(fā)現(xiàn)數(shù)據(jù)確實(shí)就存在response中, 因此直接通過xpath就可以提取想要的數(shù)據(jù)了

編寫爬蟲代碼

具體代碼在github:

這里只放出關(guān)鍵代碼

創(chuàng)建scrapy項(xiàng)目

scrapy startproject LaGou

創(chuàng)建爬蟲

scrapy genspider lagou www.lagou.com

編寫items.py, 設(shè)置要想爬取的字段

# -*- coding: utf-8 -*-# Define here the models for your scraped items## See documentation in:# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass LagouItem(scrapy.Item): # define the fields for your item here like: job_url = scrapy.Field() job_name = scrapy.Field() salary = scrapy.Field() city = scrapy.Field() area = scrapy.Field() experience = scrapy.Field() education = scrapy.Field() labels = scrapy.Field() publish_date = scrapy.Field() company = scrapy.Field() company_feature = scrapy.Field() company_public = scrapy.Field() company_size= scrapy.Field()

編寫爬蟲代碼 lagou.py

# -*- coding: utf-8 -*-import scrapyfrom LaGou.items import LagouItemimport jsonfrom pprint import pprintimport timeclass LagouSpider(scrapy.Spider): name = ’lagou’ allowed_domains = [’www.lagou.com’] start_urls = [’https://www.lagou.com/jobs/list_python?’] def __init__(self): # 設(shè)置頭信息, 若不設(shè)置的話, 在請(qǐng)求第二頁時(shí)即被拉勾網(wǎng)認(rèn)為是爬蟲而不能爬取數(shù)據(jù) self.headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Connection': 'keep-alive', 'Host': 'www.lagou.com', 'Referer': ’https://www.lagou.com/jobs/list_Python?’, 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'referer': 'https://www.lagou.com/jobs/list_python?' } self.sid = ’’ self.job_url_temp = ’https://www.lagou.com/jobs/{}.html?show={}’ # 清空文件 with open(’jobs.json’, ’w’) as f: f.truncate() def parse(self, response): ''' 解析起始頁 ''' # response為GET請(qǐng)求的起始頁, 自動(dòng)獲取cookie # 提交POST帶上前面返回的cookies, 訪問數(shù)據(jù)結(jié)果第一頁 yield scrapy.FormRequest( ’https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false’, callback=self.parse_list, formdata={'first': 'false', 'pn': '1', 'kd': 'python', }, headers=self.headers ) def parse_list(self, response): ''' 解析結(jié)果列表頁的json數(shù)據(jù) ''' # 獲取返回的json,轉(zhuǎn)為字典 res_dict = json.loads(response.text) # 判斷返回是否成功 if not res_dict.get(’success’): print(res_dict.get(’msg’, ’返回異常’)) else: # 獲取當(dāng)前頁數(shù) page_num = res_dict[’content’][’pageNo’] print(’正在爬取第{}頁’.format(page_num)) # 獲取sid if not self.sid: self.sid = res_dict[’content’][’showId’] # 獲取響應(yīng)中的職位url字典 part_url_dict = res_dict[’content’][’hrInfoMap’] # 遍歷職位字典 for key in part_url_dict: # 初始化保存職位的item item = LagouItem() # 拼接完整職位url item[’job_url’] = self.job_url_temp.format(key, self.sid) # 請(qǐng)求職位詳情頁 yield scrapy.Request( item[’job_url’], callback=self.parse_detail, headers=self.headers, meta={’item’: item} ) # 獲取下一頁 if page_num < 30: # time.sleep(2) yield scrapy.FormRequest( ’https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false’, callback=self.parse_list, formdata={'first': 'false','pn': str(page_num+1),'kd': 'python','sid': self.sid}, headers=self.headers ) def parse_detail(self, response): ''' 解析職位詳情頁 ''' # 接收item item = response.meta[’item’] # 解析數(shù)據(jù) # 獲取職位頭div job_div = response.xpath(’//div[@class='position-content-l']’) if job_div: item[’job_name’] = job_div.xpath(’./div/h1/text()’).extract_first() item[’salary’] = job_div.xpath(’./dd/h3/span[1]/text()’).extract_first().strip() item[’city’] = job_div.xpath(’./dd/h3/span[2]/text()’).extract_first().strip(’/’).strip() item[’area’] = response.xpath(’//div[@class='work_addr']/a[2]/text()’).extract_first() item[’experience’] = job_div.xpath(’./dd/h3/span[3]/text()’).extract_first().strip(’/’).strip() item[’education’] = job_div.xpath(’./dd/h3/span[4]/text()’).extract_first().strip(’/’).strip() item[’labels’] = response.xpath(’//ul[@class='position-label clearfix']/li/text()’).extract() item[’publish_date’] = response.xpath(’//p[@class='publish_time']/text()’).extract_first() item[’publish_date’] = item[’publish_date’].split(’&’)[0] # 獲取公司dl company_div = response.xpath(’//dl[@class='job_company']’) item[’company’] = company_div.xpath(’./dt/a/img/@alt’).extract_first() item[’company_feature’] = company_div.xpath(’./dd//li[1]/h4[@class='c_feature_name']/text()’).extract_first() item[’company_feature’] = item[’company_feature’].split(’,’) item[’company_public’] = company_div.xpath(’./dd//li[2]/h4[@class='c_feature_name']/text()’).extract_first() item[’company_size’] = company_div.xpath(’./dd//li[4]/h4[@class='c_feature_name']/text()’).extract_first() yield item

編寫middlewares.py, 自定義downloadermiddleware, 用來每次發(fā)送請(qǐng)求前, 隨機(jī)設(shè)置user-agent, 這里使用了第三方庫 fake_useragent, 能夠隨機(jī)提供user-agent, 使用前先安裝: pip install fake_useragent

from fake_useragent import UserAgentimport randomclass RandomUserAgentDM: ''' 隨機(jī)獲取userAgent ''' def __init__(self): self.user_agent = UserAgent() def process_request(self, request, spider): request.headers[’User-Agent’] = self.user_agent.random

編寫pipelines.py, 將數(shù)據(jù)存為json文件

import jsonclass LagouPipeline: def process_item(self, item, spider): with open(’jobs.json’, ’a’, encoding=’utf-8’) as f: item_json = json.dumps(dict(item), ensure_ascii=False, indent=2) f.write(item_json) f.write(’n’)

編寫settings.py

# 設(shè)置日志顯示LOG_LEVEL = ’WARNING’# 設(shè)置ROBOTSTXT協(xié)議, 若為true則不能爬取數(shù)據(jù)ROBOTSTXT_OBEY = False# 設(shè)置下載器延遲, 反爬蟲的一種策略DOWNLOAD_DELAY = 0.25# 開啟DOWNLOADER_MIDDLEWARESDOWNLOADER_MIDDLEWARES = { # ’LaGou.middlewares.LagouDownloaderMiddleware’: 543, ’LaGou.middlewares.RandomUserAgentDM’ :100,}# 開啟ITEM_PIPELINESITEM_PIPELINES = { ’LaGou.pipelines.LagouPipeline’: 300,}

啟動(dòng)爬蟲

scrapy crawl lagou

發(fā)現(xiàn)依然只能5 6頁, 說明拉勾網(wǎng)的反爬確實(shí)做得比較好, 還可以繼續(xù)通過使用代理來進(jìn)行反反爬, 這里就不再演示了,

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

查看爬取結(jié)果

Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息

以上就是Python爬蟲實(shí)例——scrapy框架爬取拉勾網(wǎng)招聘信息的詳細(xì)內(nèi)容,更多關(guān)于Python爬蟲爬取招聘信息的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
国产精品美女视频| 毛片av中文字幕一区二区| 亚洲国产成人91porn| 91麻豆国产精品久久| 欧美一区二区观看视频| 国产精品资源在线看| 欧美另类高清zo欧美| 免费成人小视频| 久久狠狠婷婷| 亚洲国产一二三| 一区二区精品在线观看| 亚洲免费观看高清完整版在线 | 亚洲激情二区| 久久久久九九视频| 99re视频精品| 久久久久久97三级| 欧美在线播放| 中文一区二区在线观看| 欧美日韩一卡| 成人欧美一区二区三区小说| 红桃视频国产精品| 国产精品欧美综合在线| 欧美日韩无遮挡| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ原创 | 午夜国产精品视频| 国产精品沙发午睡系列990531| 午夜精品福利一区二区三区av| 99国产精品99久久久久久| 日韩美女一区二区三区| 99精品在线观看视频| 久久免费偷拍视频| 欧美涩涩网站| 亚洲精品久久久久久国产精华液| 成人午夜电影小说| 欧美一级片在线观看| 国产成人综合亚洲网站| 日韩视频一区二区在线观看| 91亚洲男人天堂| 国产精品超碰97尤物18| 国产精品日韩欧美一区| 午夜一区二区三区在线观看| 久久青草久久| 麻豆成人91精品二区三区| 8v天堂国产在线一区二区| 成人免费精品视频| 日本一二三不卡| 亚洲神马久久| 久久精品国产精品亚洲综合| 日韩美女天天操| 欧美日本久久| 一区二区三区在线观看动漫| 久久一区二区三区四区五区| 精品一区中文字幕| 26uuu国产日韩综合| 亚洲国产精品日韩| 日韩精品欧美成人高清一区二区| 日韩亚洲视频| 午夜av一区二区| 91精品中文字幕一区二区三区| 日韩高清一区二区| 8v天堂国产在线一区二区| 不卡区在线中文字幕| 国产精品第13页| 久久久夜夜夜| 国产大陆精品国产| 国产精品丝袜一区| 美女主播一区| 国产成人精品影院| 亚洲三级小视频| 欧美在线一区二区| 91在线porny国产在线看| 亚洲精品视频在线看| 欧美曰成人黄网| 99久免费精品视频在线观看| 亚洲欧美激情在线| 欧美精品在线观看一区二区| 欧美日韩综合另类| 日韩精品国产欧美| 久久精品无码一区二区三区| 亚洲欧美日韩专区| 国产剧情av麻豆香蕉精品| 国产香蕉久久精品综合网| 亚洲制服av| 成人性生交大合| 一区二区三区四区在线| 欧美精品电影在线播放| 欧美性天天影院| 久久福利资源站| 国产精品免费人成网站| 久久综合精品一区| 波多野结衣欧美| 亚洲成av人片在www色猫咪| 日韩一区二区在线看片| 国产日韩一区二区三区| 国产精品自在欧美一区| 中文字幕在线观看不卡| 欧美三级日韩三级| 国产字幕视频一区二区| 久久精品国产精品青草| 亚洲婷婷综合久久一本伊一区| 亚洲第一网站| 激情久久五月天| 最新不卡av在线| 9191久久久久久久久久久| 国产精品国产三级欧美二区| 久色婷婷小香蕉久久| 中文字幕一区二区三区四区| 欧美精品日韩一本| 中文日韩在线| 99久久综合色| 日韩精品乱码免费| 国产精品美女久久久久久久久久久 | 日韩午夜黄色| 国产成人综合自拍| 亚洲制服丝袜在线| 日韩你懂的电影在线观看| 亚洲一区三区电影在线观看| 97se亚洲国产综合自在线| 免费在线成人网| 中文字幕视频一区| 欧美一级二级三级蜜桃| 久久久精品午夜少妇| 欧美日韩亚洲一区| 国产盗摄一区二区| 午夜视黄欧洲亚洲| 国产精品久久久久久久岛一牛影视 | 亚洲电影视频在线| 99精品国产99久久久久久福利| 亚洲香肠在线观看| 国产婷婷色一区二区三区四区| 狠狠爱综合网| 高清国产一区二区三区| 欧美日韩一区二区三区在线| 99精品国产在热久久| 色综合天天天天做夜夜夜夜做| 一区二区三国产精华液| 久久日一线二线三线suv| 欧美综合久久久| 免费永久网站黄欧美| 亚洲第一毛片| 91亚洲精品乱码久久久久久蜜桃| 亚洲天堂成人网| 精品国产污网站| 在线观看视频91| 国产精品夜夜夜| 精品不卡在线| 91热门视频在线观看| 国产高清成人在线| 玖玖九九国产精品| 中文字幕中文在线不卡住| 久久久久久免费毛片精品| 欧美一区二区三区啪啪| 欧美日韩一区二区三区视频 | 一区二区欧美视频| 国产精品久久久久一区二区三区 | 亚洲国产高清在线| 国产精品久久久亚洲一区| 91丝袜美腿高跟国产极品老师 | 国产日韩亚洲| 欧美chengren| 99久久婷婷国产精品综合| 成人性生交大片免费| 国产99久久久国产精品潘金网站| 一区二区三区在线播放| 亚洲精品一区二区三区在线观看| 国产伦精品一区二区三区照片91| 国产高清精品网站| 久久精品久久精品| 久久99久久99| 免费三级欧美电影| 免费视频一区二区| 麻豆中文一区二区| 精品中文字幕一区二区 | 激情五月婷婷综合网| 麻豆91在线观看| 极品销魂美女一区二区三区| 日韩二区在线观看| 日韩—二三区免费观看av| 天堂资源在线中文精品| 一区二区三区日韩欧美| 玉足女爽爽91| 亚洲福利一二三区| 蜜乳av一区二区三区| 久久精品999| 国产真实乱偷精品视频免| 国产成人综合视频| 成人国产精品免费观看动漫| 99re热视频这里只精品| 欧美日韩久久| 99国内精品久久久久久久软件| 91免费看视频| 黄色成人精品网站| 在线日韩中文| 亚洲免费综合| 欧美色图在线观看| 91麻豆精品91久久久久同性| 欧美夫妻性生活| 精品免费一区二区三区| 久久综合精品国产一区二区三区 | 亚洲伦伦在线|