Python使用Selenium模块实现模拟浏览器抓取淘宝商品美食信息功能示例


Posted in Python onJuly 18, 2018

本文实例讲述了Python使用Selenium模块实现模拟浏览器抓取淘宝商品美食信息功能。分享给大家供大家参考,具体如下:

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 selenium.common.exceptions import TimeoutException
from pyquery import PyQuery as pq
from bs4 import BeautifulSoup
from pymongo import MongoClient
from pymongo.errors import PyMongoError
url = 'http://www.taobao.com'
KEYWORD = '美食'
# monogdb配置信息
MONGO_HOST = "localhost"
MONGO_DATABASE = "taobao"
MONGO_TABLE = "meishi"
client = MongoClient(host=MONGO_HOST)
db = client[MONGO_DATABASE]
# PhantomJS 命令行相关配置
# 参见 http://phantomjs.org/api/command-line.html
SERVICE_ARGS = ['--disk-cache=true', '--load-images=false']
# driver = webdriver.Chrome() # 有界面
driver = webdriver.PhantomJS(service_args=SERVICE_ARGS) # 无界面
delay = 10
wait = WebDriverWait(driver, delay)
# print('windows size', driver.get_window_size())
# PhantomJs()的浏览器窗口很小,宽高只有400 * 300
driver.maximize_window() # 窗口最大化 # 对于PhantomJS来说设置窗口大小很关键,如果不设置,经常会出现问题
# driver.set_window_size(1920, 1080) # 设置浏览器窗口大小
# 模拟在淘宝网页中输入关键字搜索
def search():
  print("准备搜索 %s" % KEYWORD)
  try:
    driver.get(url)
    input_box = wait.until(
      EC.presence_of_element_located((By.CSS_SELECTOR, "input#q"))
    )
    search_btn = wait.until(EC.element_to_be_clickable(
      (By.CSS_SELECTOR, '#J_TSearchForm > div.search-button > button')))
    input_box.send_keys(KEYWORD)
    search_btn.click()
    total_page_str = wait.until(
      EC.presence_of_element_located(
        (By.CSS_SELECTOR, 'div.total'))).text
    total_page_num = int(re.search("(\d+)", total_page_str).group(1))
    item_list = get_goods_by_beautifulsoup()
    save_to_mongodb(item_list)
    return total_page_num
  except TimeoutError:
    print("搜索%s超时", KEYWORD)
    print("重新尝试搜索: %s", KEYWORD)
    search()
# 根据页码获取指定页数据,并将其保存到数据库中
def get_page(page_num):
  print("正在获取第%d页数据" % page_num)
  try:
    page_num_box = wait.until(
      EC.presence_of_element_located(
        (By.CSS_SELECTOR, "div.form > input")))
    ok_btn = wait.until(EC.element_to_be_clickable(
      (By.CSS_SELECTOR, 'div.form > span.btn.J_Submit')))
    page_num_box.clear()
    page_num_box.send_keys(page_num)
    ok_btn.click()
    wait.until(
      EC.text_to_be_present_in_element(
        (By.CSS_SELECTOR,
         'li.item.active > span.num'),
        str(page_num)))
    item_list = get_goods_by_beautifulsoup()
    save_to_mongodb(item_list)
  except TimeoutException:
    print("请求第%d页失败" % page_num)
    print("尝试重新获取第%d页" % page_num)
    return get_page(page_num)
def get_goods_by_pyquery():
  '''
  通过pyquery库解析数据
  获取商品的图片url、价格、标题、成交量、店铺名称、店铺位置
  '''
  wait.until(EC.presence_of_element_located(
    (By.CSS_SELECTOR, "#mainsrp-itemlist .items .item")))
  html = driver.page_source
  doc = pq(html)
  items = list(doc('#mainsrp-itemlist .items .item').items())
  for item in items:
    yield {
      # 不要用src属性,获取的图片地址很多是.gif图片,而非真实商品图片,
      'image': 'http://' + item.find('.J_ItemPic.img').attr('data-src'),
      'price': item.find('.price').text(),
      'title': item.find('.row > .J_ClickStat').text().strip(),
      'deal_cnt': item.find('.deal-cnt').text()[:-3],
      'shop': item.find('.shop').text(),
      'location': item.find('.location').text(),
    }
# 通过bs4解析数据
def get_goods_by_beautifulsoup():
  '''
  通过bs4库解析数据
  获取商品的图片url、价格、标题、成交量、店铺名称、店铺位置
  '''
  wait.until(EC.presence_of_element_located(
    (By.CSS_SELECTOR, "#mainsrp-itemlist .items .item")))
  html = driver.page_source
  soup = BeautifulSoup(html, 'lxml')
  items = soup.select('#mainsrp-itemlist .items .item')
  for item in items:
    yield {
      'image': 'http:' + item.select('img.J_ItemPic.img')[0]['data-src'],
      'price': item.select('div.price.g_price.g_price-highlight')[0].get_text(strip=True),
      'title': item.select('div.row.row-2.title > a.J_ClickStat')[0].get_text(strip=True),
      'deal_cnt': item.select('div.deal-cnt')[0].text[:-3],
      'shop': item.select('div.shop > a')[0].get_text(strip=True),
      'location': item.select('div.location')[0].text,
    }
