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系列之浅谈pickle模块封装和拆封数据对象的方法
May 23 Python
跟老齐学Python之编写类之三子类
Oct 11 Python
粗略分析Python中的内存泄漏
Apr 23 Python
编写Python脚本来获取Google搜索结果的示例
May 04 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
Nov 09 Python
pyqt5实现俄罗斯方块游戏
Jan 11 Python
Python检测数据类型的方法总结
May 20 Python
python数据预处理之数据标准化的几种处理方式
Jul 17 Python
处理Selenium3+python3定位鼠标悬停才显示的元素
Jul 31 Python
python保留格式汇总各部门excel内容的实现思路
Jun 01 Python
Java Unsafe类实现原理及测试代码
Sep 15 Python
Elasticsearch 聚合查询和排序
Apr 19 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实现下载断点续传的方法
2014/11/12 PHP
PHP中常用的三种设计模式详解【单例模式、工厂模式、观察者模式】
2019/06/14 PHP
ext监听事件方法[初级篇]
2008/04/27 Javascript
基于JQuery的cookie插件
2010/04/07 Javascript
js 静态动态成员 and 信息的封装和隐藏
2011/05/29 Javascript
jquery实现在光标位置插入内容的方法
2015/02/05 Javascript
jQuery实现手机号码输入提示功能实例
2015/04/30 Javascript
解决angular的post请求后SpringMVC后台接收不到参数值问题的方法
2015/12/10 Javascript
Underscore源码分析
2015/12/30 Javascript
JS实现商品筛选功能
2020/08/19 Javascript
bootstrap中的导航条实例代码详解
2019/05/20 Javascript
vue如何实现自定义底部菜单栏
2019/07/01 Javascript
vue之封装多个组件调用同一接口的案例
2020/08/11 Javascript
python创建和使用字典实例详解
2013/11/01 Python
python批量修改文件后缀示例代码分享
2013/12/24 Python
深入理解Python中命名空间的查找规则LEGB
2015/08/06 Python
python中pandas.DataFrame排除特定行方法示例
2017/03/12 Python
Python利用Beautiful Soup模块搜索内容详解
2017/03/29 Python
人工智能最火编程语言 Python大战Java!
2017/11/13 Python
书单|人生苦短,你还不用python!
2017/12/29 Python
flask框架中勾子函数的使用详解
2018/08/01 Python
在PyCharm中批量查找及替换的方法
2019/01/20 Python
django 自定义过滤器(filter)处理较为复杂的变量方法
2019/08/12 Python
TENSORFLOW变量作用域(VARIABLE SCOPE)
2020/01/10 Python
HTML5 textarea高度自适应的两种方案
2020/04/08 HTML / CSS
悬挂训练绳:TRX
2017/12/14 全球购物
西班牙Polo衫品牌:Polo Club
2020/08/09 全球购物
如何防止同一个帐户被多人同时登录
2013/08/01 面试题
班级学习计划书
2014/04/27 职场文书
考试作弊检讨书范文
2015/01/27 职场文书
2019求职信:应届生求职信范文
2019/04/24 职场文书
个人的事迹材料怎么写
2019/04/24 职场文书
2019年中学生的思想品德评语集锦
2019/12/19 职场文书
Pygame如何使用精灵和碰撞检测
2021/11/17 Python
什么是动态刷新率DRR? Windows11动态刷新率功能介绍
2021/11/21 数码科技
SpringBoot整合minio快速入门教程(代码示例)
2022/04/03 Java/Android