该代码主要用于学习参考
@功能1:实现了爬取不同的产品类目
@功能2:获取商品图片、商品名称、商品价格、购买人数、店铺名称
@功能3:实现数据库存储、对网页节点的加载优化

Mongdb数据库截图.png

输出结果.png
代码部分
#!/usr/home/orangepi/pythonWJ python3
# -*- encoding: utf-8 -*-
"""
@File : 实战Selenium爬取淘宝商品.py
@Contact : t.ianxi@foxmail.com
@License : // Copyright (C) 2018 Milo Yip<dell>
@Modify Time @Author @Version @Desciption
------------ ------- -------- -----------
2022/6/11 20:48 MuKe~ 1.0 None
"""
import pymongo
from selenium import webdriver # 浏览器驱动模块
from selenium.common.exceptions import TimeoutException # 时间异常模块
from selenium.webdriver.common.by import By # CSS选择器
from selenium.webdriver.support import expected_conditions as EC # 异常模块
from selenium.webdriver.support.wait import WebDriverWait # 匹配等待条件
from urllib.parse import quote # 字符串转换URL编码
from pyquery import PyQuery as pq # 解析器
# ======================================================================================================================
# 实例化Chrome()方法
browser = webdriver.Chrome()
# 延时等待十秒内未打开抛出异常
wait = WebDriverWait(browser,30)
# 定义一个关键字
KEYWORD = "戴尔笔记本电脑"
# ======================================================================================================================
def index_page(page):
"""
抓取索引页,获取网页节点数据
:param page:页码
:return:None
"""
print("正在爬取第",page,'页')
# 捕获获取网页节点可能发生的异常
try:
# 拼接url,q参数为搜索关键字,quote()方法用来将字符串转换为URL编码
url = 'https://s.taobao.com/search?q='+quote(KEYWORD)
# 发生GET请求url
browser.get(url)
# 页码大于1则执行
if page >= 1:
"""
@节点说明:1、'#mainsrp-pager div.form > iuput'节点是网页中最下面的“分页导航输入框”
2、selenium.webdriver.support模块的expected_conditions函数中的presence_of_element_located()方法用于异常判断是否加载出该节点
3、"By.CSS_SELECTOR" CSS选择器
4、wait.until()方法用于判断十秒钟节点加载抛出异常
"""
input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager div.form > input')))
print("账户处于登录状态~")
"""
@节点说明:1、'#mainsrp-pager div.from > span.btn.J_Submit'节点是网页中最下面的“分页导航确定控件”
2、selenium.webdriver.support模块的expected_conditions函数中的element_to_be_clickable()方法
3、"By.CSS_SELECTOR" CSS选择器
4、wait.until()方法用于判断十秒钟节点加载抛出异常
"""
submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#mainsrp-pager div.form > span.btn.J_Submit')))
# 调用clear()方法
input.clear()
# 调用send_keys()方法输入“页码”
input.send_keys(page)
# 调用click()方法让selenium模拟鼠标点击“分页导航确定控件”
submit.click()
"""
@节点说明:1、'#mainsrp-pager li.itme.active > span'节点是网页中最下面“分页导航中的当前页”
2、selenium.webdriver.support模块的expected_conditions函数中的text_to_be_present_in_element()方法用于等待指定的文本出现在某一节中时机返回成功
3、text_to_be_present_in_element()方法这里用于检测当前高亮的页码节点是否和page变量传过来的页码数一致,如果是,就证明页码成功跳转到了这一页
4、wait.until()方法用于判断十秒钟节点加载抛出异常
5、"By.CSS_SELECTOR" CSS选择器
"""
wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager li.item.active > span'),str(page)))
"""
@节点说明:1、'#.m-itemlist .items .item'节点中包含了图片、价格、商品名称、购买人数、店铺名称、商家地址数据。
2、selenium.webdriver.support模块的expected_conditions函数中的presence_of_all_elements_located()方法用于异常判断是否加载出该节点
3、"By.CSS_SELECTOR" CSS选择器
4、wait.until()方法用于判断十秒钟节点加载抛出异常
"""
wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'.m-itemlist .items .item')))
# 实例化get_products()(自定义的方法,用于解析获取到的网页节点中的数据)
get_products()
except TimeoutException:
# 发生异常后实例化index_page()方法(自定义的方法,用于获取网页节点,抓取索引页等操作),这里相当于出现异常后重新启动index_page()中的代码。
index_page(page)
print("发生异常!!!正在重试中……")
# ======================================================================================================================
def get_products():
"""
提取节点中商品数据
:return:None
"""
# 调用page_source属性获取页码的源代码
html = browser.page_source
# 实例化PyQuery()方法并传入html源代码解析
doc = pq(html)
# print(doc)
# 使用CSS选择器匹配html页面中'#mainsrp-itemlist .items .item'节点(该节点包含了图片、价格、商品名称、购买人数、店铺名称、商家地址数据)
items = doc('#mainsrp-itemlist .items .item').items()
# 对获取到的数据进行历遍(图片、价格、、购买人数、商品名称、店铺名称、商家地址)item的数据需要历遍使用find()方法传入CSS选择器,获取单个商品的特定内容
for item in items:
"""
@解析方法说明:1、构造一个字典用于提取有用的数据
2、'data-src'是原图,‘src’是缩略图(小图),这里选择原图,调用find()方法用于找到'.pic .img'(图片)的这个节点,attr()方法用于获取节点中的'data-src'(图片的下载链接)属性
3、调用find()方法用于找到'.price'(价格)的这个节点,调用text()方法用于获取节点中的文本信息
4、调用find()方法用于找到'.deal-cnt'(购买人数)的这个节点,调用text()方法用于获取节点中的文本信息
5、调用find()方法用于找到'.title'(商品名称)的这个节点,调用text()方法用于获取节点中的文本信息
6、调用find()方法用于找到'shop'(店铺名称)的这个节点,调用text()方法用于获取节点中的文本信息
7、调用find()方法用于找到'location'(商家地址)的这个节点,调用text()方法用于获取节点中的文本信息
"""
product = {
'image':item.find('.pic .img').attr('data-src'),
'price':item.find('.price').text(),
'deal':item.find('.deal-cnt').text(),
'title':item.find('.title').text(),
'shop':item.find('.shop').text(),
'location':item.find('.location').text()
}
print(product)
# 实例化save_to_mongo()(自定义的方法,连接Mongdb数据库、存储数据)
save_to_mongo(result=product)
# 定义一个数据库
MONGO_DB = 'Taobao'
# 指定集合名
MONGO_COLLECTION = 'Dell'
# 连接MongoDB数据库参数一为主机或IP,参数二为端口号默认27017 (连接数据库)
client = pymongo.MongoClient(host='localhost',port=27017)
# 指定数据库
db = client[MONGO_DB]
# ======================================================================================================================
def save_to_mongo(result):
"""
:param result:结果
:return: None
"""
try:
# 调用insert()方法将数据插入到Mongdb数据库中,result变量是get_products()方法中传来的product变量(包含着商品相关数据)
if db[MONGO_COLLECTION].insert(result):
print("储存到MongDB成功!")
except Exception:
print("储存到MongDB失败!")
# ======================================================================================================================
# 定义一个页码用于历遍(淘宝页面最大只有100页)
MAX_PAGE = 100
def main():
"""
调用index_page()方法,并传递参数(页码)
:return:None
"""
# 用于range()函数是从0开始的淘宝页面没有0页所以定义从1开始
for i in range(1,MAX_PAGE+1):
index_page(i)
# 定义一个main(程序入口)
if __name__ == '__main__':
main()