[Python3]selenium爬取淘宝商品信息

前言

前面介绍了使用selenium和chromedriver通过模拟浏览器运行的方式可以做到在浏览器中看到是什么样,抓取的源码就是什么样。不用再去管网页内部的JavaScript是如何渲染页面,也不用管网页后台的Ajax接口有哪些参数,甚至是加密规律等。这篇博客是实战演练,通过Selenium爬取淘宝网商品的图片,名称,价格,购买人数,店铺名称,店铺所在地信息,将结果保存至Mongodb数据库中。

Chromedriver for linux

上一篇博客只介绍了chromedriver在windows下的安装

http://yhch.xyz/2018/07/08/Python3%E7%88%AC%E8%99%AB-selenium-chromedriver%E5%8F%AF%E8%A7%81%E5%8D%B3%E5%8F%AF%E7%88%AC/

对应版本的下载和测试安装是方法是一样的

//解压
unzip chromedriver_linux64.zip
//移动到环境变量所在的目录
sudo mv chromedriver /usr/bin

//或者将chromedriver所在目录,添加到环境变量
export PATH="$PATH:所在目录"
//执行新的配置
source ~/.porfile

分析一波

1.ajax请求分析
pic1

_ksTS,rn这两个参数很难发现其规律,所以这里不采用构造Ajax请求的方式来爬取内容,而通过selemium价格网页最终呈现效果的HTML代码全部爬取下来,再来提取所要信息

2.商品分析

pic2

需要说明的是srcdata-src都是商品图片的网络地址,区别是前者是缩略图而后者是高清大图,两者都可以任意爬取,这里爬取的是后者

3.页码分析

pic3

这里不点击下一页,而是通过自动输入页面数来进行页面跳转,一方面是要实时监控爬取到多少页,另一方面,当程序出现异常,下一次运行又从第一页开始,下一页依次爬取,数据库中,会有重复记录

code

1. 获取商品列表
import pymongo
from selenium import webdriver
from selenium.common.exceptions import  TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from urllib.parse import quote
from pyquery import  PyQuery as pq

driver = webdriver.Chrome()
wait = WebDriverWait(driver,10)


KEYWORD = 'iMac'

def index_page(page):
    print('正在爬取第',page,'页')
    try:
        url = 'https://s.taobao.com/search?q='+quote(KEYWORD)
        driver.get(url)
        if page > 1:
            input = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR,
                                                '#mainsrp-pager    div.form > input')))
            submit = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR,
                                        '#mainsrp-pager div.form > span.btn.J_Submit')))
            input.clear()
            input.send_keys(page)
            submit.click()
        wait.until(
            EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager li.item.active > span'),str(page))
        )
        wait.until(
            EC.presence_of_element_located((
                By.CSS_SELECTOR,'.m-itemlist .items .item')))
        get_products()
    except TimeoutException:
        index_page(page)

通过构造查询参数,得到淘宝网的搜索URLhttps://s.taobao.com/search?q=iMac,q后面接你要搜索的关键词。就能够跳转到搜索指定商品后的页面,也是程序的入口URL
通过改变EYWORD的值,就能爬取不同商品信息;拼接URL的时候用到quote方法,屏蔽特殊字符串,如空格等,URL地址里是不含空格的,同时将字符串转换为URL编码格式,以保证URL的正确性。

下面代码等待加载时,使用了WebDriverWait对象,指定等待条件和10s的最长等待时间,如果在这个时间内页面元素成功加载出来了,就相应结果并继续向下执行,否则抛出超时异常。EC.presence_of_element_located是元素成功加载出来,EC.presence_of_element_located 意思是元素可以点击,因为它是一个按钮,这个按钮的作用是选定页码后的点击确定后跳转。

为了验证跳转到了对应的页码,需要判断当前高亮的页码数是当前的页码数(当前所在页码会高亮显示,也就是说当前页码的css是特殊的),所以这里使用了另一个等待条件text_to_be_present_in_element,它会等待指定的文本出现在某一个节点里面时即返回成功。这里我们将高亮的页码节点对应的CSS选择器和当前要跳转的页码通过参数传递给这个等待条件,这样它就会检测当前高亮的页码节点是不是我们传过来的页码数,如果是,就证明页面成功跳转到了这一页,页面跳转成功。

这样刚才实现的index_page()方法就可以传入对应的页码,待加载出对应页码的商品列表后,再去调用get_products()方法进行页面解析。

这些等待条件的参数都是特定的css选择器,不做赘述了,图片已经标注的很清楚了

