成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

使用代理處理反爬抓取微信文章

QiShare / 611人閱讀

摘要:目標(biāo)使用代理反爬抓取微信文章,獲取文章標(biāo)題內(nèi)容公眾號(hào)等信息,并存儲(chǔ)到數(shù)據(jù)庫(kù)中。代理設(shè)置在使用維護(hù)動(dòng)態(tài)代理池一文中,我們講解了代理池的基本原理和簡(jiǎn)單實(shí)現(xiàn),代碼已托管到上,現(xiàn)在讓我們利用代理池來(lái)獲取隨機(jī)代理。

目標(biāo)

使用代理反爬抓取微信文章,獲取文章標(biāo)題、內(nèi)容、公眾號(hào)等信息,并存儲(chǔ)到MongoDB數(shù)據(jù)庫(kù)中。

流程框架

如果要抓取微信公眾號(hào)文章可以使用搜狗的搜索引擎,它會(huì)顯示最新的文章,但是有兩個(gè)問(wèn)題需要大家注意:

如果要抓取某一個(gè)主題(比如微信風(fēng)景文章)的所有記錄的話,需要先登錄(也就是你的請(qǐng)求頭headers中要有登陸之后服務(wù)器返回的cookies),未登錄只可以查看10頁(yè),登錄之后可以查看100頁(yè)

搜狗微信站點(diǎn)的反爬措施比較嚴(yán)格,如果只是用本地IP(單IP)去抓取的話肯定是不行的,這個(gè)時(shí)候我們需要用到代理池技術(shù)(通過(guò)可用隨機(jī)代理去繞過(guò)反爬機(jī)制)

關(guān)于代理池的實(shí)現(xiàn)以及使用可以參考這篇文章:使用Redis+Flask維護(hù)動(dòng)態(tài)代理池

下圖展示了具體的流程框架:

(1)抓取索引頁(yè)內(nè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")

在流程框架部分我們提到,在此將要使用搜狗搜索微信站點(diǎn)文章,首先讓我們進(jìn)入搜狗搜索界面https://weixin.sogou.com/,比如輸入關(guān)鍵字風(fēng)景,就會(huì)出現(xiàn)微信文章的列表。

從網(wǎng)頁(yè)的url可以看出這是一個(gè)get請(qǐng)求,只保留主要參數(shù),可以把url簡(jiǎn)化為

其中,“query”代表搜索的關(guān)鍵詞,“type”代表搜索結(jié)果的類型,“type=1”表示搜索結(jié)果是微信公眾號(hào),“type=2”表示搜索結(jié)果是微信文章,“page”也就是當(dāng)前頁(yè)數(shù)。

分析完網(wǎng)頁(yè)的url組成之后,我們先解決第一個(gè)問(wèn)題:保存cookie,模擬登錄。
打開(kāi)瀏覽器控制臺(tái),選擇NetWork->Headers選項(xiàng)卡,可以看到請(qǐng)求的headers信息。

解決完以上問(wèn)題之后,讓我們嘗試寫(xiě)一下代碼獲取第1-100頁(yè)的網(wǎng)頁(yè)源碼:

from urllib.parse import urlencode
import requests

base_url = "https://weixin.sogou.com/weixin?"

# 構(gòu)造請(qǐng)求頭
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)頁(yè)返回的狀態(tài)碼是否正常
    # 如果狀態(tài)碼是200說(shuō)明可以正常訪問(wèn)
    if response.status_code == 200:
        return response.text
    # 如果狀態(tài)碼是302,則說(shuō)明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("風(fēng)景", page)
        print(html)
        
if __name__ == "__main__":
    main()

運(yùn)行以上代碼,會(huì)發(fā)現(xiàn)剛開(kāi)始運(yùn)行正常,正確返回網(wǎng)頁(yè)源碼,之后便一直返回None,此時(shí)讓我們打開(kāi)瀏覽器觀察一下:

