爬取京东的手机类商品数据 | selenium | 爬虫详解

使用selenium的爬虫实践。
爬取京东网的手机数据,robots协议

本次就不讲解思路了,而是将源代码详细说明一下。

1、import

#webdriver用于生成浏览器
from selenium import webdriver
#Options用于初始化浏览器
from selenium.webdriver.chrome.options import Options
#用于搜索栏输入后确定。
from selenium.webdriver.common.keys import Keys
#pymysql是MySQL的接口
import pymysql.cursors
#用于计算本次爬虫用时/非必要/
import datetime
#用于selenium的强制等待
import time

这里需要解释的仅selenium的强制等待
在浏览器加载网页的过程中,网页的有些元素时常会有延迟的现象,在 HTML 元素还没有准备好的情况下去操作这个 HTML 元素必然会出现错误,这个时候 Selenium 需要等待HTML 元素。
而强制等待就是通过time.sleep()来做到的,因为无论是否加载完,都要休眠那么久,因而叫做‘强制等待’。
这样做缺点很多,下次开博详讲。

2、class Spider:

爬虫源码创建了一个爬虫类。如下简略:

class Spider:
	#浏览器的头
    headers={"User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 6.0 x64; en-US; rv:1.9pre) Gecko/2008072421 Minefield/3.0.2pre"}
    #初始化
    def startUp(self, url, key):...
    #关闭爬虫
    def closeUp(self):...
    #数据插入数据库
    def insertDB(self, mNo,mPrice, mNote):...
    #主要过程
    def processSpider(self,page=0):...
    #执行爬虫,即主程序
    def executeSpider(self, url, key):

2.1 startUp

初始化函数,初始化了浏览器,某些变量和数据库,以及执行搜索命令。

    def startUp(self, url, key):
        # Initializing Chrome browser
        chrome_options = Options()
        #下面两项为无头与禁止gpu加速;
        #--headless比较重要,执行selenium时不会弹出浏览器窗口
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        #创建Chrome浏览器
        self.driver = webdriver.Chrome(chrome_options=chrome_options)#
        # Initializing variables
        self.No = 0

数据库的初始化

        print('opened DB')
        try:
        	#连接数据库,参数有host,port,user,passwd,db和charset,详细请阅读MySQL的手册
            self.con = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="", db='db1',charset="utf8")
            #创建游标
            self.cursor = self.con.cursor(pymysql.cursors.DictCursor)
            #很重要的一件事是对已存在的数据库表来执行插入是很麻烦的,所有初始化时删除可能存在的表,重新创建。
            #删除表
            try:
                self.cursor.execute("drop table phones")
            except Exception as err:
                print(err)
            #创建表
            try:
                sql = """
create table phones(No varchar(32) primary key,Price varchar(32),Note text)"""
                self.cursor.execute(sql)
            except Exception as err:
                print(err)
			#变量的初始化,opened表示数据库是否打开,count是计数,执行了多少次插入语句
            self.opened = True
            self.count = 0
        except  Exception as err:
            print(err)
            self.opened = False

执行搜索命令

		#访问url,获得源代码
        self.driver.get(url)
        #这里是selenium是使用元素方法,输入与确认等
        keyInput = self.driver.find_element_by_id("key")
        keyInput.send_keys(key)
        keyInput.send_keys(Keys.ENTER)

以上详细指南,在博文2.1与2.2

2.2 closeUp

关闭数据库,并输出爬取数据数量。

    def closeUp(self):
        if self.opened:
            self.con.commit()
            self.con.close()
            self.opened = False
        print("closed")
        print("总共爬取", self.count, "条数据")

2.3 insertDB

数据库插入数据语句。每执行一次,count+1

    def insertDB(self, mNo,mPrice, mNote):
        try:
            if self.opened:
                sql = "insert into phones(No,Price,Note) values (%s,%s,%s)"
                self.cursor.execute(sql,(mNo,mPrice, mNote))
                self.count+=1
        except Exception as err:
            print(err)

2.4 progressSpider

这个模块主要是Spider执行的具体内容

    def processSpider(self,page=0):
        try:
        	#强制等待1秒
            time.sleep(1)
            print(self.driver.current_url)

观察京东搜索页的源代码,可以发现所有商品的数据都在属性为id='J_goodsList的标签div下,其下每个li就是一个商品数据。
selenium查找元素的具体语法

			lis=self.driver.find_elements_by_xpath("//div[@id='J_goodsList']//li[@class='gl-item']")
            for li in lis:
            #同理很容易找到所需要数据的位置,执行xpath和text()得到字符串内容
                price = li.find_element_by_xpath(".//div[@class='p-price']//i").text
                note = li.find_element_by_xpath(".//div[@class='p-name p-name-type-2']//em").text
                #观察发现有部分数据标题前是‘京品手机’等无关数据,通过if语句剔除。
                if note[0:2]=='京品':note=note[5:]
                if '】' in note:note=note[note.index('】')+1:]
                #给每一条数据编号
                self.No = self.No + 1
                no = str(self.No)
                while len(no) < 6:
                    no = "0" + no
                #输出
                print('%-8s %-8s %s'%(no,price,note))
                #插入
                self.insertDB(no, price, note)

