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交换变量
Sep 06 Python
python将图片文件转换成base64编码的方法
Mar 14 Python
Python编程之序列操作实例详解
Jul 22 Python
Python决策树分类算法学习
Dec 22 Python
python使用pil库实现图片合成实例代码
Jan 20 Python
python模块smtplib学习
May 22 Python
python利用Tesseract识别验证码的方法示例
Jan 21 Python
ZABBIX3.2使用python脚本实现监控报表的方法
Jul 02 Python
Python生命游戏实现原理及过程解析(附源代码)
Aug 01 Python
django foreignkey外键使用的例子 相当于left join
Aug 06 Python
Python pandas 列转行操作详解(类似hive中explode方法)
May 18 Python
解决Tensorflow2.0 tf.keras.Model.load_weights() 报错处理问题
Jun 12 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.ini不生效问题解决方法(上传大于8M的文件)
2013/06/14 PHP
php 删除cookie方法详解
2014/12/01 PHP
PHP获取文件行数的方法
2015/06/10 PHP
Yii的Srbac插件用法详解
2016/07/14 PHP
php+ajax无刷新上传图片的实现方法
2016/12/06 PHP
JavaScript中void(0)的具体含义解释
2007/02/27 Javascript
JavaScript 组件之旅(三):用 Ant 构建组件
2009/10/28 Javascript
Jquery显示和隐藏元素或设为只读(含Ligerui的控件禁用,实例说明介绍)
2013/07/09 Javascript
在页面加载完成后通过jquery给多个span赋值
2014/05/21 Javascript
jQuery实现鼠标划过展示大图的方法
2015/03/09 Javascript
原生JS简单实现ajax的方法示例
2016/11/29 Javascript
利用jquery如何从json中读取数据追加到html中
2017/12/01 jQuery
JavaScript类数组对象转换为数组对象的方法实例分析
2018/07/24 Javascript
详解mpvue中小程序自定义导航组件开发指南
2019/02/11 Javascript
layer.alert自定义关闭回调事件的方法
2019/09/27 Javascript
vue中组件通信详解(父子组件, 爷孙组件, 兄弟组件)
2020/07/27 Javascript
[01:10:58]KG vs TNC 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
简洁的十分钟Python入门教程
2015/04/03 Python
Python StringIO模块实现在内存缓冲区中读写数据
2015/04/08 Python
Swift 3.0在集合类数据结构上的一些新变化总结
2016/07/11 Python
使用Python实现从各个子文件夹中复制指定文件的方法
2018/10/25 Python
Python BeautifulSoup [解决方法] TypeError: list indices must be integers or slices, not str
2019/08/07 Python
pytorch点乘与叉乘示例讲解
2019/12/27 Python
Python原始套接字编程实例解析
2020/01/29 Python
python 错误处理 assert详解
2020/04/20 Python
python中HTMLParser模块知识点总结
2021/01/25 Python
德国高尔夫商店:Golfshop.de
2019/06/22 全球购物
C#里面可以避免一个类被其他类继承么?如何?
2013/09/26 面试题
生物化工专业个人自荐信
2013/09/26 职场文书
校园联欢晚会主持词
2014/03/17 职场文书
品质标语大全
2014/06/21 职场文书
社区安全生产月活动总结
2014/07/05 职场文书
企业法人代表授权委托书
2014/10/02 职场文书
新闻发布会新闻稿
2015/07/17 职场文书
2015年秋季运动会前导词
2015/07/20 职场文书
Java基础之this关键字的使用
2021/06/30 Java/Android