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 11 Python
python分割列表(list)的方法示例
May 07 Python
python机器学习之贝叶斯分类
Mar 26 Python
Django csrf 验证问题的实现
Oct 09 Python
python3 爬取图片的实例代码
Nov 06 Python
windows下搭建python scrapy爬虫框架步骤
Dec 23 Python
使用python itchat包爬取微信好友头像形成矩形头像集的方法
Feb 21 Python
python中使用ctypes调用so传参设置遇到的问题及解决方法
Jun 19 Python
python中列表的切片与修改知识点总结
Jul 23 Python
python脚本之一键移动自定格式文件方法实例
Sep 02 Python
python实例化对象的具体方法
Jun 17 Python
python中字符串的编码与解码详析
Dec 03 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中url函数介绍及使用示例
2014/02/13 PHP
在WordPress中使用wp-cron插件来设置定时任务
2015/12/10 PHP
PHP入门教程之正则表达式基本用法实例详解(正则匹配,搜索,分割等)
2016/09/11 PHP
thinkphp的dump函数无输出实例代码
2016/11/15 PHP
thinkphp下MySQL数据库读写分离代码剖析
2017/04/18 PHP
js图片向右一张张滚动效果实例代码
2013/11/23 Javascript
jquery dataview数据视图插件使用方法
2016/12/23 Javascript
javascript 中设置window.location.href跳转无效问题解决办法
2017/02/09 Javascript
基于Angularjs-router动态改变Title值的问题
2018/08/30 Javascript
Nodejs实现多文件夹文件同步
2018/10/17 NodeJs
js中Function引用类型常见有用的方法和属性详解
2019/12/11 Javascript
bootstrap实现嵌套模态框的实例代码
2020/01/10 Javascript
es6中class类静态方法,静态属性,实例属性,实例方法的理解与应用分析
2020/02/15 Javascript
Vue 中 template 有且只能一个 root的原因解析(源码分析)
2020/04/11 Javascript
编写一个javascript元循环求值器的方法
2020/04/14 Javascript
[36:41]完美世界DOTA2联赛循环赛FTD vs Magma第一场 10月30日
2020/10/31 DOTA
python列表与元组详解实例
2013/11/01 Python
Python实现批量把SVG格式转成png、pdf格式的代码分享
2014/08/21 Python
Python实现简单的语音识别系统
2017/12/13 Python
在Mac下使用python实现简单的目录树展示方法
2018/11/01 Python
基于树莓派的语音对话机器人
2019/06/17 Python
Flask框架学习笔记之路由和反向路由详解【图文与实例】
2019/08/12 Python
python pyecharts 实现一个文件绘制多张图
2020/05/13 Python
python求numpy中array按列非零元素的平均值案例
2020/06/08 Python
详解CSS3+JS完美实现放大镜模式
2020/12/03 HTML / CSS
奥兰多迪士尼门票折扣:Undercover Tourist
2018/07/09 全球购物
adidas瑞典官方网站:购买阿迪达斯鞋子和运动服
2019/12/11 全球购物
一封普通求职者的求职信
2013/11/20 职场文书
如何写一份好的自荐信
2014/01/02 职场文书
机关财务管理制度
2014/01/17 职场文书
自荐信的基本格式
2014/02/22 职场文书
社区矫正工作方案
2014/06/04 职场文书
校庆口号
2014/06/20 职场文书
死者家属慰问信
2015/03/24 职场文书
基石观后感
2015/06/12 职场文书
幼儿体育课教学反思
2016/02/16 职场文书