def save_to_mongodb(item_list):
  for item in item_list:
    try:
      db[MONGO_TABLE].insert(item)  # insert支持插入多条数据
      print("mongodb插入数据成功:", item)
    except PyMongoError as e:
      print("mongodb插入数据失败:", item, e)
# 获取淘宝美食的图片url、价格、标题、成交量、店铺名称、店铺位置并将结果保存在mongodb数据库中
if __name__ == '__main__':
  try:
    total_pages = search()
    for page_num in range(2, total_pages + 1):
      get_page(page_num)
  except Exception as e:
    print("出错了", e)
  finally: # 确保 浏览器能正常关闭
    driver.close()

备注:

PhantomJS无界面浏览器打开的窗口默认大小400*300, 往往不能将网页加载完全,会给提取数据造成很大的困难,因此需要指定窗口大小。

可以使用 maximize_window() 最大化窗口或者set_window_size()设置指定大小

可能会出现的异常:

raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
Screenshot: available via screen

更多关于Python相关内容可查看本站专题:《Python Socket编程技巧总结》、《Python正则表达式用法总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python标准库内置函数complex介绍
Nov 25 Python
Django的数据模型访问多对多键值的方法
Jul 21 Python
在Django的session中使用User对象的方法
Jul 23 Python
python开发之thread线程基础实例入门
Nov 11 Python
Python的collections模块中namedtuple结构使用示例
Jul 07 Python
Python使用Tkinter实现机器人走迷宫
Jan 22 Python
python实现字符串中字符分类及个数统计
Sep 28 Python
给大家整理了19个pythonic的编程习惯(小结)
Sep 25 Python
DJango的创建和使用详解(默认数据库sqlite3)
Nov 18 Python
python装饰器相当于函数的调用方式
Dec 27 Python
Django+Celery实现动态配置定时任务的方法示例
May 26 Python
DataFrame 数据合并实现(merge,join,concat)
Jun 14 Python
python 将print输出的内容保存到txt文件中
Jul 17 #Python
python 实现对数据集的归一化的方法(0-1之间)
Jul 17 #Python
Python计算开方、立方、圆周率,精确到小数点后任意位的方法
Jul 17 #Python
python把数组中的数字每行打印3个并保存在文档中的方法
Jul 17 #Python
python3.x 将byte转成字符串的方法
Jul 17 #Python
Python 字符串转换为整形和浮点类型的方法
Jul 17 #Python
Python操作word常见方法示例【win32com与docx模块】
Jul 17 #Python
You might like
PHP实现多服务器session共享之NFS共享的方法
2007/03/16 PHP
PHP常用数组函数介绍
2014/07/28 PHP
php简单操作mysql数据库的类
2015/04/16 PHP
解读PHP中的垃圾回收机制
2015/08/10 PHP
THINKPHP截取中文字符串函数实例代码
2017/03/20 PHP
PHP实现上传多图即时显示与即时删除的方法
2017/05/09 PHP
Laravel5.0+框架邮件发送功能实现方法图文与实例详解
2019/04/23 PHP
javascript 关闭IE6、IE7
2009/06/01 Javascript
对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!
2011/10/29 Javascript
淘宝网提供的国内NPM镜像简介和使用方法
2014/04/17 Javascript
jQuery实现的网页竖向菜单效果代码
2015/08/26 Javascript
js实现的彩色方块飞舞奇幻效果
2016/01/27 Javascript
利用浮层使select不可选的实现方法
2016/12/03 Javascript
Node.js复制文件的方法示例
2016/12/29 Javascript
React Native使用Modal自定义分享界面的示例代码
2017/10/31 Javascript
微信小程序使用video组件播放视频功能示例【附源码下载】
2017/12/08 Javascript
浅谈关于JS下大批量异步任务按顺序执行解决方案一点思考
2019/01/08 Javascript
vue.js 2.*项目环境搭建、运行、打包发布的详细步骤
2019/05/01 Javascript
ant design vue中表格指定格式渲染方式
2020/10/28 Javascript
零基础写python爬虫之爬虫编写全记录
2014/11/06 Python
python 设置xlabel,ylabel 坐标轴字体大小,字体类型
2019/07/23 Python
使用虚拟环境打包python为exe 文件的方法
2019/08/29 Python
Python Numpy 自然数填充数组的实现
2019/11/28 Python
python错误调试及单元文档测试过程解析
2019/12/19 Python
Python线程条件变量Condition原理解析
2020/01/20 Python
使用python创建Excel工作簿及工作表过程图解
2020/05/27 Python
CSS3轻松实现清新 Loading 效果的简单实例
2016/06/06 HTML / CSS
新秀丽官方旗舰店:Samsonite拉杆箱、双肩包、皮具
2018/03/05 全球购物
美国领先的在线邮轮旅游公司:CruiseDirect
2018/06/07 全球购物
英国赛车、汽车改装和摩托车零件购物网站:Demon Tweeks
2018/10/29 全球购物
美国购买肉、鸭、家禽、鹅肝和熟食网站:D’Artagnan
2018/11/13 全球购物
求职信范文英文版
2014/01/05 职场文书
纪委书记群众路线整改措施思想汇报
2014/10/09 职场文书
小学生节水倡议书
2015/04/29 职场文书
Golang中interface{}转为数组的操作
2021/04/30 Golang
nginx配置虚拟主机的详细步骤
2021/07/21 Servers