100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Python爬虫淘宝基于selenium抓取淘宝商品数据测试过滑动验证

Python爬虫淘宝基于selenium抓取淘宝商品数据测试过滑动验证

时间:2019-02-11 15:05:10

相关推荐

Python爬虫淘宝基于selenium抓取淘宝商品数据测试过滑动验证

配置一下"可能需要修改的参数",就可以食用底部代码了,ps:可能已失效

本文章代码功能准备工作Python用到的库和准备工作可能需要修改的参数在CMD中打开一个Chrome浏览器并启用端口给Selenium调用导入模块调用刚打开的Chrome浏览器与Python建立连接全部代码复制可用在c盘新建一个app/chrome文件夹用来存放浏览器数据就行

本文章代码功能

淘宝搜索关键词,收集搜索到1到100页根据销量排名的各个商品信息:

商品本次排名商品链接商品搜索页的图片链接商品店铺旺旺名称商品标题商品价格商品销量抓取的时间商品ID

商品信息写入SQLite数据库,数据库表名为搜索的关键词

如果商品ID和销量与表中的一样则不写入数据库,如果商品ID有了但是销量不一样则添加这条新的数据,即防止出现完全重复的数据又能记录每个商品在不同时间段销量的变化

第一次写文章,有什么不足的地方欢迎指点和探讨。

有收获的话点个赞,让小弟知道还有人在看这篇文章。

代码运行样式:

数据库样式:

测试查询100页没有问题

准备工作

淘宝反爬虫比较严格,所以使用Selenium比较贴近真实使用环境,出现验证滑动条比较容易过。然后用了SQLite数据库来储存数据,要是觉得SQLite数据库用的不方便可以在Python中加条函数导出到Excel。

参考代码:

from xlsxwriter.workbook import Workbookimport sqlite3workbook = Workbook('output.xlsx')worksheet = workbook.add_worksheet('男装')content=sqlite3.connect('content.db')c=conn.cursor()ti=c.execute("select * from '男装'")for i, row in enumerate(ti):for j, value in enumerate(row):worksheet.write(i, j, value)workbook.close()

Python用到的库和准备工作

Python3.7开发环境re库time库sqlite3库Selenium库:调用Chrome浏览器的webdriver驱动文件,点击下载chromedrive 。将下载的浏览器驱动文件chromedriver丢到Chrome浏览器目录中的Application文件夹下,配置Chrome浏览器位置到PATH环境。

Selenium 入门参考文献;SQLite数据库,安装和配置如下: SQLite下载链接 ,下载sqlite-tools-win32-**.zip 和 sqlite-dll-win32-*.zip 压缩文件。在盘根目录创建sqlite文件夹,并添加到 PATH 环境变量。解压上面两个压缩文件(得到 sqlite3.def、sqlite3.dll 和 sqlite3.exe 文件)到sqlite文件夹。在命令提示符下,使用 sqlite3 命令,显示如下就是安装成功了:

C:\>sqlite3SQLite version 3.7.15.2 -01-09 11:53:05Enter ".help" for instructionsEnter SQL statements terminated with a ";"sqlite>

可能需要修改的参数

在CMD中打开一个Chrome浏览器并启用端口给Selenium调用

remote-debugging-port= 浏览器使用的端口,自己定义一个就行。

user-data-dir= 新打开的浏览器文件目录,自己创建一个就行。

示例代码:

chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\App\Chrome"

第一次创建浏览器文件,在打开浏览器之后最好去登录一下淘宝

导入模块

from selenium import webdriverimport timeimport reimport sqlite3from mon.action_chains import ActionChains

调用刚打开的Chrome浏览器与Python建立连接

配置Chrome浏览浏览器

chromedriver.exe的目录根据自己放的位置自行修改

增加一个js代码,在页面打开前修改windows.navigator.webdriver检测结果为undefined

代码如下:

chrome_options = webdriver.ChromeOptions()chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")chrome_driver = r"C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"Chrome = webdriver.Chrome(chrome_driver, options=chrome_options)# 设置位置和宽高Chrome.set_window_position(x=1000, y=353)Chrome.set_window_size(width=900, height=500)# 拦截webdriver检测代码Chrome.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": """Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"""})

全部代码复制可用

路径配置没问题的话,新建一个.py文件就可以用了。

1月24日更新代码

在c盘新建一个app/chrome文件夹用来存放浏览器数据就行

数据库中的两个值解读:

key_id :主键,自增加的不用理会order_number:本次运行中的排名,每次运行都是从1开始添加的

