Python 파충류 빅 데이터 일자리 채용 정보 잡기 (51job 의 경우)

파충류 의 원 리 를 간단히 소개 하 다.51job 사이트 의 완전한 파충류 방안 을 제시 했다.
파충류 기초 지식
데이터 원본
인터넷 파충류 의 데 이 터 는 일반적으로 서버 의 응답 결과 에서 나 오 는데 html 와 json 데이터 등 이 있 는데 이 두 가지 데이터 도 인터넷 파충류 의 주요 데이터 원천 이다.
그 중에서 html 데 이 터 는 웹 페이지 의 소스 코드 로 브 라 우 저 - 소스 코드 를 보면 직접 볼 수 있 습 니 다. 예 를 들 어:
json 은 데이터 저장 형식 으로 가장 원시 적 인 데이터 내용 을 포함 합 니 다. 일반적으로 웹 페이지 에 직접 표시 되 지 않 습 니 다. 여 기 는 Chrome 브 라 우 저 > 개발 자 도구 의 Network 옵션 을 통 해 서버 가 돌아 오 는 json 데 이 터 를 캡 처 할 수 있 습 니 다. 예 를 들 어:
데이터 요청
데이터 요청 방식 은 일반적으로 GET 방법 과 POST 방법 두 가지 가 있다.크롬 브 라 우 저 를 통 해 브 라 우 저 에 접근 할 때의 모든 요청 을 포착 할 수 있 습 니 다.간단 한 책 홈 페이지 의 경우 Chrome 브 라 우 저 - 개발 자 도구 (F12) 를 열 고 Network 옵션 으로 전환 하여 주소 표시 줄 에 입력 합 니 다.http://www.jianshu.com/XHR 형식 을 선택 하면 요청 한 내용 을 볼 수 있 습 니 다. Headers 를 열 면 Genel 에서 요청 방식 이 GET 방식 인 것 을 볼 수 있 습 니 다. 그 중에서 Request Headers 는 이 웹 페이지 를 방문 할 때 요청 한 데이터 입 니 다.아래 그림.
이 Headers 는 인 코딩, 언어, 사용자 로그 인 정보, 브 라 우 저 정보 등 사용자 가 요청 한 정 보 를 Python 의 사전 으로 표시 할 수 있 습 니 다.
다음은 Query String Parameters 도 있 습 니 다. 이 안 에는 사용자 가 요청 한 매개 변수 도 포함 되 어 있 고 요청 데이터 의 일부분 입 니 다.
requests 라 이브 러 리 요청 데이터 이용
Python 을 이용 하여 데이터 요청 을 구축 하 는 방식 은 매우 많 습 니 다. python 3 에 서 는 주로 urllib 와 requests 두 개의 라 이브 러 리 가 이 기능 을 실현 할 수 있 습 니 다.urllib 는 공식 표준 라 이브 러 리 로 공식 문서 전송 문 입 니 다.여 기 는 주로 제3자 라 이브 러 리 requests 를 소개 합 니 다. 이것 은 urllib 를 바탕 으로 작 성 된 것 으로 urllib 보다 사용 하기에 더욱 편리 하고 시간 을 절약 할 수 있 습 니 다.
requests 설치 방법:
$  pip install requests

requests 를 이용 하여 데이터 요청 의 주요 방식 을 구축 합 니 다.
import requests
req = request.get(url)

혹은
import requests
req = requests.post(url)

그 중에서 get () 과 post () 에 headers, params 등 인 자 를 추가 하여 사전 으로 전달 하면 됩 니 다.일반적으로 간단 한 웹 페이지 는 url 데 이 터 를 전송 하면 데 이 터 를 성공 적 으로 요청 할 수 있다.그러나 일부 사 이 트 는 반 파충류 체 제 를 사용 하여 headers 와 params 등 매개 변 수 를 전송 하여 브 라 우 저 방문, 사용자 로그 인 등 행 위 를 모 의 해 야 데 이 터 를 정상적으로 요청 할 수 있다.
웹 드라이버 요청 데이터 이용
webdriver 는 복잡 하고 반복 되 는 웹 자동화 테스트 를 하 는 도구 로 chrome, fireforx, IE 브 라 우 저 를 사용 하여 웹 테스트 를 할 수 있 으 며 사용자 가 링크 를 클릭 하고 폼 을 작성 하 며 버튼 을 누 르 는 것 을 모 의 할 수 있다.따라서 requests 라 이브 러 리 에 비해 웹 드라이버 는 아 날로 그 브 라 우 저 마우스 클릭 슬라이딩 등 사건 에서 천연 적 인 장점 을 가지 고 있 으 며, 브 라 우 저의 조작 을 진실 하 게 모 의 하여 반 파충류 체제 에 쉽게 발견 되 지 않 기 때문에 사용 하기 좋 은 파충류 도구 이다.물론 속도 가 느 리 고 효율 이 높 지 않다 는 단점 이 있다.
웹 드라이버 설치:
$ pip install selnium

