IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python爬虫之爬取拉勾网 -> 正文阅读

[Python知识库]python爬虫之爬取拉勾网

这次要爬取拉勾网,拉勾网的反爬做的还是很不错的啊,因为目标网站是Ajax交互的我一开始是直接分析json接口来爬取的,但是真的很麻烦,请求头一旦出点问题就给识别出来了后续我就改了一下方法用selenium来模拟浏览器去获取

招聘求职信息-招聘网站-人才网-拉勾招聘 (lagou.com)https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=先把前面代码写好??

思路嘛大概就是? 获取主页的源代码——从中获取详情页的url——在去解析 先围绕这三步来写

这里我们已经获取到了主页的源代码?

from selenium import webdriver
import requests
from selenium.webdriver import ChromeOptions   #这个包用来规避被检测的风险
from lxml import etree
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
import re



class lagouSpitder(object):
    option = webdriver.ChromeOptions()
    option.add_experimental_option('useAutomationExtension', False)
    option.add_experimental_option('excludeSwitches', ['enable-automation'])
    driver_path = r'驱动路径'  # 定义好路径
    def __init__(self):
        self.driver=webdriver.Chrome(executable_path=lagouSpitder.driver_path,options=lagouSpitder.option)#初始化路径+规避检测selenium框架
        self. driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })
        self.url='https://www.lagou.com/jobs/list_python/p-city_0?&cl=false&fromSearch=true&labelWords=&suginput='
        self.positions=[]
    def run(self):  #主页面
            self.driver.get(self.url)
            source = self.driver.page_source  # source页面来源  先获取一页

        

if __name__ == '__main__':
    spider=lagouSpitder()   
    spider.run()

接下来获取详情页的url,定义一个函数parse_list_page 显得美观可维护也强,可以看到 是在//a[@class="position_link"]里面的href属性里面,获取到了我们在去请求这个url一样是定义一个函数request_detall_page?

    def parse_list_page(self,source):  #获取职位详情页url
        html=etree.HTML(source)
        links=html.xpath('//a[@class="position_link"]/@href')
        for link in links:
            self.request_detall_page(link)
            time.sleep(2)

    def request_detall_page(self,url):  #去请求细节页面 
        self.driver.get(url)
        source=self.driver.page_source  #source页面来源

接下来我们去解析详情页即可 定义函数 pares_detail_page 这里就不细说了怎么解析获取了大家肯定都会,后面我要说一下具体的优化

    def pares_detail_page(self,source): #获取职位细节信息
        html=etree.HTML(source)
        Position_name=html.xpath('//span[@class="position-head-wrap-position-name"]/text()')[0] #职位名字
        salary=html.xpath('//span[@class="salary"]/text()')[0] #薪水
        Position_the_temptation=html.xpath('//dd[@class="job-advantage"]/p/text()')[0]   #职位诱惑
        Job_description=html.xpath('//div[@class="job-detail"]/text()')  #职位详情
        Job_description=''.join(html.xpath('//div[@class="job-detail"]/text()')).strip()   #拼接
        work_address=html.xpath('//div[@class="work_addr"]/text()')[3] #工作地址
        CompanyName = html.xpath('//h3[@class="fl"]/em/text()')[0]  # 公司名字
        Company_Basic_Information=html.xpath('//li/h4/text()')  #公司基本信息

        position={
            '职位名字':Position_name,
            '薪水':salary,
            '职位诱惑':Position_the_temptation,
            '职位详情':Job_description,
            '工作地址':work_address,
            '公司名字': CompanyName,
            '公司基本信息':Compnya_Basic_Information,
        }
        self.positions.append(position)
        time.sleep(5)

?这样其实我们就已经写完了这个程序,不过这只能获取第一页对吧,我们肯定不只爬取第一页的所以就要进行优化

网站是通过点击下一页翻页,那么我们先获取到下一页的元素?

?获取到元素我们可以写个循环嘛,让他解析完一页之后去点击下一页,那什么时候停止呢?可以看到我们点击第三十页的时候 它的class是不是就变了呀我们写个判断语句当它class=pager_next pager_next_disabled 这个的时候我们就停止否则就继续点击,这里也要一起写一个显示等待我爬取的时候就有几次因为这个没有加载出来导致报错

    def run(self):  #主页面
        self.driver.get(self.url) #去请求主页面
        while True:
            source = self.driver.page_source  # source页面来源  先获取一页
            WebDriverWait(driver=self.driver,timeout=10).until(
                EC.presence_of_element_located((By.XPATH,'//span[@action="next"]'))
            )  #等待按钮加载出来,避免没加载出来就点击导致的报错
            self.parse_list_page(source)  # 获取这一页职位url
            next_btn = self.driver.find_element_by_xpath('//span[@action="next"]')#下一页的元素位置
            if "pager_next pager_next_disabled" in next_btn.get_attribute('class'):  # 如果class等于最后一页则停止,否则继续点击
                break
            else:
                next_btn.click() #点击下一页
                time.sleep(1)

