Spider_jdSeacrh

作者: GHope | 来源:发表于2018-11-05 16:47 被阅读36次

    本次爬取的内容为京东的搜索功能。通过selenium利用驱动启动浏览器,并输入搜索内容,并模拟切换页面、滚动页面等操作抓取搜索结果。保存搜索商品结果的标识、描述、价格、商家、图片地址及商品链接到本地数据库中。

    爬取过程

    首先设置浏览器(无头浏览器可不设——设置目的为了提高效率及尽可能少的占用内存) -- 使用驱动启动浏览器 -- 设置启动的浏览器的界面大小及等待页面内容加载的时间 -- 通过多次观察发现京东的搜索结果均为100页 -- 主函数中通过循环生成每次填入的页码 -- 将页码传递给模拟切换页面的函数 -- 模拟切换页面的函数判断页码是否为一,若为一则向页面写入经过编码的搜索内容到请求地址中,若不为一则先得到页码输入框和确认按钮,之后清空页码输入框(避免输入页码追加到原有页码之后)输入得到的页码,点击确认按钮 -- 使用循环分六次滚动刷新页面(避免页面内容缺省太多) -- 返回当前页面内容 -- 解析页面内容(首先将所有拿到的li标签强制转换为一个list,通过循环该列表拿到单个商品的li标签。再使用.匹配li标签中的内容,存为dict形式后添加到商品list中,便于之后插入到数据库中。) -- 连接数据库保存数据 -- 抛商标标识唯一引起的异常

    import time
    import random
    import pymysql
    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 urllib.parse import quote
    from lxml import etree
    
    # 无头浏览器
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    # 启动浏览器
    browser = webdriver.Chrome(chrome_options=chrome_options)
    
    # 指定自启浏览器界面大小
    browser.set_window_size(1400, 700)
    # 显式等待  针对整个节点的等待
    wait = WebDriverWait(browser, 3)
    # 设置关键字
    KEYWORD = '古风'
    
    
    # 隐式等待(不推荐使用)
    # browser.implicitly_wait(3)
    
    # 模拟切换页面
    def get_page(page):
        if page == 1:
            # 第一次访问的地址
            url = 'https://search.jd.com/Search?keyword=%s&enc=utf-8' % quote(KEYWORD)
            # 访问地址
            browser.get(url)
        if page > 1:
            # 获取页数输入框
            input = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#J_bottomPage input.input-txt')))
            # 获取确认按钮
            submit = wait.until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_bottomPage a.btn.btn-default')))
            # 清空页数输入框
            input.clear()
            # 将目标页数填入到页数输入框
            input.send_keys(page)
            # 点击确认按钮
            submit.click()
            wait.until(
                EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#J_bottomPage a.curr'), str(page)))
            wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#J_goodsList')))
        # 随机等待时间
        t = random.randint(0, 9)
        # 分六次滚动页面
        for i in range(6):
            str_js = 'var step = document.body.scrollHeight/6;window.scrollTo(0,step*%d)' % (i + 1)
            browser.execute_script(str_js)
            time.sleep(t)
        # 得到访问的页面内容
        page_source = browser.page_source
        return page_source
    
    
    # 解析获取到的页面
    def parse_page(page_source):
        # 创建xpath解析对象
        etree_html = etree.HTML(page_source)
        # print(page_source)
        # print(type(etree_html))
        # 得到单个商品(解决一个商品单个属性中多个信息的选择)
        goods_list = list(etree_html.xpath('//div[@id="J_goodsList"]/ul/li'))
        # print(len(goods_list))
        goods_db = []
        for goods in goods_list:
            item = {}
            # 解析标识
            goods_sku = goods.xpath('./@data-sku')
            # print(goods_sku[0])
            item['sku'] = goods_sku[0]
            # 解析描述(.表示当前目录)
            goods_title = goods.xpath('.//div[@class="p-name p-name-type-2"]/a/em/text()')
            # print(goods)
            # print(goods_title)
            title = ''
            for i in goods_title:
                title += i
            # print(title)
            # print(len(goods_title))
            item['title'] = title.replace(' ', '')
            # 解析价格
            goods_price = goods.xpath('.//div[@class="p-price"]/strong/i/text()')
            # print(goods_price[0])
            item['price'] = goods_price[0]
            # 解析商家
            goods_shop = goods.xpath('.//div[@class="p-shop"]/span/a/@title')
            # print(goods_shop[0])
            item['shop'] = goods_shop[0]
            # 解析评价数量
            goods_commit = goods.xpath('.//div[@class="p-commit"]/strong/a/text()')
            # print(goods_commit[0])
            item['commit'] = goods_commit[0]
            # 解析图片地址(部分图片加载不到,设置重复更新后多次爬取)
            goods_img = goods.xpath('.//div[@class="p-img"]/a/img/@src')
            # print(goods_img)
            item['img'] = goods_img
            if goods_img:
                item['img'] = goods_img[0]
            else:
                item['img'] = ''
            # 解析商品链接
            goods_link = goods.xpath('.//div[@class="p-img"]/a/@href')
            # print(goods_link)
            item['link'] = goods_link[0]
            # 将解析好的单品信息加入返回结果中
            goods_db.append(item)
        return goods_db
    
    
    def join_MySql(goods_db):
        # 设置数据库参数
        host = '127.0.0.1'
        user = 'root'
        password = 'root'
        port = 3306
        db = 'jdSeacrh'
        db = pymysql.connect(host=host, user=user, password=password, port=port, db=db)
        # 连接数据库
        cursor = db.cursor()
        for i in range(len(goods_db)):
            sql = "INSERT INTO seacrh_gufeng(sku,title,price,shop,commit,img,link)" \
                  " VALUES('{}','{}','{}','{}','{}','{}','{}')".format(goods_db[i]['sku'], goods_db[i]['title'],
                                                                       goods_db[i]['price'], goods_db[i]['shop'],
                                                                       goods_db[i]['commit'],
                                                                       goods_db[i]['img'], goods_db[i]['link'])
            # print(sql)
            try:
                cursor.execute(sql)
                db.commit()
            except:
                print('元素已存在')
        db.close()
    
    
    def main():
        for page in range(100):
            # 动态增加页数
            page_source = get_page(page + 1)
            # 解析页面内容
            goods_db = parse_page(page_source)
            join_MySql(goods_db)
    
    
    if __name__ == '__main__':
        main()
    

    总结:

    京东这一块最麻烦的是解析页面,存的时候总是数据格式出错。也许是因为存储的是MySQL的原因吧!商品描述是em标签下被span分开的一个或多个字符串,导致解析难度提升!还有图片地址的问题到现在还没想到什么方法完美解决,每次加载的时候只有少量的图片地址能够被加载出来。知道应该多次访问,存图片的时候判断该信息是否存在,但又好像和唯一索引冲突。。。很迷...

    GitHub地址

    相关文章

      网友评论

      本文标题:Spider_jdSeacrh

      本文链接:https://www.haomeiwen.com/subject/gcgctqtx.html