Python爬蟲實踐:如何優雅地刪除豆瓣小組的帖子

前言

文章起源于自己的一個需求:想要刪除掉自己的若干個小號在豆瓣小組上的發帖及回復記錄。這是一件看似簡單的事情,但是一遍一遍的重復操作實在讓我感到非常絕望,特別是刪除自己的回復時,有時候回復的帖子的回復有好幾十頁,得一頁一頁的翻。于是就想到用腳本來代替人力操作。對于一名職業為前端工程師的人而言,最容易想到的方法就是打開DevTools發個Ajax請求直接搞定了。不過經歷過幾次之后發現這種方法很難沉淀下來,于是就想能不能寫到腳本里面。一開始依舊想到的是用NodeJS來實現,但是由于最近由于接觸程序化交易比較多,發現如果再不溫習一下Python大蟒蛇又要忘光了,于是就想借機同時練練Python。

結果

先說結果

安裝

兩種方式:

  1. 源代碼已放到github,可自行查看下載:https://github.com/acrazing/dbapi
git clone https://github.com/acrazing/dbapi.git
cd dbapi
# 安裝依賴
pip install -r requirements.txt
  1. 包已發布到pip,可自行安裝:
pip install dbapi

使用

首先得安裝,然后:

  1. 登錄客戶端:因為客戶端有緩存Session,所以你只需要登錄一次,在命令行中:
    python -m dbapi.DoubanAPI test_client login "username" "password"
    
  2. 刪除自己回復過的帖子:因為要刪除自己發的帖子實際上是要刪除掉所有自己在帖子下的回復,如果回復非常多不知道自己回復的在哪一頁或者自己的回復非常多,操作起來會比較惡心
    python -m dbapi.DoubanAPI test_api remove_commented_topic "topic_id"
    # topic_id 可以通過下面這個命令拿到:
    python -m dbapi.DoubanAPI test_api list_commented_topics
    # 這個命令會返回所有自己回復過的帖子
    
  3. 刪除自己發的帖子:因為要先刪除所有的回復,所以也很惡心
    python -m dbapi.DoubanAPI test_api remove_topic "topic_id"
    # topic_id 可以通過下面這個命令拿到:
    python -m dbapi.DoubanAPI test_api list_user_topics
    # 這個命令會返回所有自己發布的帖子
    

需求分析

  1. 首先需求很明確:快速刪除掉在豆瓣小組內的發帖和回復記錄
  2. 要訪問自己的豆瓣小組,需要登錄帳號獲取會話信息,其中一個關鍵的信息會話IDdbcl2設置了HttpOnly,此外還需要一個動態idck。當然這些問題都可以通過把所有的Cookie添加到客戶端搞定。
  3. 要刪除發帖記錄,需要先刪除掉貼子下的所有回復,在刪除別人的回復時,需要調用管理員權限并提交理由
  4. 要刪除掉回復記錄,需要刪除掉所有的自己的回復,但是別人的引用是無法刪除的,所以最后要真正隱藏掉記錄,需要注銷帳號。
  5. 登錄是敏感操作,頻繁登錄很容易觸發機器人,需要緩存會話信息
  6. 訪問頻率過高也會觸發機器人,需要做訪問限制

接口列表

通過瀏覽器抓包發現,相關操作主要有幾下幾個接口:

  • 登錄賬號:POST https://www.douban.com/accounts/login,登錄前需要先獲取bid等信息,登錄時如果不設置redir_url,會自動跳轉到豆瓣首頁,如果登錄失敗,則不會跳轉,可以據此判斷登錄是否成功,或者也可以用Cookie信息進行判斷。跳轉完成后會拿到所有會話所需要的Cookie信息,所以需要跟蹤跳轉
  • 登出賬號:GET https://www.douban.com/accounts/logout?source=group&ck=%s,這里的ck就是會話中的ck
  • 獲取自己發的帖子列表:GET https://www.douban.com/group/people/%s/publish,有翻頁
  • 獲取自己回復過的帖子列表:GET https://www.douban.com/group/people/%s/reply,有翻頁
  • 刪除自己的回復:POST https://www.douban.com/j/group/topic/%s/remove_comment
  • 刪除自己發的帖子下的別人的回復:POST https://www.douban.com/group/topic/%s/remove_comment

此外還有一些已實現但是與此無關的接口,可以到代碼中dbapi/endpoints.py中查看

接口設計

  • 為了方便擴展,封裝了一層基礎的API SDK:只是對單個頁面進行請求及信息提取,所有的其它上層操作都基于這個SDK,比如刪除發帖記錄等
  • 為了方便擴展,對接口進行了模塊化處理:比如豆瓣小組Group,用戶People等模塊等
  • 為了方便調用,封裝了一個統一的出口類DoubanAPI,對會話緩存,登錄登出等操作進行統一管理,并引入了各個模塊
  • 對于每個網絡請求,需要用到公共頭及會話信息,所以封裝了一個基類BaseAPI統一網絡請求,并且返回數據有可能是html或者json,所以提供了三個相關接口,同時部分接口需要顯式調用ck,所以提供了相關接口

依賴

  • 網絡請求由requests實現
  • 大部分read接口返回的數據都是html格式,這里使用lxmlxpath進行讀取
  • 使用logging輸出日志

代碼分析

略,請參考源代碼

其它

除了小組相關API外,還實現了用戶People相關的部分API,可以實現獲取用戶profile,關注用戶及關注者,代碼在dbapi/People.py中。利用這幾個API設計了一個多線程爬蟲,用來爬取豆瓣上的熱門用戶,代碼在test/relation.py中,爬取的結果放在__relation__.json中。目前我注冊了4個豆瓣賬號,開了4個線程進行爬取。最開始由一個種子用戶sevear,爬取其關注的用戶中關注者大于100的用戶,然后逐漸將關注者最小值加到現在的10000。目前已發布到Github的結果中,已經爬取了33599個用戶,其中1069個用戶的關注者超過了10000。發現了一些比較有趣用戶,比如熊阿姨等;也發現熱門的用戶大多都會貼上自己的微信公眾號,微博等信息;還有很多從05年就開始使用豆瓣的重度用戶,也有很多注銷了的賬號。雖然我也很多年前就注冊了豆瓣,但是一直沒有發現除了發租房貼,看電影評價,聽FM(現在已經不用了)之外還有什么其它價值。也許這些人可以給我答案。

總結

  • 因為之前對Python的了解僅限于語法層面,未接觸過相應的生態,比如pip包管理,setuptools等,并且不熟悉相關的基礎包。所以幾乎得從零開始,是件很頭疼的事情,所幸的是Python的包都比較有名氣,包管理等網絡上也有很多教程,查找起來都比較容易。感謝互聯網~
  • 通過test/relation.py測試發現,目前存在內存泄漏問題,但是搗鼓了半天沒有查到問題所在,已經沒有興趣繼續花時間了~
  • 同上,訪問頻率過高有可能會觸發IP封禁,出現Please try later以及檢測到你的IP有非正常請求發出balabala提示~
  • 同上,現在4個線程中每個請求之前間隔時間調整到了3秒,再也沒有出現IP封禁的提示~
  • 客戶端架構存在很大問題:比如無法動態更新會話信息,頻繁獲取模塊有額外的性能開銷等,需要重新設計整體架構,同樣已經沒有興趣了,等以后有心情再更新吧~
  • 分不清賬號帳號, 帖子貼子,求語文老師
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容