您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關使用代理爬取微信公眾號文章的方法的內容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。
前面講解了代理池的維護和付費代理的相關使用方法,接下來我們進行一下實戰(zhàn)演練,利用代理來爬取微信公眾號的文章。
1. 本節(jié)目標
我們的主要目標是利用代理爬取微信公眾號的文章,提取正文、發(fā)表日期、公眾號等內容,爬取來源是搜狗微信,其鏈接為 http://weixin.sogou.com/,然后把爬取結果保存到 MySQL 數據庫。
2. 準備工作
首先需要準備并正常運行前文中所介紹的代理池。這里需要用的 Python 庫有 aiohttp、requests、redis-py、pyquery、Flask、PyMySQL,如這些庫沒有安裝可以參考第 1 章的安裝說明。
3. 爬取分析
搜狗對微信公眾平臺的公眾號和文章做了整合。我們可以通過上面的鏈接搜索到相關的公眾號和文章,例如搜索 NBA,可以搜索到最新的文章,如圖 9-21 所示。
圖 9-21 搜索結果
點擊搜索后,搜索結果的 URL 中其實有很多無關 GET 請求參數,將無關的參數去掉,只保留 type 和 query 參數,例如 http://weixin.sogou.com/weixin?type=2&query=NBA,搜索關鍵詞為 NBA,類型為 2,2 代表搜索微信文章。
下拉網頁,點擊下一頁即可翻頁,如圖 9-22 所示。
圖 9-22 翻頁列表
注意,如果沒有輸入賬號登錄,那只能看到 10 頁的內容,登錄之后可以看到 100 頁內容,如圖 9-23 和圖 9-24 所示。
圖 9-23 不登錄的結果
圖 9-24 登錄后的結果
如果需要爬取更多內容,就需要登錄并使用 Cookies 來爬取。
搜狗微信站點的反爬蟲能力很強,如連續(xù)刷新,站點就會彈出類似如圖 9-25 所示的驗證。
圖 9-25 驗證碼頁面
網絡請求出現了 302 跳轉,返回狀態(tài)碼為 302,跳轉的鏈接開頭為 http://weixin.sogou.com/antispider/,這很明顯就是一個反爬蟲的驗證頁面。所以我們得出結論,如果服務器返回狀態(tài)碼為 302 而非 200,則 IP 訪問次數太高,IP 被封禁,此請求就是失敗了。
如果遇到這種情況,我們可以選擇識別驗證碼并解封,也可以使用代理直接切換 IP。在這里我們采用第二種方法,使用代理直接跳過這個驗證。代理使用上一節(jié)所講的代理池,還需要更改檢測的 URL 為搜狗微信的站點。
對于這種反爬能力很強的網站來說,如果我們遇到此種返回狀態(tài)就需要重試。所以我們采用另一種爬取方式,借助數據庫構造一個爬取隊列,待爬取的請求都放到隊列里,如果請求失敗了重新放回隊列,就會被重新調度爬取。
在這里我們可以采用 Redis 的隊列數據結構,新的請求就加入隊列,或者有需要重試的請求也放回隊列。調度的時候如果隊列不為空,那就把一個個請求取出來執(zhí)行,得到響應后再進行解析,提取出我們想要的結果。
這次我們采用 MySQL 存儲,借助 PyMySQL 庫,將爬取結果構造為一個字典,實現動態(tài)存儲。
綜上所述,我們本節(jié)實現的功能有如下幾點。
修改代理池檢測鏈接為搜狗微信站點
構造 Redis 爬取隊列,用隊列實現請求的存取
實現異常處理,失敗的請求重新加入隊列
實現翻頁和提取文章列表并把對應請求加入隊列
實現微信文章的信息的提取
將提取到的信息保存到 MySQL
好,那么接下來我們就用代碼來實現一下。
4. 構造 Request
既然我們要用隊列來存儲請求,那么肯定要實現一個請求 Request 的數據結構,這個請求需要包含一些必要信息,如請求鏈接、請求頭、請求方式、超時時間。另外對于某個請求,我們需要實現對應的方法來處理它的響應,所以需要再加一個 Callback 回調函數。每次翻頁請求需要代理來實現,所以還需要一個參數 NeedProxy。如果一個請求失敗次數太多,那就不再重新請求了,所以還需要加失敗次數的記錄。
這些字段都需要作為 Request 的一部分,組成一個完整的 Request 對象放入隊列去調度,這樣從隊列獲取出來的時候直接執(zhí)行這個 Request 對象就好了。
我們可以采用繼承 reqeusts 庫中的 Request 對象的方式來實現這個數據結構。requests 庫中已經有了 Request 對象,它將請求 Request 作為一個整體對象去執(zhí)行,得到響應后再返回。其實 requests 庫的 get()、post() 等方法都是通過執(zhí)行 Request 對象實現的。
我們首先看看 Request 對象的源碼:
class Request(RequestHooksMixin): def __init__(self, method=None, url=None, headers=None, files=None, data=None, params=None, auth=None, cookies=None, hooks=None, json=None): # Default empty dicts for dict params. data = [] if data is None else data files = [] if files is None else files headers = {} if headers is None else headers params = {} if params is None else params hooks = {} if hooks is None else hooks self.hooks = default_hooks() for (k, v) in list(hooks.items()): self.register_hook(event=k, hook=v) self.method = method self.url = url self.headers = headers self.files = files self.data = data self.json = json self.params = params self.auth = auth self.cookies = cookies
這是 requests 庫中 Request 對象的構造方法。這個 Request 已經包含了請求方式、請求鏈接、請求頭這幾個屬性,但是相比我們需要的還差了幾個。我們需要實現一個特定的數據結構,在原先基礎上加入上文所提到的額外幾個屬性。這里我們需要繼承 Request 對象重新實現一個請求,將它定義為 WeixinRequest,實現如下:
TIMEOUT = 10 from requests import Request class WeixinRequest(Request): def __init__(self, url, callback, method='GET', headers=None, need_proxy=False, fail_time=0, timeout=TIMEOUT): Request.__init__(self, method, url, headers) self.callback = callback self.need_proxy = need_proxy self.fail_time = fail_time self.timeout = timeout
在這里我們實現了 WeixinRequest 數據結構。init() 方法先調用了 Request 的init() 方法,然后加入額外的幾個參數,定義為 callback、need_proxy、fail_time、timeout,分別代表回調函數、是否需要代理爬取、失敗次數、超時時間。
我們就可以將 WeixinRequest 作為一個整體來執(zhí)行,一個個 WeixinRequest 對象都是獨立的,每個請求都有自己的屬性。例如,我們可以調用它的 callback,就可以知道這個請求的響應應該用什么方法來處理,調用 fail_time 就可以知道這個請求失敗了多少次,判斷失敗次數是不是到了閾值,該不該丟棄這個請求。這里我們采用了面向對象的一些思想。
5. 實現請求隊列
接下來我們就需要構造請求隊列,實現請求的存取。存取無非就是兩個操作,一個是放,一個是取,所以這里利用 Redis 的 rpush() 和 lpop() 方法即可。
另外還需要注意,存取不能直接存 Request 對象,Redis 里面存的是字符串。所以在存 Request 對象之前我們先把它序列化,取出來的時候再將其反序列化,這個過程可以利用 pickle 模塊實現。
from pickle import dumps, loads from request import WeixinRequest class RedisQueue(): def __init__(self): """初始化 Redis""" self.db = StrictRedis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD) def add(self, request): """ 向隊列添加序列化后的 Request :param request: 請求對象 :param fail_time: 失敗次數 :return: 添加結果 """ if isinstance(request, WeixinRequest): return self.db.rpush(REDIS_KEY, dumps(request)) return False def pop(self): """ 取出下一個 Request 并反序列化 :return: Request or None """ if self.db.llen(REDIS_KEY): return loads(self.db.lpop(REDIS_KEY)) else: return False def empty(self): return self.db.llen(REDIS_KEY) == 0
這里實現了一個 RedisQueue,它的 __init__() 構造方法里面初始化了一個 StrictRedis 對象。隨后實現了 add() 方法,首先判斷 Request 的類型,如果是 WeixinRequest,那么就把程序就會用 pickle 的 dumps() 方法序列化,然后再調用 rpush() 方法加入隊列。pop() 方法則相反,調用 lpop() 方法將請求從隊列取出,然后再用 pickle 的 loads() 方法將其轉為 WeixinRequest 對象。另外,empty() 方法返回隊列是否為空,只需要判斷隊列長度是否為 0 即可。
在調度的時候,我們只需要新建一個 RedisQueue 對象,然后調用 add() 方法,傳入 WeixinRequest 對象,即可將 WeixinRequest 加入隊列,調用 pop() 方法,即可取出下一個 WeixinRequest 對象,非常簡單易用。
6. 修改代理池
接下來我們要生成請求并開始爬取。在此之前還需要做一件事,那就是先找一些可用代理。
之前代理池檢測的 URL 并不是搜狗微信站點,所以我們需要將代理池檢測的 URL 修改成搜狗微信站點,以便于把被搜狗微信站點封禁的代理剔除掉,留下可用代理。
現在將代理池的設置文件中的 TEST_URL 修改一下,如 http://weixin.sogou.com/weixin?type=2&
query=nba,被本站點封的代理就會減分,正常請求的代理就會賦值為 100,最后留下的就是可用代理。
修改之后將獲取模塊、檢測模塊、接口模塊的開關都設置為 True,讓代理池運行一會,如圖 9-26 所示。
圖 9-26 代理池運行結果
這樣,數據庫中留下的 100 分的代理就是針對搜狗微信的可用代理了,如圖 9-27 所示。
圖 9-27 可用代理列表
同時訪問代理接口,接口設置為 5555,訪問 http://127.0.0.1:5555/random,即可獲取到隨機可用代理,如圖 9-28 所示。
圖 9-28 代理接口
再定義一個函數來獲取隨機代理:
PROXY_POOL_URL = 'http://127.0.0.1:5555/random' def get_proxy(self): """ 從代理池獲取代理 :return: """ try: response = requests.get(PROXY_POOL_URL) if response.status_code == 200: print('Get Proxy', response.text) return response.text return None except requests.ConnectionError: return None
7. 第一個請求
一切準備工作都做好,下面我們就可以構造第一個請求放到隊列里以供調度了。定義一個 Spider 類,實現 start() 方法的代碼如下:
from requests import Session from db import RedisQueue from request import WeixinRequest from urllib.parse import urlencode class Spider(): base_url = 'http://weixin.sogou.com/weixin' keyword = 'NBA' headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4,zh-TW;q=0.2,mt;q=0.2', 'Cache-Control': 'max-age=0', 'Connection': 'keep-alive', 'Cookie': 'IPLOC=CN1100; SUID=6FEDCF3C541C940A000000005968CF55; SUV=1500041046435211; ABTEST=0|1500041 048|v1; SNUID=CEA85AE02A2F7E6EAFF9C1FE2ABEBE6F; weixinIndexVisited=1; JSESSIONID=aaar_m7LEIW-jg_gikPZv; ld=Wkllllllll2BzGMVlllllVOo8cUlllll5G@HbZllll9lllllRklll5@@@@@@@@@@', 'Host': 'weixin.sogou.com', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36' } session = Session() queue = RedisQueue() def start(self): """初始化工作""" # 全局更新 Headers self.session.headers.update(self.headers) start_url = self.base_url + '?' + urlencode({'query': self.keyword, 'type': 2}) weixin_request = WeixinRequest(url=start_url, callback=self.parse_index, need_proxy=True) # 調度第一個請求 self.queue.add(weixin_request)
這里定義了 Spider 類,設置了很多全局變量,比如 keyword 設置為 NBA,headers 就是請求頭。在瀏覽器里登錄賬號,然后在開發(fā)者工具里將請求頭復制出來,記得帶上 Cookie 字段,這樣才能爬取 100 頁的內容。然后初始化了 Session 和 RedisQueue 對象,它們分別用來執(zhí)行請求和存儲請求。
首先,start() 方法全局更新了 headers,使得所有請求都能應用 Cookies。然后構造了一個起始 URL:http://weixin.sogou.com/weixin?type=2&query=NBA,隨后用改 URL 構造了一個 WeixinRequest 對象。回調函數是 Spider 類的 parse_index() 方法,也就是當這個請求成功之后就用 parse_index() 來處理和解析。need_proxy 參數設置為 True,代表執(zhí)行這個請求需要用到代理。隨后我們調用了 RedisQueue 的 add() 方法,將這個請求加入隊列,等待調度。
8. 調度請求
加入第一個請求之后,調度開始了。我們首先從隊列中取出這個請求,將它的結果解析出來,生成新的請求加入隊列,然后拿出新的請求,將結果解析,再生成新的請求加入隊列,這樣循環(huán)往復執(zhí)行,直到隊列中沒有請求,則代表爬取結束。我們用代碼實現如下:
VALID_STATUSES = [200] def schedule(self): """ 調度請求 :return: """ while not self.queue.empty(): weixin_request = self.queue.pop() callback = weixin_request.callback print('Schedule', weixin_request.url) response = self.request(weixin_request) if response and response.status_code in VALID_STATUSES: results = list(callback(response)) if results: for result in results: print('New Result', result) if isinstance(result, WeixinRequest): self.queue.add(result) if isinstance(result, dict): self.mysql.insert('articles', result) else: self.error(weixin_request) else: self.error(weixin_request)
在這里實現了一個 schedule() 方法,其內部是一個循環(huán),循環(huán)的判斷是隊列不為空。
當隊列不為空時,調用 pop() 方法取出下一個請求,調用 request() 方法執(zhí)行這個請求,request() 方法的實現如下:
from requests import ReadTimeout, ConnectionError def request(self, weixin_request): """ 執(zhí)行請求 :param weixin_request: 請求 :return: 響應 """ try: if weixin_request.need_proxy: proxy = get_proxy() if proxy: proxies = { 'http': 'http://' + proxy, 'https': 'https://' + proxy } return self.session.send(weixin_request.prepare(), timeout=weixin_request.timeout, allow_redirects=False, proxies=proxies) return self.session.send(weixin_request.prepare(), timeout=weixin_request.timeout, allow_redirects=False) except (ConnectionError, ReadTimeout) as e: print(e.args) return False
這里首先判斷這個請求是否需要代理,如果需要代理,則調用 get_proxy() 方法獲取代理,然后調用 Session 的 send() 方法執(zhí)行這個請求。這里的請求調用了 prepare() 方法轉化為 Prepared Request,具體的用法可以參考 http://docs.python-requests.org/en/master/user/advanced/#prepared-requests,同時設置 allow_redirects 為 False,timeout 是該請求的超時時間,最后響應返回。
執(zhí)行 request() 方法之后會得到兩種結果:一種是 False,即請求失敗,連接錯誤;另一種是 Response 對象,還需要判斷狀態(tài)碼,如果狀態(tài)碼合法,那么就進行解析,否則重新將請求加回隊列。
如果狀態(tài)碼合法,解析的時候就會調用 WeixinRequest 的回調函數進行解析。比如這里的回調函數是 parse_index(),其實現如下:
from pyquery import PyQuery as pq def parse_index(self, response): """ 解析索引頁 :param response: 響應 :return: 新的響應 """ doc = pq(response.text) items = doc('.news-box .news-list li .txt-box h4 a').items() for item in items: url = item.attr('href') weixin_request = WeixinRequest(url=url, callback=self.parse_detail) yield weixin_request next = doc('#sogou_next').attr('href') if next: url = self.base_url + str(next) weixin_request = WeixinRequest(url=url, callback=self.parse_index, need_proxy=True) yield weixin_request
此方法做了兩件事:一件事就是獲取本頁的所有微信文章鏈接,另一件事就是獲取下一頁的鏈接,再構造成 WeixinRequest 之后 yield 返回。
然后,schedule() 方法將返回的結果進行遍歷,利用 isinstance() 方法判斷返回結果,如果返回結果是 WeixinRequest,就將其重新加入隊列。
至此,第一次循環(huán)結束。
這時 while 循環(huán)會繼續(xù)執(zhí)行。隊列已經包含第一頁內容的文章詳情頁請求和下一頁的請求,所以第二次循環(huán)得到的下一個請求就是文章詳情頁的請求,程序重新調用 request() 方法獲取其響應,然后調用其對應的回調函數解析。這時詳情頁請求的回調方法就不同了,這次是 parse_detail() 方法,此方法實現如下:
def parse_detail(self, response): """ 解析詳情頁 :param response: 響應 :return: 微信公眾號文章 """ doc = pq(response.text) data = {'title': doc('.rich_media_title').text(), 'content': doc('.rich_media_content').text(), 'date': doc('#post-date').text(), 'nickname': doc('#js_profile_qrcode> div > strong').text(), 'wechat': doc('#js_profile_qrcode> div > p:nth-child(3) > span').text()} yield data
這個方法解析了微信文章詳情頁的內容,提取出它的標題、正文文本、發(fā)布日期、發(fā)布人昵稱、微信公眾號名稱,將這些信息組合成一個字典返回。
結果返回之后還需要判斷類型,如是字典類型,程序就調用 mysql 對象的 insert() 方法將數據存入數據庫。
這樣,第二次循環(huán)執(zhí)行完畢。
第三次循環(huán)、第四次循環(huán),循環(huán)往復,每個請求都有各自的回調函數,索引頁解析完畢之后會繼續(xù)生成后續(xù)請求,詳情頁解析完畢之后會返回結果以便存儲,直到爬取完畢。
現在,整個調度就完成了。
我們完善一下整個 Spider 代碼,實現如下:
from requests import Session from config import * from db import RedisQueue from mysql import MySQL from request import WeixinRequest from urllib.parse import urlencode import requests from pyquery import PyQuery as pq from requests import ReadTimeout, ConnectionError class Spider(): base_url = 'http://weixin.sogou.com/weixin' keyword = 'NBA' headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4,zh-TW;q=0.2,mt;q=0.2', 'Cache-Control': 'max-age=0', 'Connection': 'keep-alive', 'Cookie': 'IPLOC=CN1100; SUID=6FEDCF3C541C940A000000005968CF55; SUV=1500041046435211; ABTEST=0|150004 1048|v1; SNUID=CEA85AE02A2F7E6EAFF9C1FE2ABEBE6F; weixinIndexVisited=1; JSESSIONID=aaar_m7LEIW-jg_gikPZv; ld=Wkllllllll2BzGMVlllllVOo8cUlllll5G@HbZllll9lllllRklll5@@@@@@@@@@', 'Host': 'weixin.sogou.com', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36' } session = Session() queue = RedisQueue() mysql = MySQL() def get_proxy(self): """ 從代理池獲取代理 :return: """ try: response = requests.get(PROXY_POOL_URL) if response.status_code == 200: print('Get Proxy', response.text) return response.text return None except requests.ConnectionError: return None def start(self): """初始化工作""" # 全局更新 Headers self.session.headers.update(self.headers) start_url = self.base_url + '?' + urlencode({'query': self.keyword, 'type': 2}) weixin_request = WeixinRequest(url=start_url, callback=self.parse_index, need_proxy=True) # 調度第一個請求 self.queue.add(weixin_request) def parse_index(self, response): """ 解析索引頁 :param response: 響應 :return: 新的響應 """ doc = pq(response.text) items = doc('.news-box .news-list li .txt-box h4 a').items() for item in items: url = item.attr('href') weixin_request = WeixinRequest(url=url, callback=self.parse_detail) yield weixin_request next = doc('#sogou_next').attr('href') if next: url = self.base_url + str(next) weixin_request = WeixinRequest(url=url, callback=self.parse_index, need_proxy=True) yield weixin_request def parse_detail(self, response): """ 解析詳情頁 :param response: 響應 :return: 微信公眾號文章 """ doc = pq(response.text) data = {'title': doc('.rich_media_title').text(), 'content': doc('.rich_media_content').text(), 'date': doc('#post-date').text(), 'nickname': doc('#js_profile_qrcode> div > strong').text(), 'wechat': doc('#js_profile_qrcode> div > p:nth-child(3) > span').text()} yield data def request(self, weixin_request): """ 執(zhí)行請求 :param weixin_request: 請求 :return: 響應 """ try: if weixin_request.need_proxy: proxy = self.get_proxy() if proxy: proxies = { 'http': 'http://' + proxy, 'https': 'https://' + proxy } return self.session.send(weixin_request.prepare(), timeout=weixin_request.timeout, allow_redirects =False, proxies=proxies) return self.session.send(weixin_request.prepare(), timeout=weixin_request.timeout, allow_redirects =False) except (ConnectionError, ReadTimeout) as e: print(e.args) return False def error(self, weixin_request): """ 錯誤處理 :param weixin_request: 請求 :return: """ weixin_request.fail_time = weixin_request.fail_time + 1 print('Request Failed', weixin_request.fail_time, 'Times', weixin_request.url) if weixin_request.fail_time < MAX_FAILED_TIME: self.queue.add(weixin_request) def schedule(self): """ 調度請求 :return: """ while not self.queue.empty(): weixin_request = self.queue.pop() callback = weixin_request.callback print('Schedule', weixin_request.url) response = self.request(weixin_request) if response and response.status_code in VALID_STATUSES: results = list(callback(response)) if results: for result in results: print('New Result', result) if isinstance(result, WeixinRequest): self.queue.add(result) if isinstance(result, dict): self.mysql.insert('articles', result) else: self.error(weixin_request) else: self.error(weixin_request) def run(self): """ 入口 :return: """ self.start() self.schedule() if __name__ == '__main__': spider = Spider() spider.run()
最后,我們加了一個 run() 方法作為入口,啟動的時候只需要執(zhí)行 Spider 的 run() 方法即可。
9. MySQL 存儲
整個調度模塊完成了,上面還沒提及到的就是存儲模塊,在這里還需要定義一個 MySQL 類供存儲數據,實現如下:
REDIS_HOST = 'localhost' REDIS_PORT = 6379 REDIS_PASSWORD = 'foobared' REDIS_KEY = 'weixin' import pymysql from config import * class MySQL(): def __init__(self, host=MYSQL_HOST, username=MYSQL_USER, password=MYSQL_PASSWORD, port=MYSQL_PORT, database=MYSQL_DATABASE): """ MySQL 初始化 :param host: :param username: :param password: :param port: :param database: """ try: self.db = pymysql.connect(host, username, password, database, charset='utf8', port=port) self.cursor = self.db.cursor() except pymysql.MySQLError as e: print(e.args) def insert(self, table, data): """ 插入數據 :param table: :param data: :return: """ keys = ', '.join(data.keys()) values = ', '.join(['% s'] * len(data)) sql_query = 'insert into % s (% s) values (% s)' % (table, keys, values) try: self.cursor.execute(sql_query, tuple(data.values())) self.db.commit() except pymysql.MySQLError as e: print(e.args) self.db.rollback()
__init__() 方法初始化了 MySQL 連接,需要 MySQL 的用戶、密碼、端口、數據庫名等信息。數據庫名為 weixin,需要自己創(chuàng)建。
insert() 方法傳入表名和字典即可動態(tài)構造 SQL,在 5.2 節(jié)中也有講到,SQL 構造之后執(zhí)行即可插入數據。
我們還需要提前建立一個數據表,表名為 articles,建表的 SQL 語句如下:
CREATE TABLE `articles` (`id` int(11) NOT NULL, `title` varchar(255) NOT NULL, `content` text NOT NULL, `date` varchar(255) NOT NULL, `wechat` varchar(255) NOT NULL, `nickname` varchar(255) NOT NULL ) DEFAULT CHARSET=utf8; ALTER TABLE `articles` ADD PRIMARY KEY (`id`);
現在,我們的整個爬蟲就算完成了。
10. 運行
示例運行結果如圖 9-29 所示:
圖 9-29 運行結果
程序首先調度了第一頁結果對應的請求,獲取了代理執(zhí)行此請求,隨后得到了 11 個新請求,請求都是 WeixinRequest 類型,將其再加入隊列。隨后繼續(xù)調度新加入的請求,也就是文章詳情頁對應的請求,再執(zhí)行,得到的就是文章詳情對應的提取結果,提取結果是字典類型。
程序循環(huán)往復,不斷爬取,直至所有結果爬取完畢,程序終止,爬取完成。
爬取結果如圖 9-30 所示。
圖 9-30 爬取結果
我們可以看到,相關微信文章都已被存儲到數據庫里了。
感謝各位的閱讀!關于使用代理爬取微信公眾號文章的方法就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。