Skip to content

xqqq0/TbCate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

思路

  • 模拟在淘宝的搜索框填写关键词,然后搜索
  • 模拟数据加载完毕后,点击下一页操作
  • 数据加载结束以后利用PyQuary进行数据解析提取
  • 存储到mongoDB
  • 代码细节优化

工具安装

  • 安装 selenium brew install selenium-server-standalone
  • 安装PyQuery sudo easy_install pyquery
  • 安装phantomjs brew install phantomjs

利用 selenium模拟淘宝操作

使用selenium的大致思路根据CSS选择器或者id之类的定位到具体的控件,然后给控件实现赋值或者点击等操作。

selenium的简单配置

  • 导入框架
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
  • 加载浏览器驱动,本例中使用谷歌浏览器,使用前请确认已经安装 chromedriver,关于配置可以自行Google或者访问我的博客 支持的浏览器

选择元素css

# 加载驱动
browser = webdriver.Chrome()

此时代码运行可以呼起一个空置的谷歌浏览器

  • 设置等待超时时间:在规定时间内未能加载相应控件将报错
wait = WebDriverWait(browser, 10)
  • 通用写法
wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "#q"))
        )
  • 代码分析

    • EC 为from selenium.webdriver.support import expected_conditions as EC
    • EC后边的是选择条件,即什么时候可以选择控件,例中条件为控件完全展示,其他选择条件请看下面 EC选择条件
    • By 为from selenium.webdriver.common.by import By
    • By后边的是根据什么元素选择控件,可以使id 或者css等等,后边的参数为具体的元素值
  • EC选择条件

title_is
title_contains
presence_of_element_located
visibility_of_element_located
visibility_of
presence_of_all_elements_located
text_to_be_present_in_element
text_to_be_present_in_element_value
frame_to_be_available_and_switch_to_it
invisibility_of_element_located
element_to_be_clickable
staleness_of
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
alert_is_present
  • By参数类型
    ID = "id"
    XPATH = "xpath"
    LINK_TEXT = "link text"
    PARTIAL_LINK_TEXT = "partial link text"
    NAME = "name"
    TAG_NAME = "tag name"
    CLASS_NAME = "class name"
    CSS_SELECTOR = "css selector"

模拟关键字填写及搜索

  • 输入框的EC条件为presence_of_element_located,然后利用其css选择器,并复制其id
  • 确定按钮EC条件为element_to_be_clickable同样选择其css值
  • 输入框内通过send_keys传入搜索词
  • 确定按钮调用click()方法
  • 其他的方法参见文档
  • 坑:send_keys输入关键字的时候,在Python2.7的环境中,如果直接用字符串会报错 UnicodeDecodeError: 'utf8' codec can't decode byte 0xe7in position 0: unexpected end of data 可以通过解码进行修复 "美食".decode(encoding="utf-8")
browser.get("https://s.taobao.com")
    # selenium处理页面等待的方法
    # 设置一下需要监听的元素,可以通过id或者能唯一确定元素的属性
    # EC是选择条件点后边的是条件,我把条件记录在简书里
    # 我们通过页面元素,查找到输入框,我们利用css样式去确定,并利用css选择器去获取
        input = wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "#q"))
        )

        # 然后监听按钮,条件是以可以点击判断其加载完成
        submit = wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "#J_SearchForm > div > div.search-button > button"))
        )

        # 调用selenium的API来给搜索框输入内容,然后按钮追加点击方法
        # send_keys添加参数
        input.send_keys(KEYWORD)
        # 添加点击方法
        submit.click()

获取宝贝页面的宝贝总页数

  • 监听翻页控件加载完,以显示共xx页显示完全为依据
  • EC的条件也就是presence_of_element_located,同样利用其css选 择器
  • 将返回页数作为返回值返回
 total = wait.until(
       EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.total"))
  )
return total.text

实现翻页

翻页功能有种实现方式

  • 点击下一页,实现翻页,但是如果发生错误不易差别是具体页数

  • 输入页码,点击确定,可以清楚的知道具体跳转了那一页,翻页后确定当前面是否加载完,主要看页码当时是否为高亮状态

  • 定义一个以页码作为参数的函数

  • 获取页码户输入框架,获取确定按钮,输入框填入参数,然后点击确定实现翻页,与搜索功能相同

  • 确定当前页码的高亮状态来

