当前位置:   article > 正文

Python爬取当当网APP数据

python爬取当当网

目标

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

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

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

 

准备工作

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

  1. # 安装mitmproxy依赖包
  2. pip3 install mitmproxy
  3. # 安装pymongodb
  4. pip3 install pymongo

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

爬取思路

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

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

 

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

  1. class DangDangMongo(object):
  2.     """
  3.     初始化MongoDB数据库
  4.     """
  5.     def __init__(self):
  6.         self.client = MongoClient('localhost')
  7.         self.db = self.client['admin']
  8.         self.db.authenticate("root""xag")
  9.         self.dangdang_book_collection = self.db['dangdang_book']
  10. def response(flow):
  11.     # 过滤请求的URL
  12.     if 'keyword=Python' in request.url:
  13.         data = json.loads(response.text.encode('utf-8'))
  14.         # 书籍
  15.         products = data.get('products'or None
  16.         product_datas = []
  17.         for product in products:
  18.             # 书ID
  19.             product_id = product.get('id')
  20.             # 书名
  21.             product_name = product.get('name')
  22.             # 书价格
  23.             product_price = product.get('price')
  24.             # 作者
  25.             authorname = product.get('authorname')
  26.             # 出版社
  27.             publisher = product.get('publisher')
  28.             product_datas.append({
  29.                 'product_id': product_id,
  30.                 'product_name': product_name,
  31.                 'product_price': product_price,
  32.                 'authorname': authorname,
  33.                 'publisher': publisher
  34.             })
  35.         DangDangMongo().dangdang_book_collection.insert_many(product_datas)
  36.         print('成功插入数据成功')

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

 mitmdump -s script_dangdang.py 

 

 

2. 下面我们要利用 Appium 帮我们实现 自动化。

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

 

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

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

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

 

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

  1. self.caps = {
  2.             'automationName': DRIVER,
  3.             'platformName': PLATFORM,
  4.             'deviceName': DEVICE_NAME,
  5.             'appPackage': APP_PACKAGE,
  6.             'appActivity': APP_ACTIVITY,
  7.             'platformVersion': ANDROID_VERSION,
  8.             'autoGrantPermissions': AUTO_GRANT_PERMISSIONS,
  9.             'unicodeKeyboard'True,
  10.             'resetKeyboard'True
  11.         }
  12. self.driver = webdriver.Remote(DRIVER_SERVER, self.caps)

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

 

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

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

  1. class ExtraJob(threading.Thread):
  2.    def run(self):
  3.         while self.__running.isSet():
  4.             # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回
  5.             self.__flag.wait()
  6.             # 1.0 【红包雨】对话框
  7.             red_packet_element = is_element_exist(self.driver, 'com.dangdang.buy2:id/close')
  8.             if red_packet_element:
  9.                 red_packet_element.click()
  10.             # 1.1 【新人专享券】对话框
  11.             new_welcome_page_sure_element = is_element_exist(self.driver, 'com.dangdang.buy2:id/dialog_cancel_tv')
  12.             if new_welcome_page_sure_element:
  13.                 new_welcome_page_sure_element.click()
  14.             # 1.2 【切换位置】对话框
  15.             change_city_cancle_element = is_element_exist(self.driver, 'com.dangdang.buy2:id/left_bt')
  16.             if change_city_cancle_element:
  17.                 change_city_cancle_element.click()
  18. extra_job = ExtraJob(dangdang.driver)
  19. extra_job.start()

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

  1.  # 1.搜索框
  2. search_element_pro = self.wait.until(
  3.             EC.presence_of_element_located((By.ID, 'com.dangdang.buy2:id/index_search')))
  4. search_element_pro.click()
  5. search_input_element = self.wait.until(
  6.             EC.presence_of_element_located((By.ID, 'com.dangdang.buy2:id/search_text_layout')))
  7. search_input_element.set_text(KEY_WORD)
  8. 2.搜索对话框,开始检索
  9. search_btn_element = self.wait.until(
  10.             EC.element_to_be_clickable((By.ID, 'com.dangdang.buy2:id/search_btn_search')))
  11. search_btn_element.click()
  12. # 3.休眠3秒,保证第一页的内容加载完全
  13. time.sleep(3)

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

  1. while True:
  2.       str1 = self.driver.page_source
  3.       self.driver.swipe(FLICK_START_X, FLICK_START_Y + FLICK_DISTANCE, FLICK_START_X, FLICK_START_X)
  4.       time.sleep(1)
  5.       str2 = self.driver.page_source
  6.       if str1 == str2:
  7.             print('停止滑动')
  8.             # 停止线程
  9.             extra_job.stop()
  10.             break
  11.       print('继续滑动'

结果

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

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

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/897117
推荐阅读
相关标签
  

闽ICP备14008679号