循环插入所有数据后,即执行翻页的命令。a[@class=‘pn-next disabled’],这个标签是最后一页,找不到即执行nextPage = self.driver.find_element_by_xpath("//span[@class='p-num']//a[@class='pn-next']"),找到后执行nextPage.click(),点击翻页。递归执行self.processSpider(page)

            try:
                self.driver.find_element_by_xpath("//span[@class='p-num']//a[@class='pn-next disabled']")
            except:
                nextPage = self.driver.find_element_by_xpath("//span[@class='p-num']//a[@class='pn-next']")
                nextPage.click()
#当前页面数+1,以下if语句用来限制翻页数。
                page+=1
                if page==Page:return
                self.processSpider(page)
        except Exception as err:
            print(err)

2.5 executeSpider

    def executeSpider(self, url):
        starttime = datetime.datetime.now()
        print("Spider starting......")
        key=input('请输入要搜索的内容:')
        Page=int(input('请输入要爬取的页数,如若不限制,请输入-1:'))
        self.startUp(url, key)
        self.processSpider(Page)
        self.closeUp()
        print("Spider completed......")
        endtime = datetime.datetime.now()
        elapsed = (endtime - starttime).seconds
        print("Total ", elapsed, " seconds elapsed")

3、主程序

if __name__=='__main__':
    url = "http://www.jd.com"
    spider = Spider()
    spider.executeSpider(url)

4、完整源代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:LingInHeart
# Time: 2019/12/21
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import pymysql.cursors
import datetime
from selenium.webdriver.common.keys import Keys
import time

class Spider:
    def startUp(self, url, key):
        # Initializing Chrome browser
        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        self.driver = webdriver.Chrome(chrome_options=chrome_options)#
        # Initializing variables
        self.No = 0
        # Initializing database
        print('opened')
        try:
            self.con = pymysql.connect()
            self.cursor = self.con.cursor(pymysql.cursors.DictCursor)
            try:
                self.cursor.execute("drop table phones")
            except Exception as err:
                print(err)
            try:
                sql = """
create table phones(No varchar(32) primary key,Price varchar(32),Note text)"""
                self.cursor.execute(sql)
            except Exception as err:
                print(err)
                # self.cursor.execute("delete from books")

            self.opened = True
            self.count = 0
        except  Exception as err:
            print(err)
            self.opened = False

        self.driver.get(url)
        keyInput = self.driver.find_element_by_id("key")
        keyInput.send_keys(key)
        keyInput.send_keys(Keys.ENTER)
    def closeUp(self):
        if self.opened:
            self.con.commit()
            self.con.close()
            self.opened = False
        print("closed")
        print("总共爬取", self.count, "条数据")
    def insertDB(self, mNo,mPrice, mNote):
        try:
            if self.opened:
                sql = "insert into phones(No,Price,Note) values (%s,%s,%s)"
                self.cursor.execute(sql,(mNo,mPrice, mNote))
                self.count+=1
        except Exception as err:
            print(err)
    def processSpider(self,Page,page=0):
        try:
            time.sleep(1)
            print(self.driver.current_url)
            lis=self.driver.find_elements_by_xpath("//div[@id='J_goodsList']//li[@class='gl-item']")
            for li in lis:
                price = li.find_element_by_xpath(".//div[@class='p-price']//i").text
                note = li.find_element_by_xpath(".//div[@class='p-name p-name-type-2']//em").text
                if note[0:2]=='京品':note=note[5:]
                if '】' in note:note=note[note.index('】')+1:]
                self.No = self.No + 1
                no = str(self.No)
                while len(no) < 6:
                    no = "0" + no
                print('%-8s %-8s %s'%(no,price,note))
                self.insertDB(no, price, note)
            try:
                self.driver.find_element_by_xpath("//span[@class='p-num']//a[@class='pn-next disabled']")
            except:
                nextPage = self.driver.find_element_by_xpath("//span[@class='p-num']//a[@class='pn-next']")
                nextPage.click()
                page+=1
                if page==Page:return
                self.processSpider(Page,page)
        except Exception as err:
            print(err)
    def executeSpider(self, url):
        starttime = datetime.datetime.now()
        print("Spider starting......")
        key=input('请输入要搜索的内容:')
        Page=int(input('请输入要爬取的页数,如若不限制,请输入-1:'))
        self.startUp(url, key)
        self.processSpider(Page)
        self.closeUp()
        print("Spider completed......")
        endtime = datetime.datetime.now()
        elapsed = (endtime - starttime).seconds
        print("Total ", elapsed, " seconds elapsed")

if __name__=='__main__':
    url = "http://www.jd.com"
    spider = Spider()
    spider.executeSpider(url)
发布了70 篇原创文章 · 获赞 15 · 访问量 4290

猜你喜欢

转载自blog.csdn.net/Heart_for_Ling/article/details/103650024