继续上一个爬虫,所以说selenium加browsermobproxy

news2024/11/29 4:28:54

继续,书接上回,这次我通过jsrpc,也学会了不少逆向的知识,感觉对于一般的网站应该都能应付了。当然我说的是简单的网站,遇到那些混淆的,还有那种猿人学里面的题目,还是免谈了。那种需要的水平太高,我学习爬虫的目的也不是找什么工作,只是为了找数据,能够满足我找数据的需要就好。

现在我的初步问题已经解决了,原以为可以使用jsrpc一路搜集数据。可是还是遇到了新的问题。

接下来我想搜集这个网站的志愿服务项目的数据。发现这个网站的请求类型也比较复杂,要抓到某一个项目的数据,需要多次点击,定位到那个项目,而且进入项目的新页面,好像jsrpc获得的参数也是没什么用的了。

不知道为什么。可以先看一下。

这时,我知道这个query应该是也带bean参数。

 那么再次截获它的i值,就可以使用rpc,获得bean参数吧,想着时这样的。

这个query,地址是:/webapi/listProjectsFortisWeb/query

那么我们就找这个请求时的i

 i值有了,可以直接请求了吧。但是结果令人失望

得到的结果一直是固定的那么几个东西。即使换了i,换了参数,也会得到同样的结果。我也不太明白为什么。可能是网站需要经过几次鼠标点击,在点击的过程中,请求变了,我使用python请求,并没有抓到他那个真实的请求。

过程太复杂,我想我也研究不出来,比不了那些搞网站的。所以眼看又进入了困境。

这时候,想到了selenim。虽然一直以来都觉得selenium慢的要死。但是没办法啊,我会的,能够用的都用的差不多了,不会的也学了,学的也快吐了。不想再继续搞下去了,想着selenium慢就慢吧,好歹也是个办法。

环境配置

先安装 

pip install browsermob-proxy

pip install selenium

然后需要根据自己的浏览器版本,下载相应的webdriver

我的是chrome116,需要chrome116的webdriver。

直接从官网下。下好之后放到虚拟环境里。

另外还需要 browsermobproxy的环境,也是直接百度搜,下载下来。

browsermobproxy的使用

说干就干, 但是还有一个问题,就是我怎么能让senenium返回给我一个json,也就是一个动态网站返回给我的东西,我怎么截取这个json。selenium一旦渲染出来,就是一个网页元素了。怎么抓取到服务器发给我的json呢。

这时候看到知乎上一个帖子介绍了browsermobproxy。感觉可以用,就试了一下。

确实可以。简单来说,这个库就是相当于一个python版的fiddler,只不过fiddler是集成在一个软件里面,python调用不方便。但是这个库直接安装到python里面就可以了。简单

直接pip install就可以。

然后我也放弃了使用rpc方法,直接使用python模拟鼠标点击。

 简单粗暴。就是慢点。

直接上代码,

import json
from selenium.webdriver.common.keys import Keys
import numpy as np
import re
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from browsermobproxy import Server
from selenium.webdriver.chrome.options import Options
import os
import requests
import time

js="var q=document.documentElement.scrollTop=10000"

# 开启proxy
def start_proxy(har_name):
    server = Server(r'E:\code\codeForArticle2023\sdzyfw2\sdzyfw2.0\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat')
    server.start()
    proxy = server.create_proxy()
    print(proxy.proxy)
    proxy.new_har(har_name, options={"captureHeaders": True, "captureContent":True})
    return  proxy

# 打开driver
def start_driver(proxy):
    chrome_options = Options()
    chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy))
    chrome_options.add_argument('--ignore-certificate-errors')
    chrome_options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors"])

    driver = webdriver.Chrome(executable_path=r'venv/Scripts/chromedriver-win64/chromedriver.exe', options=chrome_options)
    driver.get("http://sd.chinavolunteer.mca.gov.cn/subsite/shandong/project")
    return driver