2.解析商品列表
def get_products():
    html = driver.page_source
    doc = pq(html)
    items = doc('#mainsrp-itemlist .items .item').items()
    for item in items:
        product = {
            'image' : item.find('.pic .img').attr('data-src'),
            'price' : item.find('.price').text(),
            'deal' : item.find('.deal-cnt').text(),
            'title' : item.find('.title').text(),
            'shop': item.find('.shop').text(),
            'location':item.find('.location').text()
        }
        print(product)
        save_to_mongo(product)
        print('\n')

通过driver.page_source 获得了不同页码下完整html源码;同时使用Pyqurey来解析网页,通过已经查找的标签,查找这个标签下的子标签或者父标签,而不用从头开始查找,效率更高;通过find(css).属性方法,获取图片URL,和其他文本信息并构造成Json字符串,调用save_to_mongo函数存入数据库中。

3.将结果保存到Mogodb中
def save_to_mongo(result):
    client = pymongo.MongoClient('mongodb://admin:admin123@localhost:27017/')
    db = client['taobao']
    collection = db['products']
    try:
        if collection.insert(result):
            print("成功保存到MongoDB")
    except Exception:
        print('someing wrong with MongDB')

python3通过认证方式连接Mongodb数据库,admin是我的用户名,admin123是我的密码,接着指定数据库和集合,调用insert方法插入数据。

4.定义爬取页数
def main():
    MAX_PAGE = 100
    for i in range(1,MAX_PAGE+1):
        index_page(i)
    driver.close()

if __name__ =='__main__':
    main()

简单for循环,并通过range生成1到100的数传递给index_page函数。

5.完整代码
import pymongo
from selenium import webdriver
from selenium.common.exceptions import  TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from urllib.parse import quote
from pyquery import  PyQuery as pq

driver = webdriver.Chrome()
wait = WebDriverWait(driver,10)


KEYWORD = 'iMac'

def index_page(page):
    print('正在爬取第',page,'页')
    try:
        url = 'https://s.taobao.com/search?q='+quote(KEYWORD)
        driver.get(url)
        if page > 1:
            input = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR,
                                                '#mainsrp-pager    div.form > input')))
            submit = wait.until(
                EC.element_to_be_clickable((By.CSS_SELECTOR,
                                        '#mainsrp-pager div.form > span.btn.J_Submit')))
            input.clear()
            input.send_keys(page)
            submit.click()
        wait.until(
            EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager li.item.active > span'),str(page))
        )
        wait.until(
            EC.presence_of_element_located((
                By.CSS_SELECTOR,'.m-itemlist .items .item')))
        get_products()
    except TimeoutException:
        index_page(page)

def get_products():
    html = driver.page_source
    doc = pq(html)
    items = doc('#mainsrp-itemlist .items .item').items()
    for item in items:
        product = {
            'image' : item.find('.pic .img').attr('data-src'),
            'price' : item.find('.price').text(),
            'deal' : item.find('.deal-cnt').text(),
            'title' : item.find('.title').text(),
            'shop': item.find('.shop').text(),
            'location':item.find('.location').text()
        }
        print(product)
        save_to_mongo(product)
        print('\n')


def save_to_mongo(result):
    client = pymongo.MongoClient('mongodb://admin:admin123@localhost:27017/')
    db = client['taobao']
    collection = db['products']
    try:
        if collection.insert(result):
            print("成功保存到MongoDB")
    except Exception:
        print('someing wrong with MongDB')
        

MAX_PAGE = 100
def main():
    for i in range(1,MAX_PAGE+1):
        index_page(i)
    driver.close()


if __name__ =='__main__':
    main()    

小结

这段程序是对以前所学知识的综合利用,Mongodb是前几天现学现用,这是我第一次使用,关系型数据库Oracle,Sql server,Mysql都用过,基本知识也有掌握,非关系型数据库
Mongodb以后可能会写几篇学习笔记

运行结果

1,输出结果
pic4
2.查看mongodb中存入的数据
pic5
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,894评论 2 89
  • 本文是我接触爬虫以来,第三套爬虫的代码记录博客。本文主要是记录淘宝搜索美食的页面信息,工具是selenium 和 ...
    小白猿阅读 1,056评论 1 9
  • 虽然淘宝的页面数据是通过 Ajax 获取的,也就是可以通过开发者模式直接找到它请求数据的接口,并且发现返回的数据是...
    小飞牛_666阅读 881评论 0 11
  • http://opensource.apple.com/source/
    曲终人散Li阅读 350评论 0 0
  • 昨天没有联系,心心念念想着装修房子的事情,我以为自己专心投入一件事然后就可以将它遗忘,早晨起来思念泛滥,我一直压抑...
    水底深蓝阅读 145评论 0 0