python爬蟲爬取拉勾網站內容
阿新 • • 發佈:2018-12-11
本次主要內容是分享下拉勾網站模擬搜尋以及搜尋內容的爬取,這裡先引入一些用到的庫,由於網站本身的反爬蟲技術和網路原因,這裡使用了fake_useragent和多執行緒模式,當然如果有條件的話也可以使用代理池,這樣可以更加保險一點。由於我沒有弄那些收費的代理,而免費的代理有時會出現問題,所有就沒有使用。
import requests import json import pymongo from bs4 import BeautifulSoup from fake_useragent import UserAgent import time from requests.exceptions import RequestException import threading from queue import Queue
首先通過分析網頁network工作情況可知,拉勾的搜尋頁面是運用的ajax技術,所以首先要找到資料介面網址,作為post資料的初始網址,然後分析所帶的引數,通過分析可以first的值和pn鍵的值對應的關係,可以使用一個判斷語句控制,內容如下:
url="https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false" tag = "true" if pn == 1 else "false" data = { 'first': true, 'pn': 1, 'kd':python }
然後就是在返回的包中提取內容,通過分析包可以知道搜尋返回的資料,找到需要的資料。這裡由於我們需要進入每個搜尋內容的詳情頁,所以我們需要獲得搜尋內容返回的頁面的id,然後進行字串操作獲得詳情頁的真實網址:
results=page['content']['positionResult']['result'] ret=[] for result in results: id=result['positionId'] ret.append(id) urls = ['https://www.lagou.com/jobs/{}.html'.format(i) for i in ret]
最後就是進入詳情頁的解析並存入資料庫就行了。
具體的程式碼如下 :
import requests
import json
import pymongo
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import time
import pymongo
from config import * #引入mongodb的配置檔案
from requests.exceptions import RequestException
from mongocache import MongoCache #這個引入的是我自己寫的一個mongodb儲存的小程式,下面會寫
#最簡單的方法是直接使用pymongo進行儲存操作,如下面的save_to_mongo
import threading
from queue import Queue
client=pymongo.MongoClient(MONGO_URL,connect=False)
db=client[MONGO_DB]
mongo=MongoCache()
def save_to_mongo(result): #資料儲存方法
try:
if db[MONGO_DB].insert(result):
print('成功存入')
except Exception:
print("失敗")
class ShiShi:
def __init__(self):
_ua=UserAgent() #模擬隨機生成useragent
#cookie是我摘取的我自己的已登入的cookie,這個根據自己進行更改
self.headers={
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'User-Agent':_ua.random,
'Accept': '*/*',
# 'Accept-Language': '',
'Connection': 'keep-alive',
'Host': 'www.lagou.com',
'Referer': 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=',
'Cookie': 'cookie',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
}
self.url="https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false"
self.q = Queue(10)
#傳送帶引數的post請求
def get_page(self,pn,kd):
tag = "true" if pn == 1 else "false"
data = {
'first': tag,
'pn': pn,
'kd':kd
}
page=requests.post(self.url,headers=self.headers,data=data).json()
return page
#獲取頁面id,並存入到空列表中
def get_id(self,page):
results=page['content']['positionResult']['result']
ret=[]
for result in results:
id=result['positionId']
ret.append(id)
return ret
#對搜尋返回的不同頁面的id進行整合
def get_mid(self,pn,kd):
list = []
for i in range(1, int(pn) + 1):
page = self.get_page(i, kd)
ids = self.get_id(page)
list.extend(ids)
return list
#對id拼接成詳情頁的url
def get_real_url(self,ret):
urls = ['https://www.lagou.com/jobs/{}.html'.format(i) for i in ret]
return urls
#對詳情頁進行解析並存入到資料庫
def get_page_detail(self,url):
try:
response=requests.get(url,headers=self.headers)
time.sleep(10)
if response.status_code==200:
soup=BeautifulSoup(response.text,'lxml')
conpany_name=soup.select('#job_company > dt > a > img')
work_name=soup.select('body > div.position-head > div > div.position-content-l > div > span')
salary=soup.select('body > div.position-head > div > div.position-content-l > dd > p:nth-of-type(1) > span.salary')
work_place=soup.select('body > div.position-head > div > div.position-content-l > dd > p:nth-of-type(1) > span:nth-of-type(2)')
exp_demand=soup.select("body > div.position-head > div > div.position-content-l > dd > p:nth-of-type(1) > span:nth-of-type(3)")
edu_demand=soup.select('body > div.position-head > div > div.position-content-l > dd > p:nth-of-type(1) > span:nth-of-type(4)')
job_desc=soup.select('#job_detail > dd.job_bt > div')
for 公司名稱,工作名稱,工資待遇,工作地點,經驗要求,學歷要求,工作描述 in zip(conpany_name,work_name,salary,work_place,exp_demand,edu_demand,job_desc):
data={
"公司名稱" : 公司名稱.get('alt'),
"工作名稱": 工作名稱.get_text(),
"工資待遇":工資待遇.get_text(),
"工作點點":工作地點.get_text(),
"經驗要求":經驗要求.get_text(),
"學歷要求":學歷要求.get_text(),
"工作描述":工作描述.get_text(),
}
mongo.__setitem__(url,data)
# write_to_file(data)
else:
print("無法連線")
except RequestException:
print('出現錯誤')
#多執行緒的生產者模式函式
def produce(self):
pn = input('請輸入你想要爬取多少頁:')
kd = input('你就說你想要搜啥:')
index=0
list=self.get_mid(pn,kd)
urls=self.get_real_url(list)
while True:
if index < len(urls):
self.q.put(urls[index])
index+=1
#消費者函式
def consume(self):
while True:
url=self.q.get()
self.get_page_detail(url)
print('thread is {} content is {}'.format(threading.current_thread(),url))
def main(self):
p1 = threading.Thread(target=self.produce, )
p2 = threading.Thread(target=self.consume, )
p3 = threading.Thread(target=self.consume, )
p4 = threading.Thread(target=self.consume, )
p5 = threading.Thread(target=self.consume, )
p6 = threading.Thread(target=self.consume, )
p7 = threading.Thread(target=self.consume, )
p1.start()
p2.start()
p3.start()
p4.start()
p5.start()
p6.start()
p7.start()
if __name__ == '__main__':
haha=ShiShi()
haha.main()
這只是一個簡單的聚焦爬蟲,其實對於這類含有ajax的網站來說,使用selenium能更加快捷有效的進行爬取。