# 进入页面
def fetch_yantai(driver):
    ele = WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.XPATH, u'//div//a[text()="烟台市"]')), u'没有发现内容')
    if ele:
        item = driver.find_element_by_xpath("//div//a[text()='烟台市']")
        item.click()

    ele = WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.XPATH, u'//div//a[text()="芝罘区"]')), u'没有发现内容')
    if ele:
        item2 = driver.find_element_by_xpath("//a[text()='芝罘区']")
        item2.click()

    ele = WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.XPATH, u'//div//a[text()="已结项"]')), u'没有发现内容')
    if ele:
        item3 = driver.find_element_by_xpath("//a[text()='已结项']")
        item3.click()

def switch_to_proj_list_page(projList_pageNum):
    pn = int(projList_pageNum)
    print(pn)
    element = driver.find_element_by_css_selector(".pages input")
    element.send_keys(Keys.CONTROL + "a")
    element.send_keys(Keys.DELETE)
    time.sleep(2)
    element.send_keys(f"{pn}")
    time.sleep(2)
    driver.find_element_by_xpath("//a[text()='跳转']").click()


# 获取项目并且点击 num是第几个项目
def get_proj(driver, num):

    ele = WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.CSS_SELECTOR, u'div.panel-card')), u'没有发现内容')
    if ele:
        panels = driver.find_elements_by_css_selector(".panel-card")
        p1 = panels[num]
        print(len(panels))

    link = p1.find_element_by_css_selector('h2')
    link.click()

    win_hans = driver.window_handles
    driver.switch_to.window(win_hans[-1])

#采集信息

# 进入时长公示 页面,返回 page_num
def go_to_time(driver):
    # 获取项目了之后,需要进入新的一页,进入项目的详情页。
    page_num = 0
    ele =  WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.XPATH, "//span[text()='时长公示']")), u'没有发现内容')
    # 如果出现时长公示了,那么就可以点击时长公示,让网站显示时长。
    # 接下来要判断的是,是否有时长公示
    if ele:
        shijian  = driver.find_element_by_xpath("//span[text()='时长公示']")
        shijian.click()
    pages = WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".pages")), u"没有时长页面")
    print(pages)
    if pages:
        recordsNum = driver.find_element_by_css_selector(".pages span:last-child").text
        print(recordsNum)
        rn = re.search(r'共(\d+)条', recordsNum).group(1)
        rn = int(rn)
        page_num = int(np.ceil(rn/8))
    print(page_num)

    return page_num

def click_pages(driver, page_num):
    if page_num == 0:
        pass
    # 若只有一页,那么不需要操作了,直接退出
    if page_num == 1:
        pass
        # 若超过2页,那么需要不断点击下一页,点击下一页需要等待,这里使用显示等待
    if page_num >= 2:

        for i in range(2, page_num+1):
            time.sleep(3)
            ele = WebDriverWait(driver, 10, 0.2).until(
                EC.visibility_of_element_located((By.XPATH, "//a[text()='下一页']")), u'没有发现内容')
            if ele:
                next_page = driver.find_element_by_xpath("//a[text()='下一页']")
                next_page.click()

                WebDriverWait(driver, 10, 0.2).until(
                    EC.visibility_of_element_located((By.XPATH, "//a[text()='下一页']")), u'没有发现内容')

# 返回结果
def get_resp(driver, proxy):
    result = proxy.har
    timefortisProj =[]
    postfortisProj = []
    inforfortisProj = []
    for rs in result['log']['entries']:
        if   "webapi/timeFortisWeb/query" in rs['request']['url']:  # 时长记录
            # 时长请求 url
            print(rs['request']['url'])
            timefortisProj.append(rs['response']['content']['text'])

        if 'getProjectInfoFortisWeb' in rs['request']['url']:  # 发起人信息
            print(rs['request']['url'])
            inforfortisProj.append(rs['response']['content']['text'])

        if 'ProjectPostFortisWeb/query' in rs['request']['url']:  # 任务信息
            print(rs['request']['url'])
            postfortisProj.append(rs['response']['content']['text'])

    dt = {
        "time":timefortisProj,
        "post":postfortisProj,
        "info":inforfortisProj
    }
    return dt



def save_file(result, qu, har_name):
    with open(f"sdzyfw2/sdzyfw2.0/{qu}/{har_name}.json",'w', encoding='utf-8') as f:
        f.write(json.dumps(result, ensure_ascii=False))
    print("success!!!")



#---------------------------------------------------------#
#----           *         *        ----#
#---------------------------------------------------------#

