之前我用pyppeteer绕过了淘宝登录时对于web driver的检测,但是这并不意味这登录

后就没有检测了,今天我就来以爬取搜索关键字得到的商品名称为例操作一下。

整个过程有 4 步:1.登录,2.输入关键字并点击搜索,3.滑到最底部并获取数据,4.点击下一页,然后重复步骤 3,4 直到没有下一页(实际上一个账号并不能每一页全部爬完,要想全部爬完可能要买或者借账号,下面的教程我只爬前几页的数据)。然后就是要搭好一个框架,为了让程序看起来简单,我就使用面向对象的设计方法来设计这个程序,大致代码如下:

class TaoBaoSpider:async def login(self):passasync def search(self):passasync def crawl(self):pass

因为pyppeteer是通过async和await异步机制来实现的,所以方法必须都是异步的,所以我在每个方法定义之前都加上了async关键字。

登录

登录有两种方式,一种是手机扫码登录,另一种是输入账号密码登录,为了尽可能简单和尽可能的不被检测,我使用手机扫码登录。既然使用手机扫码登录,那么 login 方法的实现就非常简单,只要 sleep 一会就行了。但这里需要注意的是,不能使用 time 模块的 sleep 函数(这是同步阻塞接口的等待,不能在异步函数中出现),我们需要一个异步等待,这个异步等待就是 asyncio 模块的 sleep 函数,调用时需要用关键字 await 修饰,如下所示。

from asyncio import sleepclass TaoBaoSpider:@staticmethodasync def login():await sleep(10)async def search(self):passasync def crawl(self):pass

这里我设置等待时间为 10 秒,在这 10 秒钟完成手机扫码登录应该够了,如果觉得时间紧迫可以把 10 改成更大的数。

下面我们需要进行测试,在测试之前,我们要先写好这个类的构造方法,来初始化一些属性,因为在 search 和 crawl 方法中都需要使用浏览器对象,所以我们要初始化一个浏览器对象,如下所示。

self.browser = await launch(headless=False, args=['--disable-infobars', f'--window-size={self.width},{self.height}'])

我们都知道,await 关键字必须在 async 修饰的函数体内,有些人可能会想到按照下面这种写法:

async def __init__(self)

这样写是错的,如图所示。

稍微翻译一下,说函数“__init__”不可以是异步的!那么我们就需要单独定义一个异步方法来完成异步的初始化。这个异步方法我就定义为 init 了。下面就主要编写 __init__ 和 init 两个方法。

from asyncio import sleep, get_event_loop
from pyppeteer import launchclass TaoBaoSpider:def __init__(self):self.width, self.height = 1500, 800get_event_loop().run_until_complete(self.init())get_event_loop().run_until_complete(self.login())get_event_loop().run_until_complete(self.search())get_event_loop().run_until_complete(self.crawl())async def init(self):# noinspection PyAttributeOutsideInitself.browser = await launch(headless=False, args=['--disable-infobars', f'--window-size={self.width},{self.height}'])# noinspection PyAttributeOutsideInitself.page = await self.browser.newPage()await self.page.setViewport({'width': self.width, 'height': self.height})await self.page.goto('https://login.taobao.com/member/login.jhtml?redirectURL=https://www.taobao.com/')await self.page.evaluate('()=>{Object.defineProperties(navigator,{webdriver:{get:()=>false}})}')@staticmethodasync def login():await sleep(10)async def search(self):passasync def crawl(self):pass

运行程序会弹出一个Chromium浏览器,浏览器显示的就是淘宝登录页面,手机扫码可以成功登录,没有被检测,登录部分测试完毕,下面我们主要编写一下search方法。

搜索

在编写搜索方法之前,我们来想一个问题,刚登录就搜索是不是太快了?我们都知道,访问太快容易被 BAN 的,所以我们需要降低访问速度。这个可以通过异步等待来实现。

下面又来了一个关键性的问题,我具体应该等待多久?时间太长效率就太低,时间太短容易被检测,我们可以想一下自己手动访问淘宝速度是怎样的,我感觉是1到4秒进行一次点击啥的,有些人就想当然认为

这就太简单了,直接构造方法中初始化不就完了吗?如下所示:

self.sleep_time = 1+random()*3

其实这样写是错的,因为这个字段值在中途不会被重新初始化,也就是每两个事件之间都是相同的时间间隔,这样不被检测出来就有鬼,毕竟人操作不可能这么机械化,那么我们需要在每次调用它的时候都能修改它的值,既然这个值在不断的变化,我们可以把它定义成方法,可是定义成方法后面的每次调用都要一对括号,这简直是太繁琐了。我们可以使用 property 来装饰这个方法,在调用的时候不需要加括号了,下面我实现搜索的方法。