可以看出,代碼運(yùn)行后不停返回None的原因是網(wǎng)頁(yè)被重定向,需要輸入驗(yàn)證碼才能正常訪問(wèn),這便是我們開(kāi)篇說(shuō)過(guò)的第二個(gè)問(wèn)題,我們的訪問(wèn)被搜狗搜索的反爬蟲(chóng)措施攔截,如果想要繼續(xù)正常訪問(wèn),便需要利用代理池獲取隨機(jī)代理來(lái)繞過(guò)反爬機(jī)制。

(2)代理設(shè)置

在使用Redis+Flask維護(hù)動(dòng)態(tài)代理池一文中,我們講解了代理池的基本原理和簡(jiǎn)單實(shí)現(xiàn),代碼已托管到github上,現(xiàn)在讓我們利用代理池來(lái)獲取隨機(jī)代理。

首先讓我們定義get_proxy()方法,返回代理池獲取的隨機(jī)可用ip:

# flask監(jiān)聽(tīng)的是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

接下來(lái)修改get_html(url, count=1)方法,以隨機(jī)ip的方式訪問(wèn)網(wǎng)頁(yè):

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:禁止瀏覽器自動(dòng)處理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,說(shuō)明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:
            # 如果連接超時(shí),重新調(diào)用get_html(url, count)方法
        print("Error Occurred", e.args)
        proxy = get_proxy()
        count += 1
        return get_html(url, count)

再次運(yùn)行代碼,會(huì)發(fā)現(xiàn)不停重復(fù)打印None的情況基本消失。大家注意,這里是基本消失,原因是我們的代理池使用的是免費(fèi)代理網(wǎng)站獲取的代理,同一時(shí)刻可能會(huì)有許多人訪問(wèn),這樣就很容易造成ip地址被封的情況。如果你想要獲取更好的效果,不妨使用一下收費(fèi)代理。

至此,我們解決了開(kāi)篇提到的兩個(gè)問(wèn)題,接下來(lái),就可以抓取網(wǎng)頁(yè),分析內(nèi)容。

(3)分析詳情頁(yè)內(nèi)容

首先我們需要獲取到第1-100頁(yè)中每一篇文章的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

需要注意的一點(diǎn)就是需要捕獲XMLSyntaxError異常。

(4)將數(shù)據(jù)保存到數(shù)據(jù)庫(kù)

最后讓我們新建一個(gè)config.py文件,文件中包含了MongoDB的URL,數(shù)據(jù)庫(kù)名稱,表名稱等常量:

MONGO_URL = "localhost"
MONGO_DB = "weixin"

在spider.py中配置存儲(chǔ)到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"])

運(yùn)行代碼,接下來(lái)在MongoDB中進(jìn)行查看:

項(xiàng)目完整代碼已托管到github:https://github.com/panjings/p...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42845.html