projList_pageNum = "002"
num = 3
proj_num =  str(num)
har_name = "proj_" + projList_pageNum + "_"+ proj_num
print(har_name)
#建立一个 mobproxy代理,返回端口号
proxy = start_proxy(har_name)
#通过selenium打开目标网站,
driver = start_driver(proxy)

fetch_yantai(driver)
driver.execute_script(js)

if projList_pageNum != "001":
    switch_to_proj_list_page(projList_pageNum)


get_proj(driver, num)

driver.execute_script(js)

# 返回一个页码
try:
    page_num = go_to_time(driver)
except:
    page_num = 0

driver.execute_script(js)

# 根据页码翻页
if page_num is None:
    pass
else:
    try:
        click_pages(driver, page_num)
    except:
        pass


result = get_resp(driver, proxy)

qu = "zhifuqu"
save_file(result, qu, har_name)




 上面的翻页部分的逻辑还没整清楚,会出现bug,暂时先放上。回头把翻页部分整理好了再修改吧。大致思想基本没啥问题。

代码也没怎么整理,大致的意思就是使用selenium呼出浏览器,然后在浏览器里面一步步找到我想要的东西,最后把这些所有的包存放到一个har里面。后期在筛选har,提取我想要的信息。

发现这个也是很无敌的,直接免去了反反爬措施。因为就是浏览器,除非网站对webdriver有检测,不然也没办法。就老老实实的一个一个爬吧。

这个过程,看上去不复杂,其实挺麻烦,要一个个执行。估计要有几千个,想了想,还是找别人帮忙吧。其实就是学习了以下mobproxy。真要这么做的话,还是挺麻烦。最好是逆向到参数,直接提取。不推荐这种方式,当然,如果没办法,那么这个真的是终极大招了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1008224.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智慧园区:AI边缘计算技术与视频监控汇聚平台打造智慧园区解决方案

一、行业趋势与背景 智慧园区是现代城市发展的重要组成部分,通过智能化技术提高园区的运营效率、降低成本、增强环境可持续性等具有重要作用。在智慧园区中,人工智能和视频汇聚技术是重要的前置技术。人工智能技术可以实现对数据的智能化处理和分析&…

SpringMVC的拦截器和JSR303的使用

目录 一、JSR303 二、拦截器(interceptor) 一、JSR303 1.1.什么是JSR303 JSR 303,它是Java EE(现在称为Jakarta EE)规范中的一部分。JSR 303定义了一种用于验证Java对象的标准规范,也称为Bean验证。 Bean验…

2023年五一杯数学建模A题无人机定点投放问题求解全过程论文及程序

2023年五一杯数学建模 A题 无人机定点投放问题 原题再现: 随着科学技术的不断发展,无人机在许多领域都有着广泛的应用。对于空中执行定点投放任务的无人机,其投放精度不仅依赖于无人机的操作技术,而且还与无人机执行任务时所处状…

【C++进阶】:红黑树

红黑树 一.红黑树简单实现1.性质二.更新颜色1.情况一2.情况二3.情况三 3.完整代码(代码有注释,稍微画图很容易理解,旋转部分可以看我的AVL树博客) 二.map和set1.基本实现2.迭代器 本篇的前置条件是AVL树的旋转和搜索树,如果不了解可以看看我的AVL树博客 …

机器学习(13)---降维实例

目录 一、人脸识别降维1.1 查看原图1.2 降维后的图像 二、迷你案例2.1 用人脸识别看PCA降维后的信息保存量2.2 噪音过滤2.3 手写数字降维(随机森林)2.4 手写数字降维(KNN)2.4 案例总结 一、人脸识别降维 1.1 查看原图 注意&#…

vue3 自定义Hooks

文章目录 前言一、Hooks是什么?二、图片转换Base641.Hooks2.使用 三、监听元素宽高(自定义指令Hooks)1.Hooks2.使用 总结 前言 本文主要记录了vue3学习中自定义Hooks和vue2中Mixins的使用与案例。 一、Hooks是什么? Hooks用来处…

html给下拉框添加搜索、分页功能(通过ajax从服务器获取搜索数据)

文章目录 下拉框搜索分页功能开发功能使用源码和Demo(点个赞再走咯)test.htmlsearchable-select.csssearchserver-select.js 下拉框搜索分页功能开发 最近需要开发一个下拉框从服务器通过Ajax请求搜索数据库并且分页的组件,源码和demo放在下面…

【微信小程序开发】宠物预约医疗项目实战-开发功能介绍

【微信小程序开发】宠物医院项目实战-开发功能介绍 前言 本项目主要带领大家学习微信小程序开发技术,通过一个完整的项目系统的学习微信小程序的开发过程。鉴于一些同学对视频教学跟不上节奏,为此通过图文描述的方式,完整的将系统开发过程记…

【Redis】Redis常见面试题

【Redis】Redis常见面试题(3) 文章目录 【Redis】Redis常见面试题(3)1. 特性&应用场景1.1 Redis能实现什么功能1.2 Redis支持分布式的原理1.3 为什么Redis这么快1.4 Redis实现分布式锁1.5 Redis作为缓存 2. 数据类型2.1 Redis…

C# 委托学习1

委托的标准定义是,委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用; 在实例化委托时,你可以将其实例与任何具有兼容签名和返回类型的方法相关联; 还有一种定义看上去也是正确的:委托是…

ModuleNotFoundError: No module named ‘gevent‘

1、先确定pip版本: pip3 list: 看到没有gevent包 如果pip版本不是最新版可以使用命令python -m pip install --upgrade pip进行更新, 2、安装 pip3 install gevent 安装完成

联合国教科文发布,ChatGPT等生成式AI教育应用指南

联合国教科文组织(UNESCO)在官网发布了,全球首个《生成式AI与教育未来》的应用指南。呼吁各国实施适当的政策,以确保在教育中应用以人为本的方法来使用生成式AI。(指南下载地址:https://unesdoc.unesco.org…

排序(希尔、快速、归并排序)

文章目录 1.排序的概念及其运用 2.插入排序 3.选择排序 文章内容 1.排序的概念及其运用 1.1排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性:假定在…

K8s上安装gitlab-ce

文章目录 K8s上安装gitlab-ce操作如下gitlab-deployment.yml K8s上安装gitlab-ce 前言   使用pv-pvc来持久化gitlab的数据,配置,日志文件。   pod启动后需要需要修改external_url然后重启pod。 操作如下 mkdir -p /mnt/data01/gitlab ctr -n k8s.…

C# Onnx Yolov8 Cls 分类

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System…

sql server 触发器的使用

看数据库下的所有触发器及状态 SELECT a.name 数据表名 , sysobjects.name AS 触发器名 , sysobjects.crdate AS 创建时间 , sysobjects.info , sysobjects.status FROM sysobjects LEFT JOIN ( SELECT * FROM sysobjects WHERE xtype U ) AS a ON sysobjects.parent_obj a.…

Git: 工作区、暂存区、本地仓库、远程仓库

参考链接: Git: 工作区、暂存区、本地仓库、远程仓库 https://blog.csdn.net/weixin_36750623/article/details/96189838

阿里云通义千问向全社会开放,近期将开源更大参数规模大模型

9月13日,阿里云宣布通义千问大模型已首批通过备案,并正式向公众开放,广大用户可登录通义千问官网体验,企业用户可以通过阿里云调用通义千问API。 通义千问在技术创新和行业应用上均位居大模型行业前列。IDC最新的AI大模型评估报告…

腾讯云AI超级底座新升级:训练效率提升幅度达到3倍

大模型推动AI进入新纪元,对计算、存储、网络、数据检索及调度容错等方面提出了更高要求。在9月7日举行的2023腾讯全球数字生态大会“AI超级底座专场”上,腾讯云介绍异构计算全新产品矩阵“AI超级底座”及其新能力。 腾讯云副总裁王亚晨在开场致辞中表示&…

创建第一个MyBatis框架--保姆级教学

文章目录 前言一、创建一个空的mybatis项目二、创建一个Maven模块三、各个文件的配置四、总结 前言 在idea上创建我的第一个MyBatis框架 一、创建一个空的mybatis项目 1、new一个新的项目 2、选择最下面,创建一个空项目 3、为空项目取一个名字,位置可以自己选 4、点…