记录一下最近一次爬虫的场景和应用,很久没有写了,而且之前的脚本也不好找了。
爬虫场景:需要用户登录系统,输入用户的账号和密码进入系统,进入系统页面后,在chrome浏览器可以查看到,前端页面展示的数据是通过ajax请求后端服务器的数据。
策略:如果不需要登录系统,爬虫很好实现。
我想到的有两种方法,第一种方法手动,比较笨拙,如果数据量不是很多,也够用。
现在很多网站都使用Ajax作为数据接口,这样其实也方便爬虫爬取数据。
chrome浏览器按F12键,调出开发者工具,切换到“Network”,选择筛选XHR资源。当我们点击关注的某些页面,会向后端服务器发送请求返回ajax文件,该ajax文件里面包含我们需要爬取的信息。
点击红色框的下载按钮,保存har文件。下次可以点击旁边的上传按钮,上传har文件。另外,也有一些插件可以辅助har文件浏览。
image1.png
第二种方法是Selenium+chrome driver 实现模拟登陆,使用 Selenium 获取 ajax (xhr) 数据,注意到url是动态生成的,简单的通过requests的post或get方法不易实现。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os, time, json
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
if __name__ == '__main__':
# 引入chromedriver
chrome_options = webdriver.ChromeOptions()
# chrome_options.add_argument('--headless')
# chrome_options.add_argument('--no-sandbox')
# chrome_options.add_argument("--disable-extensions")
# chrome_options.add_argument("--disable-gpu")
prefs = {
'download.default_directory': os.getenv('OS_LOG_PATH')
}
chrome_options.add_experimental_option('prefs', prefs)
# make chrome log requests
capabilities = DesiredCapabilities.CHROME
# caps['goog:loggingPrefs']
capabilities["goog:loggingPrefs"] = {"performance": "ALL"} # newer: goog:loggingPrefs
# capabilities['acceptSslCerts'] = True
#browser = webdriver.Chrome(executable_path=r'/opt/google/chrome/chromedriver', options=chrome_options)
browser = webdriver.Chrome(executable_path=r'C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe', options=chrome_options,desired_capabilities=capabilities)
browser.implicitly_wait(3)
browser.get("https://#########")
# 输入账号
browser.implicitly_wait(3)
username_inputbox = browser.find_elements(By.XPATH, '//*[@id="app"]/section/div[1]/div/div[1]/div/div[2]/form/div[1]/div/div/div/input')[0]
username_inputbox.click()
browser.implicitly_wait(3)
username_inputbox.clear()
username_inputbox.send_keys("#######")
# 输入密码
browser.implicitly_wait(3)
password_inputbox = browser.find_elements(By.XPATH, '//*[@id="app"]/section/div[1]/div/div[1]/div/div[2]/form/div[2]/div/div/div/input')[0]
password_inputbox.click()
browser.implicitly_wait(3)
password_inputbox.clear()
password_inputbox.send_keys("#######")
# 点击登录
browser.implicitly_wait(3)
submit_btn = browser.find_elements(By.XPATH, '//*[@id="app"]/section/div[1]/div/div[1]/div/div[2]/form/div[3]/div/button')[0]
submit_btn.click()
# 等待5秒
time.sleep(5)
#-------------------------------------------------
base_url = "https://#########"
browser.get(base_url)
time.sleep(3)
# extract requests from logs
logs_raw = browser.get_log("performance")
logs = [json.loads(lr["message"])["message"] for lr in logs_raw]
def log_filter(log_):
return (
# is an actual response
log_["method"] == "Network.responseReceived"
# and json
and "json" in log_["params"]["response"]["mimeType"]
)
for log in filter(log_filter, logs):
request_id = log["params"]["requestId"]
resp_url = log["params"]["response"]["url"]
print(request_id)
print(f"Caught {resp_url}")
json_str = json.dumps(browser.execute_cdp_cmd("Network.getResponseBody", {"requestId": request_id}), indent=4)
# 创建一个params.json文件
with open(f'{request_id}.json', 'w') as f:
f.write(json_str) # 将json_str写到文件中
browser.quit()
下载生成每个json文件
image.png
参考链接:
1.https://qiita.com/hatobeam75/items/dbe45324c368eedd4460
网友评论