相關(guān)文章

  • 首次公開(kāi),整理12年積累的博客收藏夾,零距離展示《收藏夾吃灰》系列博客

    摘要:時(shí)間永遠(yuǎn)都過(guò)得那么快,一晃從年注冊(cè),到現(xiàn)在已經(jīng)過(guò)去了年那些被我藏在收藏夾吃灰的文章,已經(jīng)太多了,是時(shí)候把他們整理一下了。那是因?yàn)槭詹貖A太亂,橡皮擦給設(shè)置私密了,不收拾不好看呀。 ...

    Harriet666 評(píng)論0 收藏0
  • 聽(tīng)說(shuō)你好不容易寫(xiě)了個(gè)爬蟲(chóng),結(jié)果沒(méi)抓幾個(gè)就被封了?(附工具)

    摘要:近來(lái)知乎上如雨后春筍般冒出了大把大把的爬蟲(chóng)教程。一個(gè)爬蟲(chóng)教程的案例三個(gè)月之后還能有效已經(jīng)是萬(wàn)幸了。不過(guò)仍然要說(shuō)明,即使經(jīng)過(guò)多次驗(yàn)證,也無(wú)法保證一個(gè)的絕對(duì)可用性。這是個(gè)概率問(wèn)題,工具的作用只是盡可能提高概率。 近來(lái)知乎上如雨后春筍般冒出了大把大把的爬蟲(chóng)教程。這是好事,學(xué)了 Python 基礎(chǔ)的同學(xué)們可以很輕松地搜出許多練手的例子。不過(guò)我不是針對(duì)誰(shuí),我是說(shuō)網(wǎng)上絕大多數(shù)的爬蟲(chóng)教程,其實(shí)都缺乏...

    Pluser 評(píng)論0 收藏0
  • Python爬蟲(chóng)學(xué)習(xí)路線

    摘要:以下這些項(xiàng)目,你拿來(lái)學(xué)習(xí)學(xué)習(xí)練練手。當(dāng)你每個(gè)步驟都能做到很優(yōu)秀的時(shí)候,你應(yīng)該考慮如何組合這四個(gè)步驟,使你的爬蟲(chóng)達(dá)到效率最高,也就是所謂的爬蟲(chóng)策略問(wèn)題,爬蟲(chóng)策略學(xué)習(xí)不是一朝一夕的事情,建議多看看一些比較優(yōu)秀的爬蟲(chóng)的設(shè)計(jì)方案,比如說(shuō)。 (一)如何學(xué)習(xí)Python 學(xué)習(xí)Python大致可以分為以下幾個(gè)階段: 1.剛上手的時(shí)候肯定是先過(guò)一遍Python最基本的知識(shí),比如說(shuō):變量、數(shù)據(jù)結(jié)構(gòu)、語(yǔ)法...

    liaoyg8023 評(píng)論0 收藏0
  • 極簡(jiǎn)爬蟲(chóng)攻防戰(zhàn)紀(jì)要

    摘要:極簡(jiǎn)爬蟲(chóng)攻防戰(zhàn)紀(jì)要爬蟲(chóng)是構(gòu)建搜索引擎的基礎(chǔ)負(fù)責(zé)抓取網(wǎng)頁(yè)信息并對(duì)網(wǎng)頁(yè)識(shí)別分類及過(guò)濾。爬蟲(chóng)方終于鎖定了第一場(chǎng)戰(zhàn)役的勝局由于斷崖式技術(shù)的出現(xiàn),反爬方在瀏覽器識(shí)別戰(zhàn)役上望風(fēng)披靡。經(jīng)過(guò)反爬方的精心運(yùn)作,逐漸有效削弱了敵方的攻勢(shì)。 極簡(jiǎn)爬蟲(chóng)攻防戰(zhàn)紀(jì)要 ? ??爬蟲(chóng)是構(gòu)建搜索引擎的基礎(chǔ), 負(fù)責(zé)抓取網(wǎng)頁(yè)信息并對(duì)網(wǎng)頁(yè)識(shí)別、分類及過(guò)濾。我們熟識(shí)的電商、搜索、新聞及各大門(mén)戶網(wǎng)站都有強(qiáng)大的爬蟲(chóng)集群在每...

    elliott_hu 評(píng)論0 收藏0
  • 爬蟲(chóng)+網(wǎng)站開(kāi)發(fā)實(shí)例:電影票比價(jià)網(wǎng)

    摘要:注一篇去年的舊文,發(fā)現(xiàn)沒(méi)在知乎發(fā)過(guò),過(guò)來(lái)補(bǔ)個(gè)檔。于是就有了我們這個(gè)小項(xiàng)目電影票比價(jià)網(wǎng)在我們這個(gè)網(wǎng)頁(yè)上,會(huì)展示出當(dāng)前熱映的電影。涉及到模塊主要是用來(lái)匹配不同渠道的影院信息代碼結(jié)構(gòu)項(xiàng)目主要有三塊使用豆瓣每日更新上映的影片列表。 注:一篇去年的舊文,發(fā)現(xiàn)沒(méi)在知乎發(fā)過(guò),過(guò)來(lái)補(bǔ)個(gè)檔。有個(gè)小問(wèn)題是項(xiàng)目中淘票票的網(wǎng)頁(yè)反爬提升且變動(dòng)較多,目前暫不可用了。 時(shí)常有同學(xué)會(huì)問(wèn)我類似的問(wèn)題:我已經(jīng)學(xué)完了 Py...

    Codeing_ls 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<