selnium 라 이브 러 리 를 설치 하 는 것 외 에 웹 드라이버 의 실행 은 브 라 우 저 구동 설정 이 필요 합 니 다.Chrome, 불 여우, IE 브 라 우 저 는 모두 설정 방식 이 있 고 구체 적 인 방법 으로 링크 를 볼 수 있 습 니 다.
IE 브 라 우 저 를 예 로 들 어 간단 한 시범 을 보 여 줍 니 다.
from selenium import webdriver
import os
iedriver = "IEDriverServer.exe"
os.environ["webdriver.ie.driver"] = iedriver
driver = webdriver.Ie(iedriver)

이렇게 해서 IE 브 라 우 저 설정 이 완료 되 었 습 니 다. 그 중에서 'IEDriverServer. exe' 는 IE 브 라 우 저가 구동 하 는 저장 경로 입 니 다.그래서 약서 망 홈 페이지 데 이 터 를 방문 하려 면 한 단계 만 필요 합 니 다.
driver.get(http://www.jianshu.com/)

데이터 분석
requests 가 요청 한 데 이 터 를 사용 하면. text () 방법 이나. content () 방법 으로 접근 할 수 있 습 니 다. 텍스트 요청 에 대해 서 는 큰 차이 가 없습니다. 주로 인 코딩 문제 에 있 습 니 다.구체 적 인 용법 은 공식 문 서 를 참고 할 수 있 으 며, 여 기 는 더 이상 군말 하지 않 는 다.웹 드라이버 로 요청 한 데 이 터 를. page 로 사용 할 수 있 습 니 다.source 속성 가 져 오기.요청 한 데 이 터 는 일반적으로 대량의 웹 소스 코드 를 포함 하고 있 는데, 어떻게 그것 을 분석 하여 원 하 는 내용 을 추출 합 니까?
html 형식 데이터 분석
html 언어 는 하이퍼텍스트 태그 언어 로 html 태그 로 구성 되 어 있 으 며 구조 화 된 언어 이기 때문에 정 보 를 추출 하 는 데 쉽게 일치 합 니 다.이러한 유형의 데 이 터 를 분석 하 는 방법 은 여러 가지 가 있 습 니 다. 예 를 들 어 정규 표현 식 을 이용 하여 html 태그 의 구조 에 따라 문자열 을 일치 시 키 거나 lxml 라 이브 러 리 의 xpath 방법 으로 xpath 경 로 를 사용 하여 모든 노드 를 찾 거나 jQuery 와 유사 한 PyQuery 방법 도 있 습 니 다.여 기 는 주로 BeautifulSoup 방법 을 소개 합 니 다.
Beautiful Soup 은 HTML 이나 XML 파일 에서 데 이 터 를 추출 할 수 있 는 Python 라 이브 러 리 입 니 다. 원 하 는 변환 기 를 통 해 일반적인 문서 내 비게 이 션 을 할 수 있 습 니 다. 문 서 를 찾 고 수정 하 는 방식 입 니 다. Beautiful Soup 은 몇 시간, 심지어 며칠 동안 의 작업 시간 을 절약 할 수 있 습 니 다.이 소 개 는 공식 중국어 문서, 전송 문 에서 유래 했다.BeautifulSoup 을 이용 하여 html 문자열 을 트 리 구조 로 바 꾸 고 모든 탭 을 빠르게 찾 을 수 있 습 니 다.
현재 버 전 은 BeautifulSoup 4, pip 설치 방법:
$ pip install BeautifulSoup4

또는 bs4 의 원본 코드 를 다운로드 한 후 압축 을 풀 고 실행 합 니 다.
$ python setup.py install 

BeautifulSoup 을 이용 하여 html 데 이 터 를 분석 하 는 관건 적 인 절 차 는:
from bs4 import BeautifulSoup
soup = BeautifulSoup(req.contents, "html.parser")

웹 드라이버 로 데 이 터 를 요청 하면:
from bs4 import BeautifulSoup
soup = BeautifulSoup(driver.page_source, "html.parser")

이렇게 html 데 이 터 를 BeautifulSoup 의 트 리 구조 로 변환 합 니 다.그리고 BeautifulSoup 의 find (), findall () 등 방법 으로 모든 노드 를 찾 을 수 있 습 니 다.자세 한 내용 은 공식 문 서 를 참조 하 시기 바 랍 니 다.
json 형식 데이터 분석
json 형식의 데 이 터 는 이미 고도 로 구조 화 된 데이터 로 Python 에서 사전 의 표현 형식 과 같 기 때문에 분석 에 매우 편리 하 다.통과 가능:
import json
data = json.loads(req.text)

json 데 이 터 를 직접 읽 고 사전 형식 을 되 돌 릴 수 있 습 니 다.
빅 데이터 직위 데이터 파충류 실전
이곳 은 51job 사 이 트 를 예 로 들 어 빅 데이터 관련 직위 를 구축 하 는 데이터 파충류 다.검색 키 워드 는 다음 과 같 습 니 다.
     
     
     
     
    
      
       
      

웹 분석
51job 첫 페이지 열기http://www.51job.com/검색 상자 에 '데이터 과학자' 를 입력 하고 검색 상자 에 있 는 지역 을 열 어 현재 선택 한 도 시 를 제거 합 니 다. 즉, 기본적으로 전국 적 으로 검색 합 니 다."검색" 단 추 를 누 르 면 검색 결 과 를 얻 을 수 있 습 니 다.이 때 URL 을 복사 합 니 다:
 http://search.51job.com/list/000000,000000,0000,00,9,99,
%25E6%2595%25B0%25E6%258D%25AE%25E7%25A7%2591%25E5%25AD%25A6%25E5%25AE%25B6,
2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99&degreefrom=99
&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0
&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare=

결 과 는 한 페이지 가 아니 라 두 번 째 페이지 를 클릭 하여 URL 을 복사 합 니 다.
http://search.51job.com/list/000000,000000,0000,00,9,99,
%25E6%2595%25B0%25E6%258D%25AE%25E7%25A7%2591%25E5%25AD%25A6%25E5%25AE%25B6,
2,2.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99
&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0
&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare=

이 두 단락 의 url 의 유일한 차이 점 은 'html' 앞의 숫자 1 과 2 에 있 기 때문에 페이지 번 호 를 대표 합 니 다.그 중:
%25E6%2595%25B0%25E6%258D%25AE%25E7%25A7%2591%25E5%25AD%25A6%25E5%25AE%25B6

URL 인 코딩 입 니 다. 중국어 로 번역 하면 '데이터 과학자' 입 니 다. 변환 방식 은 urllib 라 이브 러 리 의 quote () 방법 을 사용 할 수 있 습 니 다.
import urllib.quote
keyword = '     '
url = quote(keyword)

첫 번 째 검색 결 과 를 통 해 페이지 수 를 가 져 올 수 있 습 니 다:
def GetPages(keyword):
    keyword = quote(keyword, safe='/:?=')
    url = 'http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=000000%2C00&district=000000&funtype=0000&industrytype=00&issuedate=9&providesalary=99&keyword='+keyword + \
      '&keywordtype=2&curr_page=1&lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&list_type=0&fromType=14&dibiaoid=0&confirmdate=9'
    html = requests.get(url)
    soup = BeautifulSoup(html.content, "html.parser")
    span = soup.find('div', class_='p_in').find('span', class_='td')
    page_num = span.get_text().replace(' ', '').replace(' ,  ', '')
    return page_num

이 를 통 해 특정 키워드 에 대한 모든 검색 결과 페이지 를 옮 겨 다 닐 수 있다.
URL 목록 구축
검색 결과 페이지 를 열 면 직위 이름 을 클릭 하면 각 직위 의 상세 한 페이지 로 연결 할 수 있 고 필요 한 데이터 원본 입 니 다.따라서 모든 검색 결과 의 직위 이름 의 하이퍼링크 주 소 를 가 져 오 면 모든 직위 의 상세 한 데 이 터 를 옮 겨 다 닐 수 있 습 니 다.
def GetUrls(keyword, page_num):
    keyword = quote(keyword, safe='/:?=')
    urls = []
    p = page_num+1
    for i in range(1, p):
        url = 'http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=000000%2C00&district=000000&funtype=0000&industrytype=00&issuedate=9&providesalary=99&keyword='+keyword + \
            '&keywordtype=2&curr_page=' + \
            str(i) + \
            '&lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&list_type=0&dibiaoid=0&confirmdate=9'
        html = requests.get(url)
        soup = BeautifulSoup(html.content, "html.parser")
        ps = soup.find_all('p', class_='t1')
        for p in ps:
            a = p.find('a')
            urls.append(str(a['href']))
        s = random.randint(5, 30)
        print(str(i)+'page done,'+str(s)+'s later')
        time.sleep(s)
    return urls

구조 데이터 요청
모든 직위 데이터 의 url 을 가 져 온 후에 requests 를 사용 하여 이 url 을 방문 하면 데 이 터 를 순조롭게 가 져 올 수 없습니다.따라서 요청 에 headers 데 이 터 를 추가 하 는 것 을 고려 할 수 있 습 니 다. 쿠키 와 User 가 포함 되 어 있 습 니 다.Agent:
User_Agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
cookie = 'guid=14842945278988500031; slife=indexguide%3D1'
headers = {'User-Agent': User_Agent, 'cookie': cookie}

이렇게 하면 모든 직위 의 상세 한 페이지 데 이 터 를 성공 적 으로 요청 할 수 있 습 니 다.
데이터 분석
데이터 분석 은 먼저 데이터 수 요 를 명 확 히 하 는 것 이 고 데 이 터 를 가능 한 한 많이 캡 처 합 니 다.
직위 요구 란 을 예 로 들 면 여러 페이지 를 방문 하여 비교 한 결과 이 란 에 표 시 될 수 있 는 요구 개수 가 다 릅 니 다.
여기 에는 경험, 학력, 채용 인원 과 발표 시간 이 포함 되 어 있다.
여기 에는 경험 에 대한 요구 가 없다.
브 라 우 저 개발 자 옵션 기능 을 사용 하여 이 표시 줄 의 원본 코드 를 보십시오.
이 직위 의 요 구 는 모두 class = "sp4" 의 span 에 놓 여 있 습 니 다. 검색 기능 을 통 해 다른 class = "sp4" 의 태그 가 없 음 을 발견 할 수 있 기 때문에 find 를 이용 합 니 다.all () 방법 은 이 직위 의 요구 데 이 터 를 쉽게 찾 을 수 있다.
비 교 를 통 해 이 가장 많은 요구 개 수 는 4 라 는 것 을 알 수 있 습 니 다. 따라서 개수 가 불확실 한 상황 에서 네 개의 빈 문자열 요 소 를 포함 하 는 새 배열 을 새로 만 들 고 모든 요구 개 수 를 이 배열 에 채 워 넣 으 면 서로 다른 웹 페이지 의 데이터 가 완전 하 게 얻 을 수 있 습 니 다.
spans = soup.find_all('span', class_='sp4')
num = len(spans)
nav = ['', '', '', '']
for i in range(0, num-1):
    nav[i] = spans[i].get_text().strip()

전체 코드 는 다음 과 같 습 니 다:
# -*- coding: utf-8 -*-
from urllib.parse import quote
import requests
from bs4 import BeautifulSoup
import time
import random


def GetPages(keyword):
    keyword = quote(keyword, safe='/:?=')
    url = 'http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=000000%2C00&district=000000&funtype=0000&industrytype=00&issuedate=9&providesalary=99&keyword='+keyword + \
        '&keywordtype=2&curr_page=1&lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&list_type=0&fromType=14&dibiaoid=0&confirmdate=9'
    html = requests.get(url)
    soup = BeautifulSoup(html.content, "html.parser")
    span = soup.find('div', class_='p_in').find('span', class_='td')
    page_num = span.get_text().replace(' ', '').replace(' ,  ', '')
    return page_num


def GetUrls(keyword, page_num):
    keyword = quote(keyword, safe='/:?=')
    urls = []
    p = page_num+1
    for i in range(1, p):
        url = 'http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=000000%2C00&district=000000&funtype=0000&industrytype=00&issuedate=9&providesalary=99&keyword='+keyword + \
            '&keywordtype=2&curr_page=' + \
            str(i) + \
            '&lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&list_type=0&dibiaoid=0&confirmdate=9'
        html = requests.get(url)
        soup = BeautifulSoup(html.content, "html.parser")
        ps = soup.find_all('p', class_='t1')
        for p in ps:
            a = p.find('a')
            urls.append(str(a['href']))
        s = random.randint(5, 30)
        print(str(i)+'page done,'+str(s)+'s later')
        time.sleep(s)
    return urls


def GetContent(url, headers):
    html = requests.get(url, headers=headers)
    soup = BeautifulSoup(html.content, "html.parser")
    PositionTitle = str(soup.find('h1')['title'])
    Location = soup.find('span', class_='lname').string
    Salary = soup.find('strong').string
    CompanyName = soup.find('p', class_='cname').get_text().strip()
    CompanyType = soup.find(
        'p', class_='msg ltype').get_text().strip().replace(' ', '').replace('  ', '').replace('  ', '').replace('  ', '')
    spans = soup.find_all('span', class_='sp4')
    num = len(spans)
    nav = ['', '', '', '']
    for i in range(0, num-1):
        nav[i] = spans[i].get_text().strip()
    Exp = nav[0]
    Degree = nav[1]
    RecruitNum = nav[2]
    PostTime = nav[3]
    Welfare = soup.find('p', class_='t2')
    if str(type(Welfare)) == "":
        Welfare = ''
    else:
        Welfare = Welfare.get_text().strip().replace('
'
, '|') PositionInfo = soup.find( 'div', class_='bmsg job_msg inbox').get_text().strip().replace('
'
, '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace(' ', '').replace('\r', '') PositionType = soup.find('span', class_='el') if str(type(PositionType)) == "": PositionType = '' else: PositionType = PositionType.get_text().strip().replace('
'
, '') Contact = soup.find('div', class_='bmsg inbox') if str(type(Contact)) == "": Contact = '' else: Contact = Contact.get_text().strip().replace( ' ', '').replace(' ', '').replace(' ', '').replace('
'
, '') ConpanyInfo = soup.find('div', class_='tmsg inbox') if str(type(ConpanyInfo)) == "": ConpanyInfo = '' else: ConpanyInfo = ConpanyInfo.get_text().strip().replace( '
'
, '').replace(' ', '').replace(' ', '') try: record = PositionTitle+'\t'+Location+'\t'+Salary+'\t'+CompanyName+'\t'+CompanyType+'\t'+Exp+'\t'+Degree+'\t' + \ RecruitNum+'\t'+PostTime+'\t'+Welfare+'\t'+PositionInfo + \ '\t'+str(PositionType)+'\t'+str(Contact)+'\t'+str(ConpanyInfo) except Exception as e: record = '' else: pass finally: pass return record def main(): with open('keywords.txt', 'r', encoding='utf-8') as f: keywords = f.readlines() for keyword in keywords[1:]: keyword = keyword.strip() page_num = int(GetPages(keyword)) urls = GetUrls(keyword, page_num) with open(keyword+'urls.txt', 'w', encoding='utf-8') as f: for url in urls: f.write(url+'
'
) User_Agent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36' cookie = 'guid=14842945278988500031; slife=indexguide%3D1' headers = {'User-Agent': User_Agent, 'cookie': cookie} with open(keyword+'urls.txt', 'r', encoding='utf-8') as f: urls = f.readlines() records = [] i = 0 for url in urls: url = url.strip() if url != '': records.append( GetContent(url, headers)) i += 1 s = random.randint(5, 30) print(str(i)+'page done,'+str(s)+'s later') time.sleep(s) with open(keyword+'.txt', 'w', encoding='utf-8') as f: for re in records: f.write(re+'
'
) print(keyword+' Done---------------------------') if __name__ == '__main__': main()

좋은 웹페이지 즐겨찾기