使用Appium爬取当当网App的所有数据

image

01 目标

场景:有时候通过传统的方法去爬一些 Web 网页或者 APP,受限于对方的反爬方案,很难爬到想要的数据,这个时候可以考虑使用「Appium」结合「mitmproxy」的方式去爬取数据。

其中,Appium 负责驱动 App 端自动化运行,mitmproxy 负责截取请求数据并解析保存到数据库。

今天的目的是爬取「当当网」的所有数据,并保存到 MongoDB 数据库当中。

02 准备工作

首先,需要在 PC 上安装好 Charles 和 Appium Desktop,并配置好 mitmproxy 环境。

# 安装mitmproxy依赖包
pip3 install mitmproxy

# 安装pymongod
bpip3 install pymongo

另外,需要准备一台 Android 手机,另外 PC 端配置好 Android 开发环境。

03 爬取思路

  1. 在配置好手动代理的情况下,打开 Charles 实时捕获客户端的发起的网络请求。

打开当当网搜索商品的页面,搜索关键字「Python」,可以在 Charles 查看到当前请求的 URL 地址包含:「word=Python」

image

编写 mitmproxy 的执行脚本文件,重写 response() 函数,通过对请求的 URL 进行过滤,对有用的数据进行整理并保存到 MongoDB 数据库当中。

class DangDangMongo(object):   
    def __init__(self):        
      self.client = MongoClient('localhost')        
      self.db = self.client['admin']        
      self.db.authenticate("root", "xag")        
      self.dangdang_book_collection = self.db['dangdang_book']def response(flow):    

    # 过滤请求的URL    
    if 'keyword=Python' in request.url:        
        data = json.loads(response.text.encode('utf-8'))       
     # 书籍       
        products = data.get('products') or None        
        product_datas = []        
        for product in products:            
        # 书ID            
        product_id = product.get('id')            
        # 书名            
        product_name = product.get('name')            
        # 书价格            
        product_price = product.get('price')            
        # 作者            
        authorname = product.get('authorname')            
        # 出版社            
        publisher = product.get('publisher')            
        product_datas.append({                'product_id': product_id,                'product_name': product_name,                'product_price': product_price,                'authorname': authorname,                'publisher': publisher            })        
        DangDangMongo().dangdang_book_collection.insert_many(product_datas)        
        print('成功插入数据成功')

先打开客户端的手动代理监听 8080 端口,然后执行「mitmdump」命令,然后滚动商品界面,发现数据到写入到数据库中了。

 mitmdump -s script_dangdang.py 
  1. 下面我们要利用 Appium 帮我们实现 自动化。

首先打开 Appium Desktop,并启动服务。

image

打开 Android Studio,利用菜单栏的 Build-Analyze APK 分析当当网的安卓应用,打开 AndroidManifest.xml

可以发现应用包名和初始化 Activity 分别为:

com.dangdang.buy2、com.dangdang.buy2.StartupActivity

image

获取到包名和初始 Activity 后,就可以利用 WebDriver 去模拟打开当当网 APP。

self.caps = {            
  'automationName': DRIVER,            
  'platformName': PLATFORM,           
  'deviceName': DEVICE_NAME,            
  'appPackage': APP_PACKAGE,            
  'appActivity': APP_ACTIVITY,            
  'platformVersion': ANDROID_VERSION,            
  'autoGrantPermissions': AUTO_GRANT_PERMISSIONS,            
  'unicodeKeyboard': True,            
  'resetKeyboard': True        
}
self.driver = webdriver.Remote(DRIVER_SERVER, self.caps)

接着使用 Android SDK 自带的工具 uiautomatorviewer 获取到元素信息,使用 Appium 中的 WebDriver 去操作 UI 元素。

image

第一次打开应用的时候,可能会出现红包雨对话框、新人专享红包对话框、切换城市对话框,这里需要通过元素 ID 获取到关闭按钮,执行点击操作来关闭这些对话框。

这里创建一个 新的线程 来单独处理这些对话框。

class ExtraJob(threading.Thread):
   def run(self):
        while self.__running.isSet():

            # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回
            self.__flag.wait()

            # 1.0 【红包雨】对话框
            red_packet_element = is_element_exist(self.driver, 'com.dangdang.buy2:id/close')
            if red_packet_element:
                red_packet_element.click()

            # 1.1 【新人专享券】对话框
            new_welcome_page_sure_element = is_element_exist(self.driver, 'com.dangdang.buy2:id/dialog_cancel_tv')
            if new_welcome_page_sure_element:
                new_welcome_page_sure_element.click()

            # 1.2 【切换位置】对话框
            change_city_cancle_element = is_element_exist(self.driver, 'com.dangdang.buy2:id/left_bt')
            if change_city_cancle_element:
                change_city_cancle_element.click()

extra_job = ExtraJob(dangdang.driver)
extra_job.start()

接下来就是点击搜索按钮,然后输入内容,执行点击搜索对话框。

 # 1.搜索框
search_element_pro = self.wait.until(
            EC.presence_of_element_located((By.ID, 'com.dangdang.buy2:id/index_search')))
search_element_pro.click()

search_input_element = self.wait.until(
            EC.presence_of_element_located((By.ID, 'com.dangdang.buy2:id/search_text_layout')))
search_input_element.set_text(KEY_WORD)

# 2.搜索对话框,开始检索
search_btn_element = self.wait.until(
            EC.element_to_be_clickable((By.ID, 'com.dangdang.buy2:id/search_btn_search')))
search_btn_element.click()

# 3.休眠3秒,保证第一页的内容加载完全
time.sleep(3)

待第一页的数据加载完全之后,可以一直向上滚动页面,直到数据全部被加载完全,数据会由 mitmproxy 自动保存到 MongoDB 数据库当中。

while True:
      str1 = self.driver.page_source
      self.driver.swipe(FLICK_START_X, FLICK_START_Y + FLICK_DISTANCE, FLICK_START_X, FLICK_START_X)
      time.sleep(1)
      str2 = self.driver.page_source
      if str1 == str2:
            print('停止滑动')
            # 停止线程
            extra_job.stop()
            break
      print('继续滑动'

04 结果

首先使用 mitmdump 开启请求监听的服务,然后执行爬取脚本。

App 会自动打开,执行一系列操作后,到达商品界面,然后自动滑动界面,通过 mitmproxy 自动把有用的数据保存到 MongoDB 数据库中。

image
image

本文首发于公众号「 AirPython 」,后台回复「 Appium 」即可获取完整代码。

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

推荐阅读更多精彩内容

  • 前文介绍的都是爬取web网页的内容,随着移动互联网的发展,有很多企业并没有提web网页端的服务,而是开发了app来...
    逆向与爬虫的故事阅读 6,727评论 2 34
  • 记录一下如何用python爬取app数据,本文以爬取抖音视频app为例。 编程工具:pycharm app抓包工具...
    叫我老村长阅读 2,962评论 0 9
  • 迎着朝霞 披着晚星 日复一日 年复一年 大树用年轮记录着春去秋来 我们用盛满回忆的过去丈量寒来暑往 时间一刻不停的...
    暮雨潇潇X阅读 176评论 0 1
  • 一直以来都是极度的怀疑论者,怀疑然后才有了理性,不断思辨从而得到真理。然而这其实是相信了怀疑。然而这世界上,感性才...
    友谊的哲学阅读 320评论 0 1
  • 配置环境变量C:\Program Files\PostgreSQL\10\bin;C:\Program Files...
    _Xie_阅读 3,805评论 0 1