声明:此篇文章主要是观看静觅教学视频后做的笔记,原教程地址:https://cuiqingcai.com/
淘宝页面比较复杂,含有各种请求参数和加密参数,如果直接请求或者分析Ajax将会非常繁琐。Selenium是一个自动化测试工具,可以驱动浏览器去完成各种工作,比如模拟点击、输入和下拉等多种功能,这样我们只需关心操作,不需要关心后台发生了怎么样的请求下面对具体操作步骤进行详述
实现流程
1.搜索关键字:利用Selenium驱动浏览器搜索关键字,得到查询后的商品列表
2.分析页码并翻页:得到商品页码数,模拟翻页,得到后续页面的商品列表
3.分析提取商品内容:利用PyQuery分析源码,解析得到商品列表
4.存储至MongoDB:将商品列表信息存储到数据库MongoDB
具体实现
1.首先需要声明一个browser用来操作,我的是chrome。这里的wait是在后面的判断元素是否出现时使用,第二个参数为等待最长时间,超过该值则抛出异常
#创建一个浏览器对象
browser = webdriver.Chrome()
#十秒内寻找元素失败,将报出TimeoutException异常
wait = WebDriverWait(browser, 10)
2.声明好之后就需要进行打开网页、进行搜索的操作
def search():
"""
作用:通过关键字搜索得到搜索内容第一页产品信息,并返回搜索内容共计页码
"""
print('正在搜索')
try:
browser.get('https://www.taobao.com')
print(browser.page_source)
# 获取input输入框对象
input = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#q"))
)#
# 获取button提交对象
submit = wait.until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, "#J_TSearchForm > div.search-button > button")
)
)
# KEYWORD是config.py文件中定义的搜索关键字,可修改
input.send_keys(KEYWORD)
# 点击button提交按钮
submit.click()
# 通过CSS_SELECTOR选择器获取total页码
total_page = wait.until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.total")
)
)
# 解析页面内容,并将数据保存至MongoDB中
get_products()
return total_page.text
except TimeoutException:
# 出现超时访问就重新调用一次search
return search()
3.第一个页面操作之后,我们需要进行翻页操作,如下:
def next_page(page_number):
"""
作用:作人为翻页功能,并得到该页产品信息
page_number:循环的页码,将页码写入input框中
"""
print('正在翻页', page_number)
try:
# 获取input输入框对象
input = wait.until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > input")
)
)
# 获取button提交对象
submit = wait.until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, "div > div > div > div.form > span.btn.J_Submit")
)
)
# 将input框清空
input.clear()
# 向input框中输入页码
input.send_keys(page_number)
# 点击button提交按钮
submit.click()
wait.until(
# 验证输入框内的页码是否为当前高亮页码,如果是,则继续执行
# text参数是否在该span元素内,此处需要注意text的参数位置
EC.text_to_be_present_in_element(
(By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > ul > li.item.active > span'), str(page_number)
)
)
# 获取产品信息并保存至MongoDB
get_products()
except TimeoutException:
# 超时异常,则继续解析该页
next_page(page_number)
4.写完搜索操作和翻页操作后,我们需要完成对每个页面的商品信息获取功能
def get_products():
"""
作用:通过页面源代码,将产品信息保存至MongoDB中
"""
# 通过CSS_SELECTOR选择器,验证页面中是否存在产品对象
wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-itemlist .items .item"))
)
# 拿到页面源码
html = browser.page_source
# 通过pyquery找到产品对象
doc = pq(html)
items = doc('#mainsrp-itemlist .items .item').items()
# 遍历每个产品对象,组建数据内容
for item in items:
product = {
'image': item.find('.pic .img').attr('src'),
'price': item.find('.price').text(),
'deal': item.find('.deal-cnt').text()[:-3],
'title': item.find('.title').text(),
'shop': item.find('.shop').text(),
'location': item.find('.location').text()
}
# print(product)
# 将组建好的每个产品信息保存至MongoDB
save_to_mongo(product)
5.获取信息之后则需要对信息进行存储,将数据库关键参数定义在config.py文件中
#!/usr/bin/env python
# coding=utf-8
# 本地的数据库
MONGO_URL = 'localhost'
# 数据库的名称
MONGO_DB = 'taobao'
# 数据库的表名
MONGO_TABLE = 'products'
6.将组建好的每个产品信息保存至MongoDB
# 创建一个MongoDB对象
client = pymongo.MongoClient(MONGO_URL)
# 创建一个数据库,注意是[]而不是()
db = client[MONGO_DB]
def save_to_mongo(result):
"""
作用:将信息保存至MongoDB中
"""
try:
if db[MONGO_TABLE].insert(result):
print('Successfully save to MongoDB', result)
except Exception:
print('Failed save to MongoDB', result)
7.爬取调度器
def TbMeishi_Spider():
"""
作用:淘宝美食爬取调度器
"""
try:
total_page = search()
# 通过正则将search返回的total页码内容解析成数字形式
pattern = re.compile('(\d+)')
total_page = int(pattern.search(total_page).group(1))
# print(total_page)
# 遍历页码,传入next_page函数中,做整站爬取
for i in range(2, total_page + 1):
next_page(i)
except Exception:
print('有错误产生...')
finally:
browser.close()
8.代码完成到这里已经可以结束了,但是使用Selenium模拟会发现每次运行程序都会打开一个浏览器,然后自动操作,可以最直接地观察到代码的运行,但是假如不想弹出浏览器的话,可以使用PhantomJS来实现一个无界面的webkit浏览器。虽然没有界面,但dom渲染、js运行、网络访问、canvas/svg绘制等功能都很完备,在页面抓取、页面输出、自动化测试等方面有广泛的应用。下载PhantomJS地址:http://phantomjs.org/download.html,下载完成后解压缩,将PhantomJS添加到环境变量中即可
在config.py文件中加上
# 关闭load-images的功能,加快运行速度,默认开启,开启disk-cache缓存,默认关闭
SERVICE_ARGS = ['--load-images=false', '--disk-cache=true']
# 无界面浏览器,将browser改为
browser = webdriver.PhantomJS(service_args=SERVICE_ARGS)
# 设置PlantomJS的窗口大小,可能会影响内容下载
browser.set_window_size(1400, 900)
总结思考
1.目标网址不匹配
一开始使用显示等待访问,通过CSS_SELECTOR的id选择器找到网页元素,可最后程序都执行异常,每次都是TimeoutExceptions的异常错误。经过反复排查,才发现淘宝网有很多个站点
我在程序中使用的是:http://www.taobao.com
但是在进行网页分析的时候随意用百度搜了一个淘宝站点,它的站点是:https://uland.taobao.com/sem/tbsearch
两个站点地址不一样,网页元素也不一样,自己竟然会犯这种错误,应牢记,正确的选择元素应该是下面这几行
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
input = WebDriverWait(browser, 10).until(
EC.presence_of_element_located((By.ID, 'q'))
)
button = WebDriverWait(browser, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search'))
)
2.text参数是否在该span元素内,此处需要注意text的参数位置
# 验证text参数是否与选择器选择的元素文本内容一致
text_to_be_present_in_element(locator, text_)
3.完整源码地址:https://github.com/XiaoFei-97/TbMeishi_Spider
原文出处:https://www.jzfblog.com/detail/67,文章的更新编辑以此链接为准。欢迎关注源站文章!