- 官方文档: Selenium 浏览器自动化项目
Selenium 是支持 web 浏览器自动化的一系列工具和库的综合项目。它提供了扩展来模拟用户与浏览器的交互,用于扩展浏览器分配的分发服务器,以及用于实现 W3C WebDriver 规范的基础结构,该规范允许您为所有主要 Web 浏览器编写可互换的代码。
Selenium 的核心是 WebDriver,这是一个编写指令集的接口,可以在许多浏览器中互换运行。 这里有一个最简单的说明:
1 | from selenium import webdriver |
ProxyPool 是爬虫代理池 IP 项目,主要功能为定时采集网上发布的免费代理验证入库,定时验证入库的代理保证代理的可用性,提供 API 和 CLI 两种使用方式。同时你也可以扩展代理源以增加代理池IP的质量和数量。
部署代理服务 ProxyPool
下载代码到本地
1
git clone https://github.com/jhao104/proxy_pool.git
安装依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 进入 proxy_pool 项目目录
cd proxy_pool
# 创建虚拟环境
python -m venv ./venv
# 激活虚拟环境
source venv/bin/activate
# 升级 pip 工具
pip install -U pip
# 安装依赖
pip install -r requirements.txt更新配置,配置文件
setting.py
位于项目的主目录下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 配置API服务
HOST = "0.0.0.0" # IP
PORT = 5010 # 监听端口
# 配置 redis 数据库配置
DB_CONN = 'redis://@127.0.0.1:8888/0'
# 配置 ProxyFetcher
PROXY_FETCHER = [
"freeProxy01", # 这里是启用的代理抓取方法,所有fetch方法位于fetcher/proxyFetcher.py
"freeProxy02",
# ....
]启动 proxy_pool 项目
1
2
3
4
5# 启动调度程序
$ python proxyPool.py schedule
# 启动webApi服务
$ python proxyPool.py server编写代码使用代理,爬虫代码要对接代理池目前有两种方式: 一是通过调用API接口使用, 二是直接读取数据库.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import requests
def get_proxy():
while True:
resp = requests.get("http://127.0.0.1:5010/get/").json()
# 只调用中国境内的代理 IP
if '中国' in resp['region']:
return resp
else:
continue
def delete_proxy(proxy):
requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy))
Selenium 自动化操作
实战目标:爬取波奇宠物网站商品信息,包括商品的标题、价格、品牌,主图等信息。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166from proxy import get_proxy
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
def get_tracks(driver):
"""
滑块解锁
:param driver: 浏览器实例对象
"""
try:
# 如果出现滑动验证码,则进行滑动解锁
if driver.find_element(by=By.CSS_SELECTOR, value='#PC > div.contentbg > div > div.right > h1').text == '访问验证':
# 事件参数对象
actions = ActionChains(driver)
# 捕捉滑块元素
slide_btn = driver.find_element(by=By.ID, value='nc_1_n1z')
# 观察网站滑块移动的长度和位置
actions.drag_and_drop_by_offset(slide_btn, 252, 0).perform()
sleep(0.5)
except Exception:
pass
def generate_driver():
"""
创建浏览器实例对象
"""
# chrome 选项配置
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
# 配置使用代理
chrome_options.add_argument('--proxy-server=%s' % proxy)
# 配置不打开浏览器窗口
chrome_options.add_argument('headless')
# 创建浏览器对象
chrome = webdriver.Chrome(options=chrome_options)
return chrome
def get_data(driver, url):
"""
获取页面所有商品
:param driver: 浏览器实例对象
:param url: 页面 URL
"""
# 浏览器访问地址
driver.get(url)
# 隐式等待,确保动态内容节点被完全加载出来——时间感受不到
driver.implicitly_wait(2)
# 最大化浏览器窗口,主要是防止内容被遮挡
driver.maximize_window()
# 强制等待3秒
sleep(0.1)
get_tracks(driver=driver)
try:
data = driver.find_elements(
by=By.CSS_SELECTOR,
value='#listcontent > div.rightBar > div.product_container > div > ul > li'
)
return data
except Exception as e:
print(e)
def parse_commodity(url):
"""
解析商品页面信息
:param url: 商品详情页面 URL
"""
# 商品图片列表
images = []
# 创建浏览器实例对象 shop_chrome
commodity_chrome = generate_driver()
# 浏览器访问地址
commodity_chrome.get(url)
# 隐式等待,确保动态内容节点被完全加载出来
commodity_chrome.implicitly_wait(1)
# 最大化浏览器窗口,主要是防止内容被遮挡
commodity_chrome.maximize_window()
# 强制等待 0.1 秒
sleep(0.1)
# 判断是否滑块验证,并解锁滑块
get_tracks(driver=shop_chrome)
# 获取商品类型
commodity_spec = commodity_chrome.find_element(
by=By.CSS_SELECTOR,
value='#content > div.body_auto > div.shop_t.mt10.clearfix >'
'div.shop_t_r.right > div.brand > dl:nth-child(1) > dd > a'
).text.replace('\n', '')
# 获取商品价格
commodity_price = commodity_chrome.find_element(
by=By.ID,
value='bqPrice'
).text.replace('\n', '')
# 获取商品名称
commodity_name = commodity_chrome.find_element(
by=By.CLASS_NAME,
value='shop_name'
).text.replace('\n', '')
# 获取商品编号
commodity_num = commodity_chrome.find_element(
by=By.CSS_SELECTOR,
value='#content > div.body_auto > div.shop_t.mt10.clearfix > '
'div.shop_t_r.right > div.brand > dl:nth-child(2) > dd'
).text.replace('\n', '')
# 获取商品图片
commodity_images = commodity_chrome.find_element(
by=By.CLASS_NAME,
value='pro_s_img'
).find_elements(by=By.TAG_NAME, value='img')
for img in commodity_images:
images.append(img.get_attribute('src'))
print('品牌: {commoditySpec}, 商品名称: {commodityName}, 商品编号: {commodityNum}, 价格: {commodityPrice}, 主图: {images}'.format(
commoditySpec=commodity_spec,
commodityName=commodity_name,
commodityNum=commodity_num,
commodityPrice=commodity_price,
images=images
))
record = {
'commodity_spec': commodity_spec,
'commodity_name': commodity_name,
'commodity_num': commodity_num,
'commodity_price': commodity_price,
'commodity_images': images
}
return record
if __name__ == '__main__':
# 获取代理IP
proxy = get_proxy()
print('当前使用的 IP 地址是:%s, 地区是:%s' % (proxy['proxy'], proxy['region']))
# 所有商品列表
all_commodity = []
# 创建浏览器实例
browser = generate_driver()
# 爬取页面为 1~ 24 页
for page in range(1, 25):
# 渲染页面
url = 'https://shop.boqii.com/cat/list-576-0-0-0-0-0-p{0}.html'.format(page)
print('正在获取 {} 页面的商品内容'.format(url))
# 获取当前页面所有商品
goods = get_data(driver=browser, url=url)
# 将结果写入到当前目录下的 commodity.txt 文件
with open('commodity.txt', 'w', encoding='utf-8') as f:
for good in goods:
# 获取商品的详情页面
link = good.find_element(by=By.TAG_NAME, value='a').get_attribute('href')
# 解析商品的详细信息
commodity_info = parse_commodity(link)
# 写入文件
f.writelines('{}\n'.format(str(commodity_info)))
# 追加商品信息字典到 all_commodity 列表
all_commodity.append(commodity_info)