下文提到的所有工具都可以在这里下载:拼多多砍价神器Python教程所需软件

大家可以点下小站,给个支持~谢谢啦~

/1 前语/

嘿,各位小伙伴们晚上好呀,今日小编又给我们带来干货内容啦,今日带来的是,怎么主动登录拼多多,而且砍价!

  原计划是不计划运用selenium的,但是由于要涉及砍价,需要用户权鉴,所以免不了登录。

但事实证明,我又被啪啪打脸了,拼多多的登录是真的难,各种参数把我干懵了。无赖之下,我仍是捡起了selenium,难逃真香规律呐,哈哈哈。

  好了,废话不多说,直接进入正题吧!

     事先声明:本文涉及的各类操作可能有多种实现方法,我只会提及其中一种,而且我采取的方法很有可能不是最优的方法。

/2 准备工作/

用Python操作手机APP的项目,无一例外需要布置ADB环境。至于什么是ADB,许多大神都讲过,只是写得比较专业,我等菜鸟看完仍是云里雾里。后文会详细解释。

万年不变的套装...

  Chromedriver:浏览器驱动,可以理解为一个没有界面的chrome浏览器。

  Selenium:用于模拟人对浏览器进行点击、输出、拖拽等操作,就相当于是个人在使用浏览器,也常常用来应付反爬虫措施。

Android SDK套装:通过电脑对安卓手机发起控制,至关重要的中间件。

/2.1 环境配置/

Android SDK下载和部署

说起Android SDK工具,那还真是不少,有SDK Tools、SDK、Platform-tools等等,这里我推荐SDK Tools,进入https://www.androiddevtools.cn/这个网站可以看到下图中的界面,选择自己对应的系统版本(zip版)下载。

将下载后的文件解压缩,运行其中的SDK Manager.exe文件,进入Packages安装管理界面,对于新手朋友们我建议直接使用默认选项,然后点击右下角的 Install XX packages 按钮,整个下载安装过程大概需要几十分钟,具体时间跟个人网速有关

接着就是配置环境变量了,把android-sdk目录下的platform-tools和tools文件夹添加到系统变量中,这一步属于常规操作,我就不再演示了。

执行完以上步骤,ADB环境就算配置完毕了,之后要做的就是开启手机的开发者选项、开启USB调试、用usb线将手机跟电脑链接。

下面进入关键的一步——通过ADB测试手机是否连接成功。进入系统终端,输入adb devices指令,如果出现下图中的结果,就说明刚才的环境部署成功了,其中device前面的是连接的设备号。

如果连接测试不成功,例如找不到设备或者设备连接不上,可以依次尝试关闭并再次开始调试、重启手机、重启电脑、插拔USB线等操作,通常都可以解决。

/2.2ADB的一些基本操作/

1).显示所有包名

adb shell pm list packages

这个指令会罗列出手机已经安装的所有应用包的名称,如果后缀加上参数-s,则会列出所有的系统应用的名称(下图),而加上后缀参数-3则会列出所有第三方应用名称。

2).显示活动程序

adb shell dumpsys activity activities

这个指令能够获取到当前手机系统中正在运行的程序包的名称,例如当我在手机中启动小米手机的“游戏中心”,运行上述指令就会获取到下图中的信息:

/3 了解工作原理/

我们都知道,要想砍价,就需要知道是谁砍的,登录以后需要等保存状态,一般有cookie,seeeion,token三种形式,那么拼多多的是怎么玩的呢?我们来图解一下,如下图所示。

通过上图,我们一目了然,能看出来,只要我们登录了之后,拿到了token,以后就不用selenium啦!所以,我们这里将登录获取token和点赞进行分离,分开进行,逻辑也十分的清晰,而且一点儿也不耽误事情。

/4 登录拼多多/

在上图我们可以看到右上方的登录按钮,在左侧可以看到需要点赞的图标以及点赞数,评论数和收藏数等等,接下来我们先进行第一步自动登录。

/5 开始登录/

点击右上方的登录按钮,页面将会进行跳转,进入到一个登录界面,如下图所示。

注意事项2抽屉如果登录多了,可能会让输入滑块验证码之类的,本文这部分并未有进行处理。

/6 开始自动砍价/

  在上面的工作中,我们已经成功的拿到登录返回的cookie了,接下来我们就开始自动点赞,而且有了之前的基础,下面的事情我们就好办多了。

  我们首先需要看一下,点赞请求的是哪个接口。我们清空一下浏览器中的NetWork日志,点击第一个砍价的砍价按钮,如下图所示。