from asyncio import sleep, get_event_loop
from pyppeteer import launch
from random import randomclass TaoBaoSpider:def __init__(self):self.width, self.height = 1500, 800get_event_loop().run_until_complete(self.init())get_event_loop().run_until_complete(self.login())get_event_loop().run_until_complete(self.search())get_event_loop().run_until_complete(self.crawl())async def init(self):# noinspection PyAttributeOutsideInitself.browser = await launch(headless=False,args=['--disable-infobars', f'--window-size={self.width},{self.height}'])# noinspection PyAttributeOutsideInitself.page = await self.browser.newPage()await self.page.setViewport({'width': self.width, 'height': self.height})await self.page.goto('https://login.taobao.com/member/login.jhtml?redirectURL=https://www.taobao.com/')await self.page.evaluate('()=>{Object.defineProperties(navigator,{webdriver:{get:()=>false}})}')@staticmethodasync def login():await sleep(10)@propertydef sleep_time(self):return 1+random()*3async def login():await sleep(10)@propertydef sleep_time(self):return 1+random()*3async def search(self):await self.page.click('#q')await sleep(self.sleep_time)await self.page.keyboard.type('机械革命')await sleep(self.sleep_time)await self.page.click('#J_TSearchForm > div.search-button > button')await sleep(self.sleep_time)async def crawl(self):passif __name__ == '__main__':TaoBaoSpider()

在这里我搜索的关键字直接赋了初值,大家可以自己修改成输入传参的形式,这很简单,我就不讲了,下面是最关键的步骤,爬取数据。

爬取数据

爬取数据我们就爬一下搜索到的商品名称,下图中价格下面的两行字。

通过审查元素我们可以找到每一段字的对应的HTML的源码形式,如下图所示:

既然a标签下还有标签,那么我们就需要做出二次过滤,第一次提取a标签下的内容,第二次把第一次提取的数据的标签和空白字符去掉。所以需要些两个正则,首先是提取a标签下的内容,经过不停地比对,可以得出最后的正则:

pattern = compile(r'<a id=".*?" class="J_ClickStat".*?>(.*?)</a>',S)

接着是用来替换的正则:

repl_pattern = compile(r'<.*?>|\s+')

接下来我们尝试获取前5页的数据。先到底部(不能一蹴而就,一定要模拟人的操作。这里使用匀加速来实现,加速度是一个随机值,不随机可能会被检测),然后获取页面源码进行数据筛选。最后跳到下一页,重复之前的操作。下面直接给出完整的源代码。

from asyncio import sleep, get_event_loop
from pyppeteer import launch
from random import random
from re import compile, Sclass TaoBaoSpider:def __init__(self):self.width, self.height = 1500, 800get_event_loop().run_until_complete(self.init())get_event_loop().run_until_complete(self.login())get_event_loop().run_until_complete(self.search())get_event_loop().run_until_complete(self.crawl())async def init(self):# noinspection PyAttributeOutsideInitself.browser = await launch(headless=False,args=['--disable-infobars', f'--window-size={self.width},{self.height}'])# noinspection PyAttributeOutsideInitself.page = await self.browser.newPage()await self.page.setViewport({'width': self.width, 'height': self.height})await self.page.goto('https://login.taobao.com/member/login.jhtml?redirectURL=https://www.taobao.com/')await self.page.evaluate('()=>{Object.defineProperties(navigator,{webdriver:{get:()=>false}})}')@staticmethodasync def login():await sleep(10)@propertydef sleep_time(self):return 1+random()*3async def search(self):await self.page.click('#q')await sleep(self.sleep_time)await self.page.keyboard.type('机械革命')await sleep(self.sleep_time)await self.page.click('#J_TSearchForm > div.search-button > button')await sleep(self.sleep_time)async def crawl(self):pattern = compile(r'<a id=".*?" class="J_ClickStat".*?>(.*?)</a>', S)repl_pattern = compile(r'<.*?>|\s+')for i in range(5):# document.body.clientHeightheight = await self.page.evaluate('document.body.clientHeight')scrolled_height = 0a = 1+random()t = 1# window.scrollTo(width, height)while scrolled_height < height:scrolled_height = int(1/2*a*t**2)  # x=v0*t+1/2*a*t**2,v0=0await self.page.evaluate(f'window.scrollTo(0,{scrolled_height})')t += 1await sleep(self.sleep_time)html = await self.page.content()results = pattern.findall(html)for result in results:result = repl_pattern.sub('', result)print(result)print()await sleep(self.sleep_time)await self.page.click('#mainsrp-pager > div > div > div > ul > li.item.next > a')await sleep(self.sleep_time)await sleep(self.sleep_time)if __name__ == '__main__':TaoBaoSpider()

运行结果如图所示。

可以发现显示在网页上的数据被爬了下来,下面来总结一些应付这种反爬特别严的网站的一些技巧:

