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 相关文章推荐
开始着手第一个Django项目
Jul 15 Python
python实现汉诺塔递归算法经典案例
Mar 01 Python
python3 图片referer防盗链的实现方法
Mar 12 Python
Python实现批量修改图片格式和大小的方法【opencv库与PIL库】
Dec 03 Python
Python字符串逆序的实现方法【一题多解】
Feb 18 Python
python 使用opencv 把视频分割成图片示例
Dec 12 Python
pyenv虚拟环境管理python多版本和软件库的方法
Dec 26 Python
Python smtp邮件发送模块用法教程
Jun 15 Python
django使用graphql的实例
Sep 02 Python
Python datetime模块的使用示例
Feb 02 Python
聊一聊python常用的编程模块
May 14 Python
Django框架中表单的用法
Jun 10 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利用正则表达式解决采集内容排版的问题
2013/06/20 PHP
ThinkPHP采用原生query实现关联查询left join实例
2014/12/02 PHP
php使用preg_match()函数验证ip地址的方法
2017/01/07 PHP
php实现算术验证码功能
2018/12/05 PHP
Laravel框架查询构造器 CURD操作示例
2019/09/04 PHP
laravel框架的安装与路由实例分析
2019/10/11 PHP
jQuery对象和DOM对象相互转化
2009/04/24 Javascript
jQuery 工具函数学习资料
2010/04/29 Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
2016/07/15 Javascript
浅谈箭头函数写法在ReactJs中的使用
2017/08/22 Javascript
nodejs 如何手动实现服务器
2018/08/20 NodeJs
JS立即执行函数功能与用法分析
2019/01/15 Javascript
浅谈React Native 传参的几种方式(小结)
2019/05/21 Javascript
详解使用mocha对webpack打包的项目进行"冒烟测试"的大致流程
2020/04/27 Javascript
jQuery实现回到顶部效果
2020/10/19 jQuery
[01:14:34]DOTA2上海特级锦标赛C组资格赛#2 LGD VS Newbee第一局
2016/02/28 DOTA
python 获取文件列表(或是目录例表)
2009/03/25 Python
Python正则表达式介绍
2012/08/06 Python
python del()函数用法
2013/03/24 Python
python的三目运算符和not in运算符使用示例
2014/03/03 Python
详谈Python2.6和Python3.0中对除法操作的异同
2017/04/28 Python
浅谈python标准库--functools.partial
2019/03/13 Python
Pandas之Dropna滤除缺失数据的实现方法
2019/06/25 Python
python实现图片压缩代码实例
2019/08/12 Python
css3中背景尺寸background-size详解
2014/09/02 HTML / CSS
小区门卫管理制度
2014/01/29 职场文书
2014中考励志标语
2014/06/05 职场文书
2015年世界环境日演讲稿
2015/03/18 职场文书
vue+element ui实现锚点定位
2021/06/29 Vue.js
JS数组方法some、every和find的使用详情
2021/10/05 Javascript
一起来看看Vue的核心原理剖析
2022/03/24 Vue.js
电脑开机弹出documents文件夹怎么回事?弹出documents文件夹解决方法
2022/04/08 数码科技
MySQL 外连接语法之 OUTER JOIN
2022/04/09 MySQL
PHP面试题 wakeup魔法 Ezpop pop序列化与反序列化
2022/04/11 PHP
Windows Server 2016 配置 IIS 的详细步骤
2022/04/28 Servers
使用Cargo工具高效创建Rust项目
2022/08/14 Javascript