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生成二维码的实例详解
Oct 29 Python
使用python和pygame绘制繁花曲线的方法
Feb 24 Python
python去除文件中重复的行实例
Jun 29 Python
Python OpenCV处理图像之图像像素点操作
Jul 10 Python
对python制作自己的数据集实例讲解
Dec 12 Python
python中for循环把字符串或者字典添加到列表的方法
Jul 20 Python
Python 处理文件的几种方式
Aug 23 Python
如何通过python实现人脸识别验证
Jan 17 Python
python读取文件指定行内容实例讲解
Mar 02 Python
Django中文件上传和文件访问微项目的方法
Apr 27 Python
Pandas把dataframe或series转换成list的方法
Jun 14 Python
Python工程师必考的6个经典面试题
Jun 28 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 iconv函数的使用详解
2013/06/09 PHP
PHP zip扩展Linux下安装过程分享
2014/05/05 PHP
查找php配置文件php.ini所在路径的二种方法
2014/05/26 PHP
提高php编程效率技巧
2015/08/13 PHP
项目中应用Redis+Php的场景
2016/05/22 PHP
Zend Framework入门教程之Zend_Config组件用法详解
2016/12/09 PHP
语义化 H1 标签
2008/01/14 Javascript
javascript面向对象编程(一) 实例代码
2010/06/25 Javascript
Jquery validation remote 验证的缓存问题解决方法
2014/03/25 Javascript
Nodejs关于gzip/deflate压缩详解
2015/03/04 NodeJs
举例简介AngularJS的内部语言环境
2015/06/17 Javascript
js带缩略图的图片轮播效果代码分享
2015/09/14 Javascript
JS控制层作圆周运动的方法
2016/06/20 Javascript
Angularjs中三种数据的绑定策略(“@”,“=”,“&”)
2016/12/23 Javascript
详解vue数据渲染出现闪烁问题
2017/06/29 Javascript
JavaScript实现省市联动过程中bug的解决方法
2017/12/04 Javascript
ES6基础之默认参数值
2019/02/21 Javascript
C#程序员入门学习微信小程序的笔记
2019/03/05 Javascript
python发腾讯微博代码分享
2014/01/10 Python
深入解析Python中的list列表及其切片和迭代操作
2016/03/13 Python
python实现二叉查找树实例代码
2018/02/08 Python
一百多行python代码实现抢票助手
2018/09/25 Python
pyside+pyqt实现鼠标右键菜单功能
2020/12/08 Python
详解Python静态网页爬取获取高清壁纸
2019/04/23 Python
Django 静态文件配置过程详解
2019/07/23 Python
Django发送邮件和itsdangerous模块的配合使用解析
2019/08/10 Python
django-rest-swagger对API接口注释的方法
2019/08/29 Python
Nanushka官网:匈牙利服装品牌
2019/08/14 全球购物
班主任评语大全
2014/04/26 职场文书
幼儿园爱国卫生月活动总结
2014/06/30 职场文书
房产协议书范本2014
2014/09/30 职场文书
医生学习党的群众路线教育实践活动心得体会
2014/11/03 职场文书
因工资原因离职的辞职信范文
2015/05/12 职场文书
小学运动会前导词
2015/07/20 职场文书
2016教师党员学习心得体会
2016/01/21 职场文书
Vue.js中v-bind指令的用法介绍
2022/03/13 Vue.js