1.模拟人的操作,每次请求都要随机等待一会。

2.如果需要登录,尽量手动登录,自动登录可能会被检测。

3.一个账号(如果要登录)或一个IP访问次数不要太多,如果要爬很多数据可以使用多个账号(如果要登录)或者对个IP。

使用pyppeteer爬取淘宝商品相关推荐

  1. 利用Selenium爬取淘宝商品信息

    文章来源:公众号-智能化IT系统. 一.  Selenium和PhantomJS介绍 Selenium是一个用于Web应用程序测试的工具,Selenium直接运行在浏览器中,就像真正的用户在操作一样. ...

  2. 爬取淘宝商品信息selenium+pyquery+mongodb

    ''' 爬取淘宝商品信息,通过selenium获得渲染后的源码,pyquery解析,mongodb存储 '''from selenium import webdriver from selenium. ...

  3. python爬淘宝商品销量信息_python爬取淘宝商品销量信息

    python爬取淘宝商品销量的程序,运行程序,输入想要爬取的商品关键词,在代码中的'###'可以进一步约束商品的属性,比如某某作者的书籍,可以在###处输入作者名字,以及时期等等.最后可以得到所要商品 ...

  4. 2021-11-16爬取淘宝商品信息时如何获取cookie

    爬取淘宝商品信息时如何获取cookie ###一.基本环境 1.win10系统 2.火狐浏览器 3.编程软件anaconda 4.淘宝的robots:https://www.taobao.com/ro ...

  5. python爬取淘宝商品做数据挖掘

    作业要求:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/3159 项目内容: 本项目选择 淘宝商品类目:零食 数量:一共100页,44 ...

  6. python爬取淘宝商品图片

    python爬取淘宝商品的图片 话不多说,直接上代码: from selenium import webdriver from selenium.webdriver.common import key ...

  7. 爬虫「Python」:一次登录,解决爬取淘宝商品评价繁杂的问题——简述 Headers 的使用

    在爬取淘宝商品评价时,可能会被以下几个问题所困扰: (1)直接请求,服务器要求登录帐号,怎么登录? (2)请求到的网页 Html 怎么没有我要的评价信息? (3)等等 下面介绍一下我使用的比较简单的获 ...

  8. Python + selenium 爬取淘宝商品列表及商品评论 2021-08-26

    Python + selenium 爬取淘宝商品列表及商品评论[2021-08-26] 主要内容 登录淘宝 获取商品列表 获取评论信息 存入数据库 需要提醒 主要内容 通过python3.8+ sel ...

  9. 无法爬取淘宝商品页面

    问题描述:无法爬取淘宝商品页面 案例如下: import requests import redef getHTMLText(url):try: r = requests.get(url,timeou ...

最新文章

  1. 2020牛客多校第7场C-A National Pandemic[树链剖分+思维]
  2. class参数传入 python_小白学 Python 爬虫(20):Xpath 进阶
  3. SpringCloud 微服务
  4. ubuntu 12.04 nginx+ mono-fastcgi-server
  5. Python基础知识__字符串
  6. Linux 内核修复5个高危漏洞
  7. 一个盒子两个摄像头,你就不知道怎么办了?
  8. Python Tornado web框架简单例子
  9. GsonFormat的使用 (转)
  10. LM393双电压比较器集成电路引脚图及功能_工作原理及应用电路
  11. 视频动态滚动水印制作,滚动的水印字幕
  12. 【论文翻译】Generation of Non-Deterministic Synthetic Face Datasets Guided by Identity Priors(21.12)
  13. python中tuple的意思_pythontuple什么意思
  14. 转: 学习开源项目的若干建议(infoq)
  15. (一)Yocto的介绍
  16. 远程唤醒 过一段时间 失效
  17. 转:中国移动宽带光猫F663路由模式改桥接模式
  18. rabbitmq安装 虚拟ip_步骤4:配置IPv6地址
  19. 他是“创业教父”,做出4家上市公司,秘诀6个字:找俗人,打呆仗!
  20. Ubuntu下配置WPS字体

热门文章

  1. mysql虚拟列(Generated Columns)及JSON字段类型的使用
  2. 洛谷——P1223 排队接水
  3. Leecode06. Z 字形变换——Leecode大厂热题100道系列
  4. L1-009 N个数求和(分数运算模板)(34行代码AC)
  5. 【图示】小程序云开发和不使用云开发的区别
  6. JavaWeb程序设计任务教程(黑马程序员 传智播客)测一测 编写一个Servlet,实现统计网站被访问次数的功能
  7. 并发编程中的“冷知识”(更新中)
  8. oraclde存储过程_Oracle存储过程详解(引用)+补充
  9. linux 扫描i2c端口,s3c2440用I2C接口访问EEPROM
  10. 应付账款账龄分析模板_超全的财务会计表单模板分享