我们可以看到,这个接口发的是post请求,但是发送的是什么数据呢?我们下滑继续一探究竟。

可以看到在Form Data里边,有一个linkid:29213534,是一串长数字,这个是什么呢?马上揭晓!

使用浏览器与网页的交互功能,我们点击对应的砍价,那么很快我们就可以锁定这个linkid,如下图所示。

  相信大家肯定都看得出来,其实post的那一串数字其实就是砍价ID。换句话说,我们只需要把这个ID都获取到,放到post构造数据里边,程序一运行,就可以实现砍价啦!

/7 代码实现/

下面是部分代码截图,完整代码在文末,如下图所示。

注:这里只是测试了前10个砍价。

/8完整代码/

# -*- coding: utf-8 -*-
"""
@author: 冰蓝
@site: http://lanbing510.info
"""import re
import urllib2
import sqlite3
import random
import threading
from bs4 import BeautifulSoupimport sys
reload(sys)
sys.setdefaultencoding("utf-8")#登录,不登录不能爬取三个月之内的数据
import LianJiaLogIn#Some User Agents
hds=[{'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'},\{'User-Agent':'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11'},\{'User-Agent':'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'},\{'User-Agent':'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0'},\{'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36'},\{'User-Agent':'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'},\{'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'},\{'User-Agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0'},\{'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1'},\{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1'},\{'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11'},\{'User-Agent':'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11'},\{'User-Agent':'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11'}]#北京区域列表
regions=[u"东城",u"西城",u"朝阳",u"海淀",u"丰台",u"石景山","通州",u"昌平",u"大兴",u"亦庄开发区",u"顺义",u"房山",u"门头沟",u"平谷",u"怀柔",u"密云",u"延庆",u"燕郊"]lock = threading.Lock()class SQLiteWraper(object):"""数据库的一个小封装,更好的处理多线程写入"""def __init__(self,path,command='',*args,**kwargs):  self.lock = threading.RLock() #锁  self.path = path #数据库连接参数  if command!='':conn=self.get_conn()cu=conn.cursor()cu.execute(command)def get_conn(self):  conn = sqlite3.connect(self.path)#,check_same_thread=False)  conn.text_factory=strreturn conn   def conn_close(self,conn=None):  conn.close()  def conn_trans(func):  def connection(self,*args,**kwargs):  self.lock.acquire()  conn = self.get_conn()  kwargs['conn'] = conn  rs = func(self,*args,**kwargs)  self.conn_close(conn)  self.lock.release()  return rs  return connection  @conn_trans    def execute(self,command,method_flag=0,conn=None):  cu = conn.cursor()try:if not method_flag:cu.execute(command)else:cu.execute(command[0],command[1])conn.commit()except sqlite3.IntegrityError,e:#print ereturn -1except Exception, e:print ereturn -2return 0@conn_transdef fetchall(self,command="select name from xiaoqu",conn=None):cu=conn.cursor()lists=[]try:cu.execute(command)lists=cu.fetchall()except Exception,e:print epassreturn listsdef gen_xiaoqu_insert_command(info_dict):"""生成小区数据库插入命令"""info_list=[u'小区名称',u'大区域',u'小区域',u'小区户型',u'建造时间']t=[]for il in info_list:if il in info_dict:t.append(info_dict[il])else:t.append('')t=tuple(t)command=(r"insert into xiaoqu values(?,?,?,?,?)",t)return commanddef gen_chengjiao_insert_command(info_dict):"""生成成交记录数据库插入命令"""info_list=[u'链接',u'小区名称',u'户型',u'面积',u'朝向',u'楼层',u'建造时间',u'签约时间',u'签约单价',u'签约总价',u'房产类型',u'学区',u'地铁']t=[]for il in info_list:if il in info_dict:t.append(info_dict[il])else:t.append('')t=tuple(t)command=(r"insert into chengjiao values(?,?,?,?,?,?,?,?,?,?,?,?,?)",t)return commanddef xiaoqu_spider(db_xq,url_page=u"http://bj.lianjia.com/xiaoqu/pg1rs%E6%98%8C%E5%B9%B3/"):"""爬取页面链接中的小区信息"""try:req = urllib2.Request(url_page,headers=hds[random.randint(0,len(hds)-1)])source_code = urllib2.urlopen(req,timeout=10).read()plain_text=unicode(source_code)#,errors='ignore')   soup = BeautifulSoup(plain_text)except (urllib2.HTTPError, urllib2.URLError), e:print eexit(-1)except Exception,e:print eexit(-1)xiaoqu_list=soup.findAll('div',{'class':'info-panel'})for xq in xiaoqu_list:info_dict={}info_dict.update({u'小区名称':xq.find('a').text})content=unicode(xq.find('div',{'class':'con'}).renderContents().strip())info=re.match(r".+>(.+)</a>.+>(.+)</a>.+</span>(.+)<span>.+</span>(.+)",content)if info:info=info.groups()info_dict.update({u'大区域':info[0]})info_dict.update({u'小区域':info[1]})info_dict.update({u'小区户型':info[2]})info_dict.update({u'建造时间':info[3][:4]})command=gen_xiaoqu_insert_command(info_dict)db_xq.execute(command,1)def do_xiaoqu_spider(db_xq,region=u"昌平"):"""爬取大区域中的所有小区信息"""url=u"http://bj.lianjia.com/xiaoqu/rs"+region+"/"try:req = urllib2.Request(url,headers=hds[random.randint(0,len(hds)-1)])source_code = urllib2.urlopen(req,timeout=5).read()plain_text=unicode(source_code)#,errors='ignore')   soup = BeautifulSoup(plain_text)except (urllib2.HTTPError, urllib2.URLError), e:print ereturnexcept Exception,e:print ereturnd="d="+soup.find('div',{'class':'page-box house-lst-page-box'}).get('page-data')exec(d)total_pages=d['totalPage']threads=[]for i in range(total_pages):url_page=u"http://bj.lianjia.com/xiaoqu/pg%drs%s/" % (i+1,region)t=threading.Thread(target=xiaoqu_spider,args=(db_xq,url_page))threads.append(t)for t in threads:t.start()for t in threads:t.join()print u"爬下了 %s 区全部的小区信息" % regiondef chengjiao_spider(db_cj,url_page=u"http://bj.lianjia.com/chengjiao/pg1rs%E5%86%A0%E5%BA%AD%E5%9B%AD"):"""爬取页面链接中的成交记录"""try:req = urllib2.Request(url_page,headers=hds[random.randint(0,len(hds)-1)])source_code = urllib2.urlopen(req,timeout=10).read()plain_text=unicode(source_code)#,errors='ignore')   soup = BeautifulSoup(plain_text)except (urllib2.HTTPError, urllib2.URLError), e:print eexception_write('chengjiao_spider',url_page)returnexcept Exception,e:print eexception_write('chengjiao_spider',url_page)returncj_list=soup.findAll('div',{'class':'info-panel'})for cj in cj_list:info_dict={}href=cj.find('a')if not href:continueinfo_dict.update({u'链接':href.attrs['href']})content=cj.find('h2').text.split()if content:info_dict.update({u'小区名称':content[0]})info_dict.update({u'户型':content[1]})info_dict.update({u'面积':content[2]})content=unicode(cj.find('div',{'class':'con'}).renderContents().strip())content=content.split('/')if content:info_dict.update({u'朝向':content[0].strip()})info_dict.update({u'楼层':content[1].strip()})if len(content)>=3:content[2]=content[2].strip();info_dict.update({u'建造时间':content[2][:4]}) content=cj.findAll('div',{'class':'div-cun'})if content:info_dict.update({u'签约时间':content[0].text})info_dict.update({u'签约单价':content[1].text})info_dict.update({u'签约总价':content[2].text})content=cj.find('div',{'class':'introduce'}).text.strip().split()if content:for c in content:if c.find(u'满')!=-1:info_dict.update({u'房产类型':c})elif c.find(u'学')!=-1:info_dict.update({u'学区':c})elif c.find(u'距')!=-1:info_dict.update({u'地铁':c})command=gen_chengjiao_insert_command(info_dict)db_cj.execute(command,1)def xiaoqu_chengjiao_spider(db_cj,xq_name=u"冠庭园"):"""爬取小区成交记录"""url=u"http://bj.lianjia.com/chengjiao/rs"+urllib2.quote(xq_name)+"/"try:req = urllib2.Request(url,headers=hds[random.randint(0,len(hds)-1)])source_code = urllib2.urlopen(req,timeout=10).read()plain_text=unicode(source_code)#,errors='ignore')   soup = BeautifulSoup(plain_text)except (urllib2.HTTPError, urllib2.URLError), e:print eexception_write('xiaoqu_chengjiao_spider',xq_name)returnexcept Exception,e:print eexception_write('xiaoqu_chengjiao_spider',xq_name)returncontent=soup.find('div',{'class':'page-box house-lst-page-box'})total_pages=0if content:d="d="+content.get('page-data')exec(d)total_pages=d['totalPage']threads=[]for i in range(total_pages):url_page=u"http://bj.lianjia.com/chengjiao/pg%drs%s/" % (i+1,urllib2.quote(xq_name))t=threading.Thread(target=chengjiao_spider,args=(db_cj,url_page))threads.append(t)for t in threads:t.start()for t in threads:t.join()def do_xiaoqu_chengjiao_spider(db_xq,db_cj):"""批量爬取小区成交记录"""count=0xq_list=db_xq.fetchall()for xq in xq_list:xiaoqu_chengjiao_spider(db_cj,xq[0])count+=1print 'have spidered %d xiaoqu' % countprint 'done'def exception_write(fun_name,url):"""写入异常信息到日志"""lock.acquire()f = open('log.txt','a')line="%s %s\n" % (fun_name,url)f.write(line)f.close()lock.release()def exception_read():"""从日志中读取异常信息"""lock.acquire()f=open('log.txt','r')lines=f.readlines()f.close()f=open('log.txt','w')f.truncate()f.close()lock.release()return linesdef exception_spider(db_cj):"""重新爬取爬取异常的链接"""count=0excep_list=exception_read()while excep_list:for excep in excep_list:excep=excep.strip()if excep=="":continueexcep_name,url=excep.split(" ",1)if excep_name=="chengjiao_spider":chengjiao_spider(db_cj,url)count+=1elif excep_name=="xiaoqu_chengjiao_spider":xiaoqu_chengjiao_spider(db_cj,url)count+=1else:print "wrong format"print "have spidered %d exception url" % countexcep_list=exception_read()print 'all done ^_^'if __name__=="__main__":command="create table if not exists xiaoqu (name TEXT primary key UNIQUE, regionb TEXT, regions TEXT, style TEXT, year TEXT)"db_xq=SQLiteWraper('lianjia-xq.db',command)command="create table if not exists chengjiao (href TEXT primary key UNIQUE, name TEXT, style TEXT, area TEXT, orientation TEXT, floor TEXT, year TEXT, sign_time TEXT, unit_price TEXT, total_price TEXT,fangchan_class TEXT, school TEXT, subway TEXT)"db_cj=SQLiteWraper('lianjia-cj.db',command)#爬下所有的小区信息for region in regions:do_xiaoqu_spider(db_xq,region)#爬下所有小区里的成交信息do_xiaoqu_chengjiao_spider(db_xq,db_cj)#重新爬取爬取异常的链接exception_spider(db_cj)

/9 结语/

代码详情我已经上传到这里了:点击传送门。如果觉得还不错,记得给个star噢,感想小伙伴们的支持!

拼多多砍价用户福利贴:通过python模拟操作进行拼多多砍价相关推荐

  1. python玩转android_今天玩点啥:利用Python模拟操作安卓手机实现刷dou音短视频浏览量...

    adb工具即Android Debug Bridge(安卓调试桥) tools.它就是一个命令行窗口,用于通过电脑端与模拟器或者真实设备交互.在某些特殊的情况下进入不了系统,adb就派上用场啦! Py ...

  2. python模拟银行存取款_python 模拟银行转账功能过程详解

    首先画出流程图,流程图与现实代码有出入,因为刚开始画流程图的时候,有些东西没考虑进去,后来写着写着就慢慢能想起来并实现了. 另有一点经验推荐给新手朋友,如果说碰到一个项目无从下手的话,就先慢慢去写,写 ...

  3. python 在软件自己自动输入-Python模拟百度自动输入搜索功能的实例

    如下所示: # 访问百度,模拟自动输入搜索 # 代码中引入selenium版本为:3.4.3 # 通过Chrom浏览器访问发起请求 # Chrom版本:59 ,chromdriver:2.3 # 需要 ...

  4. 特权级转移之 高,低特权级互相转移,模拟操作系统内核态与用户态切换以及应用程序调用系统资源

    TSS中保存的栈信息,是在特权级转移的时候被用到,具体就是在从低特权级转移到高特权级的时候会用.注意 从低到高 问题:为什么要保存 段寄存器值和通用寄存器的值? 既然是为了实现多任务,那么任务之间显然 ...

  5. 双11拼团最后的福利!老用户如何解散团并加入新团!

    摘要:双11拼团最后的福利!老用户如何解散团并加入新团! 各位开团没有拉新的团长们,双11拼团最后的福利快点上车! 一.解散原有团(已有拉新的团请忽略,无法解散) 登录双11拼团页面---> 我 ...

  6. 拼多多否认损失 200 亿;董明珠回应再拼三年;特斯拉称“未来艰难” | 极客头条...

    「CSDN 极客头条」,是从 CSDN 网站延伸至官方微信公众号的特别栏目,专注于一天业界事报道.风里雨里,我们将每天为朋友们,播报最新鲜有料的新闻资讯,让所有技术人,时刻紧跟业界潮流. 快讯速知 个 ...

  7. 拼多多:item_search-根据关键词取商品列表接口,拼多多关键词搜索API接口,拼多多上货API接口,拼多多API接口

    一.拼多多:item_search-根据关键词取商品列表接口,拼多多关键词搜索API接口,拼多多上货API接口代码如下: 1.公共参数: 名称 类型 必须 描述 key String 是 调用key( ...

  8. 拼多多商品详情采集上传京东店铺(拼多多商品详情接口,京东商品详情接口,拼多多整店宝贝采集接口,一键采集拼多多宝贝详情接口,无货源商品详情采集接口)代码对接教程

    拼多多商品详情采集上传京东店铺(拼多多商品详情接口,京东商品详情接口,拼多多整店宝贝采集接口,一键采集拼多多宝贝详情接口,无货源商品详情采集接口)代码对接教程如下: 1.公共参数 名称 类型 必须 描 ...

  9. 拼多多的新用户,是从哪来的?

    距离拼多多成为中国用户数第一的电商,或许只剩 1 个月了. 拼多多终于开始盈利了. 11 月 12 日晚,拼多多发布了 2020 年第三季度财报.截至 9 月底的 12 个月期间,拼多多平台 GMV ...

最新文章

  1. Tungsten Fabric SDN — SmartNIC vRouter 软件架构设计
  2. linux按顺序运行命令,linux – 安排cron作业打开终端并按顺序运行命令
  3. CSP认证202012-1期末预测之安全指数[C++题解]:简单题
  4. pwn(ctf)中常见的系统调用
  5. 10-java程序的编译阶段
  6. Python+OpenGL使用鼠标选择模型不同组成部分
  7. MySQL-30道面试题
  8. 最新小白详细描述在centos7.5上安装python3并使用Nginx+virtualenv+supervisor来部署tornado项目(整理集合结合实际)系列2
  9. python识别数字程序_Python识别处理照片中的条形码
  10. 大数据培训(第三季)——Linux基础-徐培成-专题视频课程
  11. springboot接入支付宝支付
  12. RC(Cadence RTL Compiler)物理综合
  13. 趋势预测方法(五)Holt-Winters模型_时序递推预测
  14. 【报告分享】淘宝直播2021年度报告-淘榜单淘宝直播(附下载)
  15. 软件项目管理 3.2.预测生存期模型
  16. word中添加续表和合并续表
  17. 接到阿里HR面试通过电话的那天我哭了,奋战6个月终进阿里定级P6+
  18. 【图片流转成图片】vue处理后端传来的图片流信息并转换成图片显示在前端页面上【详细解释】
  19. 为啥我的钉钉无法打卡拍照片
  20. jqweui的picker动态加载数据

热门文章

  1. 深度学习框架之争:TensorFlow退守工业界,PyTorch主导学术界?
  2. bcd转ascii码 流程图_BCD码与ASC码互转 | 学步园
  3. 大一计算机试题答案,大一计算机期末考试试题及答案
  4. vue源码解析:vue生命周期方法$destory方法的实现原理
  5. 微信小程序(四)会员专区
  6. 穆利堂(推荐)WxOA房地产协同办公整体解决方案-河南郑州房地产OA协同办公系统软件 穆穆-movno1
  7. Vim插件ale在windows下的安装配置与BUG解决
  8. window子对象的详细介绍 _@jie
  9. 有哪些比较安全可靠的PDF编辑器
  10. Linux PXE无盘工作站