def get_next_page(page_number):
    print(u"正在翻页")
    try:
    # 拿到输入框 和确定 按钮,然后输入页码
        input = wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > div.form > input"))
        )

        submit = wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit"))
        )
        input.clear()
        input.send_keys(page_number)
        submit.click()

        # 翻页后确定当前面是否加载完,主要看页码当时是否为高亮状态
        text = wait.until(
            EC.text_to_be_present_in_element((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > ul > li.item.active > span"), str(page_number))
        )
        get_product()
    except TimeoutException:
        print("get_next_page超时")
        get_next_page(page_number)

PyQuery实现页面解析

对于PyQuery(以下简称pq)的用法目前完全懵逼,完全是跟着视频敲的,只知道类似于jQuery,根据id或者css样式去获取查找元素,页面结果见下图,通过idmainsrp-itemlist的,然后css样式为items获取商品列表,最后通过css样式为items,然后每个商品的信息 网页结构图

  • 没啥说的直接上代码
'''
3.解析页面,获取美食信息
'''
def get_product():
    print("正在获取产品")
    # 页面记载结束:主要是看商品信息的大节点是不是加载完了
    wait.until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-itemlist .items .item"))
    )
    # 获取页面内容
    html = browser.page_source
    # 通过PyQuery解析页面
    doc = pq(html)
    # 根据节点获取美食的集合
    items = doc("#mainsrp-itemlist .items .item").items()
    # 遍历 获取各值
    for item in items:
        product = {
            # 获取img标签下的src属性
            "image": item.find(".pic .img").attr("src"),
            "price": item.find(".price").text(),
            "deal": item.find(".deal-cnt").text()[:-3],
            "title": item.find(".title").text(),
            "shop": item.find(".shop").text(),
            "location": item.find(".location").text()
        }
  • 在第一次加载页面方法时,也就是第一页的时候调用此方法,获取第一页的数据
  • 在翻页的时候也要调用此方法

存储到mongoDB

与第一篇爬取头条数据一样,需要单独创建配置文件,然后创建俩呢及,创建数据库,存储数据,有一点着重提示的是,在代码运行存储数据的时候,一定要记得开启mongoDB的服务,不然会报一些莫名其妙的错误

  • 配置文件代码
MONGO_URL = "localhost"
MONGO_DB = "Taobao"
MONGO_TAB = "TbCate"
  • 创建数据库连接
# 创建数据库链接
client = MongoClient(MONGO_URL)
# 创建数据库
db = client[MONGO_DB]
  • 存储数据
'''
4.存储数据
'''
def save_to_mongo(result):
    try:
        if db[MONGO_TAB].insert(result):
            print("正在存储到mongDB")
    except Exception:
        print("存储失败",result)

代码整体串接

def main():
    try:
        # 获取总页数
        totoal = search()
        # 获取数字,过滤汉字
        pattern = re.compile(r"(\d+)")
        match = re.search(pattern, totoal)
        # 遍历获取所有的页面
        for i in range(2,int(match.group(1)) + 1):
            get_next_page(i)
        # 数据获取结束以后关闭浏览器
    except Exception:
        print("出错了")
   # 用完后,必须关闭浏览器
    finally:
        browser.close()

引入phantomJS

我感觉如果遇到一个具体类似淘宝宝贝数据爬取的需求的话,可能的大致思路是先通过浏览器去模拟数据,成功以后,引入phantomJS去静默爬取数据

  • 配置phantomJS
# 将Google浏览器换成PhantomJS
browser = webdriver.PhantomJS()
# 修改弹框大小
browser.set_window_size(1400,800)
  • PhantomJS的一些高级配置,详见官网
    • 在配置文件中简单进行配置
# phantomJS的高级用配置:不加载图片,加缓存
SEARVICE_ARGS = ["--load-images=false","--disk-cache=true"]
  • 代码中引入
browser = webdriver.PhantomJS(service_args=SEARVICE_ARGS)

一些注意点

  • selenium 等待控件加载的时候,容易发生超时问题,所以要加异常处理,一般超时后都是在调用一遍方法
  • 引入 PhantomJS以后,browser.close()会报错,所以也要加异常处理,在finally后边关闭
  • 存储到mongoDB的时候一定要先开启mong服务
  • 本博客对PyQueryPhantomJS没有进行详细的讲解,因为本人基础薄弱,但是给了一些博客链接,待到本人学习以后会将博客进行完善,另外本博客在GitHub的源码README中同步更新了
  • 代码地址

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages