繼續(xù),書接上回,這次我通過jsrpc,也學會了不少逆向的知識,感覺對于一般的網(wǎng)站應該都能應付了。當然我說的是簡單的網(wǎng)站,遇到那些混淆的,還有那種猿人學里面的題目,還是免談了。那種需要的水平太高,我學習爬蟲的目的也不是找什么工作,只是為了找數(shù)據(jù),能夠滿足我找數(shù)據(jù)的需要就好。
現(xiàn)在我的初步問題已經(jīng)解決了,原以為可以使用jsrpc一路搜集數(shù)據(jù)??墒沁€是遇到了新的問題。
接下來我想搜集這個網(wǎng)站的志愿服務(wù)項目的數(shù)據(jù)。發(fā)現(xiàn)這個網(wǎng)站的請求類型也比較復雜,要抓到某一個項目的數(shù)據(jù),需要多次點擊,定位到那個項目,而且進入項目的新頁面,好像jsrpc獲得的參數(shù)也是沒什么用的了。
不知道為什么??梢韵瓤匆幌隆?/p>
這時,我知道這個query應該是也帶bean參數(shù)。
?那么再次截獲它的i值,就可以使用rpc,獲得bean參數(shù)吧,想著時這樣的。
這個query,地址是:/webapi/listProjectsFortisWeb/query
那么我們就找這個請求時的i
?i值有了,可以直接請求了吧。但是結(jié)果令人失望
得到的結(jié)果一直是固定的那么幾個東西。即使換了i,換了參數(shù),也會得到同樣的結(jié)果。我也不太明白為什么。可能是網(wǎng)站需要經(jīng)過幾次鼠標點擊,在點擊的過程中,請求變了,我使用python請求,并沒有抓到他那個真實的請求。
過程太復雜,我想我也研究不出來,比不了那些搞網(wǎng)站的。所以眼看又進入了困境。
這時候,想到了selenim。雖然一直以來都覺得selenium慢的要死。但是沒辦法啊,我會的,能夠用的都用的差不多了,不會的也學了,學的也快吐了。不想再繼續(xù)搞下去了,想著selenium慢就慢吧,好歹也是個辦法。
環(huán)境配置
先安裝?
pip?install?browsermob-proxy
pip?install selenium
然后需要根據(jù)自己的瀏覽器版本,下載相應的webdriver
我的是chrome116,需要chrome116的webdriver。
直接從官網(wǎng)下。下好之后放到虛擬環(huán)境里。
另外還需要 browsermobproxy的環(huán)境,也是直接百度搜,下載下來。
browsermobproxy的使用
說干就干,?但是還有一個問題,就是我怎么能讓senenium返回給我一個json,也就是一個動態(tài)網(wǎng)站返回給我的東西,我怎么截取這個json。selenium一旦渲染出來,就是一個網(wǎng)頁元素了。怎么抓取到服務(wù)器發(fā)給我的json呢。
這時候看到知乎上一個帖子介紹了browsermobproxy。感覺可以用,就試了一下。
確實可以。簡單來說,這個庫就是相當于一個python版的fiddler,只不過fiddler是集成在一個軟件里面,python調(diào)用不方便。但是這個庫直接安裝到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'沒有發(fā)現(xiàn)內(nèi)容')
if ele:
item = driver.find_element_by_xpath("http://div//a[text()='煙臺市']")
item.click()
ele = WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.XPATH, u'//div//a[text()="芝罘區(qū)"]')), u'沒有發(fā)現(xiàn)內(nèi)容')
if ele:
item2 = driver.find_element_by_xpath("http://a[text()='芝罘區(qū)']")
item2.click()
ele = WebDriverWait(driver, 10, 0.2).until(EC.visibility_of_element_located((By.XPATH, u'//div//a[text()="已結(jié)項"]')), u'沒有發(fā)現(xiàn)內(nèi)容')
if ele:
item3 = driver.find_element_by_xpath("http://a[text()='已結(jié)項']")
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("http://a[text()='跳轉(zhuǎn)']").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'沒有發(fā)現(xiàn)內(nèi)容')
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, "http://span[text()='時長公示']")), u'沒有發(fā)現(xiàn)內(nèi)容')
# 如果出現(xiàn)時長公示了,那么就可以點擊時長公示,讓網(wǎng)站顯示時長。
# 接下來要判斷的是,是否有時長公示
if ele:
shijian = driver.find_element_by_xpath("http://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, "http://a[text()='下一頁']")), u'沒有發(fā)現(xiàn)內(nèi)容')
if ele:
next_page = driver.find_element_by_xpath("http://a[text()='下一頁']")
next_page.click()
WebDriverWait(driver, 10, 0.2).until(
EC.visibility_of_element_located((By.XPATH, "http://a[text()='下一頁']")), u'沒有發(fā)現(xiàn)內(nèi)容')
# 返回結(jié)果
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']: # 發(fā)起人信息
print(rs['request']['url'])
inforfortisProj.append(rs['response']['content']['text'])
if 'ProjectPostFortisWeb/query' in rs['request']['url']: # 任務(wù)信息
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打開目標網(wǎng)站,
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)
# 根據(jù)頁碼翻頁
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)
?上面的翻頁部分的邏輯還沒整清楚,會出現(xiàn)bug,暫時先放上?;仡^把翻頁部分整理好了再修改吧。大致思想基本沒啥問題。
代碼也沒怎么整理,大致的意思就是使用selenium呼出瀏覽器,然后在瀏覽器里面一步步找到我想要的東西,最后把這些所有的包存放到一個har里面。后期在篩選har,提取我想要的信息。
發(fā)現(xiàn)這個也是很無敵的,直接免去了反反爬措施。因為就是瀏覽器,除非網(wǎng)站對webdriver有檢測,不然也沒辦法。就老老實實的一個一個爬吧。文章來源:http://www.zghlxwxcb.cn/news/detail-738871.html
這個過程,看上去不復雜,其實挺麻煩,要一個個執(zhí)行。估計要有幾千個,想了想,還是找別人幫忙吧。其實就是學習了以下mobproxy。真要這么做的話,還是挺麻煩。最好是逆向到參數(shù),直接提取。不推薦這種方式,當然,如果沒辦法,那么這個真的是終極大招了。文章來源地址http://www.zghlxwxcb.cn/news/detail-738871.html
到了這里,關(guān)于繼續(xù)上一個爬蟲,所以說selenium加browsermobproxy的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!