from selenium import webdriverimport timeimport reimport osimport sqlite3from mon.action_chains import ActionChains'''根据关键词,在淘宝搜索页面按照销量排序,收集商品信息.在cmd中运行: chrome.exe --remote-debugging-port=9222 --user-data-dir=""数据库表查询:先根据id选取唯一值,根据time时间排序,根据sales观察销量变化'''def open_chrome():user_port = input('输入要使用的端口(回车默认9222):') or 9222find_port = os.popen('netstat -ano|findstr {}'.format(user_port)).read()while str(user_port) in find_port:print(user_port, '端口已被占用,正在更换端口')user_port += 1find_port = os.popen('netstat -ano|findstr {}'.format(user_port)).read()os.system(r'start chrome.exe --remote-debugging-port={} --user-data-dir="C:\app\chrome"'.format(user_port))print('使用端口:',user_port)class ItemClass:def __init__(self, url_keyword, user_page):self.url_keyword = url_keywordself.user_page = user_pageself.img_url = Noneself.item_url = Noneself.sales = Noneself.price = Noneself.detail_head = Noneself.shop_name = Noneself.order_number = 0self.t_dic = []self.conn = Noneself.cursor = Noneself.img_err = 0self.err_log = []chrome_options = webdriver.ChromeOptions()chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:{}".format(user_port))chrome_driver = r"C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"try:self.Chrome = webdriver.Chrome(chrome_driver, options=chrome_options)except Exception as err:print('开启浏览器错误:\n', err)print(r'cmd中打开chrome.exe --remote-debugging-port=9222 --user-data-dir=""')self.err_log.append(err)# 设置位置和宽高self.Chrome.set_window_position(x=1000, y=353)self.Chrome.set_window_size(width=900, height=500)# 拦截webdriver检测代码self.Chrome.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": """Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"""})def searchwords(self):self.Chrome.get('')self.Chrome.find_element_by_xpath('//*[@id="q"]').send_keys('{}'.format(self.url_keyword))time.sleep(0.3)self.Chrome.find_element_by_xpath('//button[@class="btn-search tb-bg"]').click()# 如果出现验证码拦截def intercept(self):if '验证码拦截' in self.Chrome.title:print('滑动验证码')slider = self.Chrome.find_element_by_xpath("//span[contains(@class, 'btn_slide')]")try:# 找到滑块# 判断滑块是否可见if slider.is_displayed():# 点击并且不松开鼠标ActionChains(self.Chrome).click_and_hold(on_element=slider).perform()# 往右边移动258个位置ActionChains(self.Chrome).move_by_offset(xoffset=258, yoffset=0).perform()# 松开鼠标ActionChains(self.Chrome).pause(0.5).release().perform()except Exception as err:print('验证码滑动出错')print(err)self.err_log.append(err)time.sleep(1)# 直接下拉到固定的最底栏def scrolldown(self):y_plus = 450y = 0for i in range(9):y += y_plusself.Chrome.execute_script("window.scroll(0,{})".format(y))time.sleep(0.2)# self.Chrome.execute_script("window.scroll(400,200)")# 下拉到最底栏第二种,检查是否到最底栏def scrolldown_two(self):t = Truey = 400x = self.Chrome.execute_script("return document.body.scrollHeight;")while t:check_height = self.Chrome.execute_script("return document.body.scrollHeight;")x += yself.Chrome.execute_script("window.scroll(0,{})".format(x))time.sleep(0.5)check_height1 = self.Chrome.execute_script("return document.body.scrollHeight;")if check_height == check_height1:# print(str(check_height1))t = Falseself.Chrome.execute_script("window.scroll(0,200)")# 按照销量排序def sales_sort(self):time.sleep(1)self.Chrome.find_element_by_xpath('//a[@data-value="sale-desc"]').click()# 点击下一页def click_next(self):self.Chrome.execute_script("window.scroll(400,150)")self.Chrome.find_element_by_xpath('//a[@title="下一页"]').click()time.sleep(1)# 获得商品列表信息并储存def get_content(self):time.sleep(0.2)self.scrolldown()time.sleep(0.5)for item in self.Chrome.find_elements_by_xpath('.//*[@class="item J_MouserOnverReq "]'):try:self.order_number += 1self.img_url = \item.find_element_by_xpath('.//*[@class="J_ItemPic img"]').get_attribute('src').split('_360')[0]self.item_url = item.find_element_by_xpath('.//*[@class="pic-link J_ClickStat J_ItemPicA"]')\.get_attribute('href').split('&')[0]sales_tem = item.find_element_by_xpath('.//*[@class="deal-cnt"]').textself.sales = int(''.join(re.findall(r'\d*\d', sales_tem)))self.price = float(item.find_element_by_xpath('.//*[@class="price g_price g_price-highlight"]/strong').text)self.detail_head = item.find_element_by_xpath('.//*[@class="J_ItemPic img"]').get_attribute('alt')self.shop_name = item.find_element_by_xpath('.//*[@class="shopname J_MouseEneterLeave J_ShopInfo"]').textif '万' in sales_tem:self.sales = int(float(re.findall(r'\d+.\d*', sales_tem)[0])*10000)if '.gif' in self.img_url:self.img_err += 1print('排名第{}位:\t销量:{}件,\t价格为:{}元, \t店铺名:{}, \t图片错误:{}'.format(self.order_number, self.sales, self.price, self.shop_name, self.img_url))else:print('排名第{}位:\t销量:{}件,\t价格为:{}元, \t店铺名:{}'.format(self.order_number, self.sales, self.price, self.shop_name))self.t_dic = [self.item_url, self.img_url, self.shop_name, self.detail_head, self.price, self.sales]# 储存在多张表# self.save_content()# 储存在一表self.save_content_one()except Exception as err:print('第{}号出错,出错代码为: '.format(self.order_number), err)self.err_log.append('第{}号,出错代码为:{} '.format(self.order_number, err))continue# 储存多张表def save_content(self):t_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))# 获取商品idid_and_table_name = int(self.item_url.split('=')[1])# 字典里增加时间和idself.t_dic.append(t_time)self.t_dic.append(id_and_table_name)# 创建表sql代码,如果不存在则创建表sql_if_exists = '''CREATE TABLE IF NOT EXISTS [{}] (sales INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,order_number INT,idINT,time TEXT,price REAL,headerTEXT,shop TXEXT,item TEXT,img TEXT);'''# 写入表sql代码,如果表里有匹配到的数据,则写入否则不写入sql_insert_or_ignore = '''INSERT INTO [{0}] (order_number,id,time,sales,price,header,shop,img,item) \SELECT '{2}',{1[7]},'{1[6]}','{1[5]}','{1[4]}','{1[3]}','{1[2]}','{1[1]}','{1[0]}'WHERE NOT EXISTS (SELECT *FROM [{0}] WHERE id='{1[7]}' AND sales='{1[5]}');'''# 执行创建表sql代码,用商品id当表名self.cursor.execute(sql_if_exists.format(id_and_table_name))# 执行写入表sql代码self.cursor.execute(sql_insert_or_ignore.format(id_and_table_name, self.t_dic, self.order_number))# 保存mit()# 字典归零self.t_dic = []# 储存在一张表中def save_content_one(self):# 时间t_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))# 获取商品idt_id = int(self.item_url.split('=')[1])# 字典里加入时间self.t_dic.append(t_time)# 字典里加入商品idself.t_dic.append(t_id)# 用搜索关键词当表名table_name = self.url_keyword# 创建表sql代码,如果不存在则创建表sql_if_exists = '''CREATE TABLE IF NOT EXISTS [{}] (key_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,order_number INT,idINT,time TEXT,sales INT,price REAL,headerTEXT,shop TXEXT,item TEXT,img TEXT);'''# 写入表sql代码,如果表里有匹配到的数据,则写入否则不写入sql_insert_or_ignore = '''INSERT INTO [{0}] (order_number,id,time,sales,price,header,shop,img,item) \SELECT '{2}',{1[7]},'{1[6]}','{1[5]}','{1[4]}','{1[3]}','{1[2]}','{1[1]}','{1[0]}'WHERE NOT EXISTS (SELECT *FROM [{0}] WHERE id='{1[7]}' AND sales='{1[5]}');'''# 执行创建表sql代码self.cursor.execute(sql_if_exists.format(table_name))# 执行写入表sql代码self.cursor.execute(sql_insert_or_ignore.format(table_name, self.t_dic, self.order_number))# 保存mit()# 字典归零self.t_dic = []# 开始def start(self, t_path=r'content.db'):print('开始运行')self.conn = sqlite3.connect(t_path)self.cursor = self.conn.cursor()get_page = 0 # 查询到了多少页# url = '/search?q={}'.format(self.url_keyword)# self.Chrome.get(url)self.searchwords()time.sleep(1)self.intercept()self.sales_sort() # 按销量排序try:while get_page < self.user_page:get_page += 1print('抓取第{}页:'.format(get_page))self.get_content()if get_page != self.user_page:self.click_next()except Exception as err:print('出现错误:', err)self.err_log.append(err)self.cursor.close()mit()self.conn.close()else:print('抓取结束一共抓取了{}位'.format(self.order_number))self.cursor.close()mit()self.conn.close()if __name__ == '__main__':start_time = time.time()# 打开远程调用浏览器user_port = 9222# if '9222' not in os.popen('netstat -ano|findstr 9222').read():# print('打开chrome浏览器')open_chrome()# 程序开始browser = ItemClass(url_keyword=input('输入要查询的关键词(默认男童):') or '男童', user_page=int(input('查询的页数(默认10):') or 10))browser.start()# 程序结束打印信息end_time = time.time()run_time = '%.2f' % (end_time-start_time)print('运行了:{}秒'.format(run_time))# 写入日志with open('log.txt', 'a+') as f:f.write('\n程序运行结束日期:{}\n抓取数量:{}\n使用时间:{}秒\n图片获取错误:{}个\n程序出错信息:{}个\n'.format(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())),browser.order_number, run_time, browser.img_err, len(browser.err_log)))for err_tosrt in browser.err_log:f.write(str(err_tosrt)+'\n')

==如果有收获、点个赞哦=

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。