摘要:目標使用代理反爬抓取微信文章,獲取文章標題內(nèi)容公眾號等信息,并存儲到數(shù)據(jù)庫中。代理設置在使用維護動態(tài)代理池一文中,我們講解了代理池的基本原理和簡單實現(xiàn),代碼已托管到上,現(xiàn)在讓我們利用代理池來獲取隨機代理。
目標
使用代理反爬抓取微信文章,獲取文章標題、內(nèi)容、公眾號等信息,并存儲到MongoDB數(shù)據(jù)庫中。
流程框架如果要抓取微信公眾號文章可以使用搜狗的搜索引擎,它會顯示最新的文章,但是有兩個問題需要大家注意:
如果要抓取某一個主題(比如微信風景文章)的所有記錄的話,需要先登錄(也就是你的請求頭headers中要有登陸之后服務器返回的cookies),未登錄只可以查看10頁,登錄之后可以查看100頁
搜狗微信站點的反爬措施比較嚴格,如果只是用本地IP(單IP)去抓取的話肯定是不行的,這個時候我們需要用到代理池技術(shù)(通過可用隨機代理去繞過反爬機制)
關(guān)于代理池的實現(xiàn)以及使用可以參考這篇文章:使用Redis+Flask維護動態(tài)代理池
下圖展示了具體的流程框架:
def parse_index(html): doc = pq(html) items = doc(".news-box .news-list li .txt-box h3 a").items() for item in items: yield item.attr("href")def parse_index(html): doc = pq(html) items = doc(".news-box .news-list li .txt-box h3 a").items() for item in items: yield item.attr("href")
在流程框架部分我們提到,在此將要使用搜狗搜索微信站點文章,首先讓我們進入搜狗搜索界面https://weixin.sogou.com/,比如輸入關(guān)鍵字風景,就會出現(xiàn)微信文章的列表。
從網(wǎng)頁的url可以看出這是一個get請求,只保留主要參數(shù),可以把url簡化為
其中,“query”代表搜索的關(guān)鍵詞,“type”代表搜索結(jié)果的類型,“type=1”表示搜索結(jié)果是微信公眾號,“type=2”表示搜索結(jié)果是微信文章,“page”也就是當前頁數(shù)。
分析完網(wǎng)頁的url組成之后,我們先解決第一個問題:保存cookie,模擬登錄。
打開瀏覽器控制臺,選擇NetWork->Headers選項卡,可以看到請求的headers信息。
解決完以上問題之后,讓我們嘗試寫一下代碼獲取第1-100頁的網(wǎng)頁源碼:
from urllib.parse import urlencode import requests base_url = "https://weixin.sogou.com/weixin?" # 構(gòu)造請求頭 headers = { "Cookie": "CXID=DF1F2AE56903B8B6289106D60E0C1339; SUID=F5959E3D8483920A000000005BCEB8CD; sw_uuid=3544458569; ssuid=8026096631; pex=C864C03270DED3DD8A06887A372DA219231FFAC25A9D64AE09E82AED12E416AC; SUV=00140F4F78C27EE25BF168CF5C981926; ad=p7R@vkllll2bio@ZlllllVsE@EclllllNBENLlllll9lllllpA7ll5@@@@@@@@@@; IPLOC=CN4110; ABTEST=2|1543456547|v1; weixinIndexVisited=1; sct=1; JSESSIONID=aaaXtNmDWRk5X5sEsy6Cw; PHPSESSID=lfgarg05due13kkgknnlbh3bq7; SUIR=EF72CF750D0876CFF631992E0D94BE34;", "Host": "weixin.sogou.com", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36" } def get_html(url, count=1): response = requests.get(url, allow_redirects=False, headers=headers) # 判斷網(wǎng)頁返回的狀態(tài)碼是否正常 # 如果狀態(tài)碼是200說明可以正常訪問 if response.status_code == 200: return response.text # 如果狀態(tài)碼是302,則說明IP已經(jīng)被封 if response.status_code == 302: return None def get_index(keyword, page): data = { "query": keyword, "type": 2, "page": page } queries = urlencode(data) url = base_url + queries html = get_html(url) return html def main(): for page in range(1, 101): html = get_index("風景", page) print(html) if __name__ == "__main__": main()
運行以上代碼,會發(fā)現(xiàn)剛開始運行正常,正確返回網(wǎng)頁源碼,之后便一直返回None,此時讓我們打開瀏覽器觀察一下:
可以看出,代碼運行后不停返回None的原因是網(wǎng)頁被重定向,需要輸入驗證碼才能正常訪問,這便是我們開篇說過的第二個問題,我們的訪問被搜狗搜索的反爬蟲措施攔截,如果想要繼續(xù)正常訪問,便需要利用代理池獲取隨機代理來繞過反爬機制。
(2)代理設置在使用Redis+Flask維護動態(tài)代理池一文中,我們講解了代理池的基本原理和簡單實現(xiàn),代碼已托管到github上,現(xiàn)在讓我們利用代理池來獲取隨機代理。
首先讓我們定義get_proxy()方法,返回代理池獲取的隨機可用ip:
# flask監(jiān)聽的是5000端口 PROXY_POOL_URL = "http://127.0.0.1:5000/get" def get_proxy(): try: response = requests.get(PROXY_POOL_URL) if response.status_code == 200: return response.text return None except ConnectionError: return None
接下來修改get_html(url, count=1)方法,以隨機ip的方式訪問網(wǎng)頁:
MAX_COUNT = 5 proxy = None def get_html(url, count=1): # 打印抓取的url print("Crawling", url) # 打印嘗試抓取的次數(shù) print("Trying Count", count) global proxy # 如果抓取的次數(shù)大于最大次數(shù),則返回None if count >= MAX_COUNT: print("Tried Too Many Counts") return None try: if proxy: proxies = { "http": "http://" + proxy } # allow_redirects=False:禁止瀏覽器自動處理302跳轉(zhuǎn) response = requests.get(url, allow_redirects=False, headers=headers, proxies=proxies) else: response = requests.get(url, allow_redirects=False, headers=headers) if response.status_code == 200: return response.text # 狀態(tài)碼是302,說明IP已經(jīng)被封,調(diào)用get_proxy()獲取新的ip if response.status_code == 302: # Need Proxy print("302") proxy = get_proxy() if proxy: print("Using Proxy", proxy) return get_html(url) else: print("Get Proxy Failed") return None except ConnectionError as e: # 如果連接超時,重新調(diào)用get_html(url, count)方法 print("Error Occurred", e.args) proxy = get_proxy() count += 1 return get_html(url, count)
再次運行代碼,會發(fā)現(xiàn)不停重復打印None的情況基本消失。大家注意,這里是基本消失,原因是我們的代理池使用的是免費代理網(wǎng)站獲取的代理,同一時刻可能會有許多人訪問,這樣就很容易造成ip地址被封的情況。如果你想要獲取更好的效果,不妨使用一下收費代理。
至此,我們解決了開篇提到的兩個問題,接下來,就可以抓取網(wǎng)頁,分析內(nèi)容。
(3)分析詳情頁內(nèi)容首先我們需要獲取到第1-100頁中每一篇文章的url:
def parse_index(html): doc = pq(html) items = doc(".news-box .news-list li .txt-box h3 a").items() for item in items: yield item.attr("href") def main(): for page in range(1, 101): html = get_index(KEYWORD, page) if html: article_urls = parse_index(html) print(article_urls)
獲取到每一篇文章的url之后,就需要解析每一篇文章的內(nèi)容。解析方法與上面相同,在此不再贅述。具體代碼如下:
def parse_detail(html): try: doc = pq(html) title = doc(".rich_media_title").text() content = doc(".rich_media_content ").text() date = doc("#publish_time").text() nickname = doc(".rich_media_meta_list .rich_media_meta_nickname").text() wechat = doc("#activity-name").text() return { "title": title, "content": content, "date": date, "nickname": nickname, "wechat": wechat } except XMLSyntaxError: return None
需要注意的一點就是需要捕獲XMLSyntaxError異常。
(4)將數(shù)據(jù)保存到數(shù)據(jù)庫最后讓我們新建一個config.py文件,文件中包含了MongoDB的URL,數(shù)據(jù)庫名稱,表名稱等常量:
MONGO_URL = "localhost" MONGO_DB = "weixin"
在spider.py中配置存儲到MongoDB相關(guān)方法:
from config import * import pymongo client = pymongo.MongoClient(MONGO_URL) db = client[MONGO_DB] def save_to_mongo(data): if db["articles"].update({"title": data["title"]}, {"$set": data}, True): print("Saved to Mongo", data["title"]) else: print("Saved to Mongo Failed", data["title"])
運行代碼,接下來在MongoDB中進行查看:
項目完整代碼已托管到github:https://github.com/panjings/p...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/42845.html
摘要:時間永遠都過得那么快,一晃從年注冊,到現(xiàn)在已經(jīng)過去了年那些被我藏在收藏夾吃灰的文章,已經(jīng)太多了,是時候把他們整理一下了。那是因為收藏夾太亂,橡皮擦給設置私密了,不收拾不好看呀。 ...
摘要:近來知乎上如雨后春筍般冒出了大把大把的爬蟲教程。一個爬蟲教程的案例三個月之后還能有效已經(jīng)是萬幸了。不過仍然要說明,即使經(jīng)過多次驗證,也無法保證一個的絕對可用性。這是個概率問題,工具的作用只是盡可能提高概率。 近來知乎上如雨后春筍般冒出了大把大把的爬蟲教程。這是好事,學了 Python 基礎的同學們可以很輕松地搜出許多練手的例子。不過我不是針對誰,我是說網(wǎng)上絕大多數(shù)的爬蟲教程,其實都缺乏...
摘要:以下這些項目,你拿來學習學習練練手。當你每個步驟都能做到很優(yōu)秀的時候,你應該考慮如何組合這四個步驟,使你的爬蟲達到效率最高,也就是所謂的爬蟲策略問題,爬蟲策略學習不是一朝一夕的事情,建議多看看一些比較優(yōu)秀的爬蟲的設計方案,比如說。 (一)如何學習Python 學習Python大致可以分為以下幾個階段: 1.剛上手的時候肯定是先過一遍Python最基本的知識,比如說:變量、數(shù)據(jù)結(jié)構(gòu)、語法...
摘要:極簡爬蟲攻防戰(zhàn)紀要爬蟲是構(gòu)建搜索引擎的基礎負責抓取網(wǎng)頁信息并對網(wǎng)頁識別分類及過濾。爬蟲方終于鎖定了第一場戰(zhàn)役的勝局由于斷崖式技術(shù)的出現(xiàn),反爬方在瀏覽器識別戰(zhàn)役上望風披靡。經(jīng)過反爬方的精心運作,逐漸有效削弱了敵方的攻勢。 極簡爬蟲攻防戰(zhàn)紀要 ? ??爬蟲是構(gòu)建搜索引擎的基礎, 負責抓取網(wǎng)頁信息并對網(wǎng)頁識別、分類及過濾。我們熟識的電商、搜索、新聞及各大門戶網(wǎng)站都有強大的爬蟲集群在每...
摘要:注一篇去年的舊文,發(fā)現(xiàn)沒在知乎發(fā)過,過來補個檔。于是就有了我們這個小項目電影票比價網(wǎng)在我們這個網(wǎng)頁上,會展示出當前熱映的電影。涉及到模塊主要是用來匹配不同渠道的影院信息代碼結(jié)構(gòu)項目主要有三塊使用豆瓣每日更新上映的影片列表。 注:一篇去年的舊文,發(fā)現(xiàn)沒在知乎發(fā)過,過來補個檔。有個小問題是項目中淘票票的網(wǎng)頁反爬提升且變動較多,目前暫不可用了。 時常有同學會問我類似的問題:我已經(jīng)學完了 Py...
閱讀 1402·2021-11-08 13:14
閱讀 758·2021-09-23 11:31
閱讀 1048·2021-07-29 13:48
閱讀 2787·2019-08-29 12:29
閱讀 3383·2019-08-29 11:24
閱讀 1908·2019-08-26 12:02
閱讀 3698·2019-08-26 10:34
閱讀 3444·2019-08-23 17:07