?接下来我们还得新开窗口,为什么呢详情页哪里来的下一页按钮这不得报错呀

 def request_detall_page(self,url):  #去请求细节页面
        # self.driver.get(url)
        self.driver.execute_script("window.open('%s')"%url)  #新打开一个职位页面
        self.driver.switch_to_window(self.driver.window_handles[1]) #切换到当前页面来解析,不切换的话selenium会停留在上一页
        source=self.driver.page_source  #source页面来源
        self.pares_detail_page(source)   #解析页面
        self.driver.close()   #解析完关闭页面
        time.sleep(0.5)
        self.driver.switch_to_window(self.driver.window_handles[0]) #切换回主页面

我们来看下效果,也是没有问题呀

?

?全部源代码如下

from  selenium import webdriver
import requests
from lxml import etree
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
import re
import random  #随机模块

class lagouSpitder(object):
    option = webdriver.ChromeOptions()
    option.add_experimental_option('useAutomationExtension', False)
    option.add_experimental_option('excludeSwitches', ['enable-automation'])
    driver_path = r'驱动路径'  # 定义好路径
    def __init__(self):
        self.driver=webdriver.Chrome(executable_path=lagouSpitder.driver_path,options=lagouSpitder.option)#初始化路径+规避检测selenium框架
        self. driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })
        self.url='https://www.lagou.com/jobs/list_python/p-city_0?&cl=false&fromSearch=true&labelWords=&suginput='
        self.positions=[]

    def run(self):  #主页面
        self.driver.get(self.url) #去请求主页面
        while True:
            source = self.driver.page_source  # source页面来源  先获取一页
            WebDriverWait(driver=self.driver,timeout=10).until(
                EC.presence_of_element_located((By.XPATH,'//span[@action="next"]'))
            )  #等待按钮加载出来,避免没加载出来就点击导致的报错
            self.parse_list_page(source)  # 解析完获取的这一页职位之后,去点击下一页
            next_btn = self.driver.find_element_by_xpath('//span[@action="next"]')#下一页的元素位置
            if "pager_next pager_next_disabled" in next_btn.get_attribute('class'):  # 如果class等于最后一页则停止,否则继续点击
                break
            else:
                next_btn.click() #点击下一页
                time.sleep(1)

    def parse_list_page(self,source):  #获取职位详情页url
        html=etree.HTML(source)
        links=html.xpath('//a[@class="position_link"]/@href')
        for link in links:    #循环去解析详情页
            self.request_detall_page(link)
            time.sleep(random.uniform(1, 3))#随机暂停

    def request_detall_page(self,url):  #去请求细节页面
        # self.driver.get(url)
        self.driver.execute_script("window.open('%s')"%url)  #新打开一个职位页面
        self.driver.switch_to_window(self.driver.window_handles[1]) #切换到当前页面来解析,不切换的话selenium会停留在上一页
        source=self.driver.page_source  #source页面来源
        self.pares_detail_page(source)   #解析页面
        self.driver.close()   #解析完关闭页面
        time.sleep(0.5)
        self.driver.switch_to_window(self.driver.window_handles[0]) #切换回主页面

    def pares_detail_page(self,source): #获取职位细节信息
        html=etree.HTML(source)
        Position_name=html.xpath('//span[@class="position-head-wrap-position-name"]/text()')[0] #职位名字
        salary=html.xpath('//span[@class="salary"]/text()')[0] #薪水
        Position_the_temptation=html.xpath('//dd[@class="job-advantage"]/p/text()')[0]   #职位诱惑
        Job_description=html.xpath('//div[@class="job-detail"]//text()')  #职位详情
        # Job_description=re.sub(r'[\s/]','',Job_description)
        desc=''.join(html.xpath('//div[@class="job-detail"]//text()')).strip()   #拼接
        work_address=html.xpath('//div[@class="work_addr"]//text()')[3] #工作地址
        CompanyName = html.xpath('//h3[@class="fl"]/em/text()')[0]  # 公司名字
        Company_Basic_Information=html.xpath('//li/h4/text()')  #公司基本信息

        position={
            '职位名字':Position_name,
            '薪水':salary,
            '职位诱惑':Position_the_temptation,
            '职位详情':Job_description,
            '工作地址':work_address,
            '公司名字': CompanyName,
            '公司基本信息':Company_Basic_Information,
        }
        self.positions.append(position)
        print(position)
        print('='*40)







if __name__ == '__main__':
    spider=lagouSpitder()
    spider.run()

对了还有一件事~看完觉得可以的话点个赞吧,切莫白嫖?

至此程序就全部写完啦?

声明

本文仅限于做技术交流学习,请勿用作任何非法用途!

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-11-23 12:17:56  更:2021-11-23 12:18:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 0:47:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码