python 爬取天眼查,有效應對字體反爬

作爲一個新生代的爬蟲小菜雞,應該多學習一些爬蟲的奇技淫巧。

本篇博文旨在經驗交流,如果侵犯利益,請告知刪除。


作爲企業信息的彙總之地,天眼查和企查查一直被大量的爬蟲愛好者光顧,於是各種反爬措施層出不窮,極驗二代三代驗證碼,字體反爬,JS加密等等手段,但是,蒼蠅不叮沒縫的蛋,總有辦法應對這些反爬措施。

1.先來看看登錄頁面,這裏登錄有個極驗二代的驗證碼,可以推導軌跡進行selenium模擬拖動。

但是我們可以嘗試看一下頁面,發現登錄不登錄都看不到第六頁,貧窮限制了自己的想象,兩個網站都要開VIP才能看之後的頁面,於是我們其實可以考慮不登陸網站的方法,這樣也不用登錄就可以愉快抓取5頁了。

抓取的url:https://www.tianyancha.com/search/p6?key=知乎-----------------------p6代表第6頁,之後類推,key後面帶關鍵字

2.好的,裝模做樣分析一波就可以開幹了,我們在這個搜索頁面只需要兩個值就可以了,公司名字和公司鏈接,但是這裏需要提醒的是,公司名是text,偶爾觸發字體反爬(也就是加了tyc-num的屬性後)會變成其他文本,所以我們可以考慮用左邊圖片的替代文本alt的值來作爲公司名字。

def get_url(keyword,page):
    global count
    res = requests.get('代理池代理池')
    proxy = json.loads(res.text)
    url= "https://www.tianyancha.com/search/p{}?key={}".format(page, keyword)
    response = requests.get(url, headers=headers,  proxies=proxy)
    if response.status_code == 200:
        doc = pq(response.text)
        items = doc("#web-content > div > div.container-left > div.search-block.header-block-container > div.result-list.sv-search-container > div").items()
        data = {}
        for item in items:
            #利用圖片的填充文本獲取公司名字
            img = item("div > div.left-item > div > div.logo.-w88 > img")
            data['name'] = img.attr("alt").replace("<em>", "").replace("</em>", "")
            # 獲取公司url
            a = item("div > div.content > div.header > a")
            data['url'] = a.attr("href")
            count = count + 1
            print(data, count)
            yield data

這裏進行了統計,前五頁爬取的count爲100,與原頁面每頁20相同,證明沒有漏的公司,這個也有一個弊端,像我這裏加了個代理,不然偶爾會要求登錄,當然也可以不加,加個cookies也是可以的,複製自己登錄後的cookies放到get中,一般都利用字典推導式來做cookies。

# 不帶上Cookie就訪問不了這個頁面
cookie = "aliyungf_tc=AQAAAIub1w4uFgcAikIYdAQzI8dY9mjU; ssuid=6115264187; bannerFlag=undefined; Hm_lvt_e92c8d65d92d534b0fc290df538b4758=1558404890; _ga=GA1.2.418827579.1558404891; _gid=GA1.2.1891485528.1558404891; csrfToken=lpQFxeRdjmGjcXoLdq3aGZsV; TYCID=46901ee07b6e11e9be27abfcc402465e; undefined=46901ee07b6e11e9be27abfcc402465e; RTYCID=3893429da45240babd4ebcf58969d8c0; CT_TYCID=4135fc93e4a744efb4baa63d20fbf539; _gat_gtag_UA_123487620_1=1; token=a2e453b73bdb483689cb1e653afc9501; _utm=ec1d80bc6b174ee0b1244b21be75a067; tyc-user-info=%257B%2522claimEditPoint%2522%253A%25220%2522%252C%2522myAnswerCount%2522%253A%25220%2522%252C%2522myQuestionCount%2522%253A%25220%2522%252C%2522signUp%2522%253A%25220%2522%252C%2522explainPoint%2522%253A%25220%2522%252C%2522privateMessagePointWeb%2522%253A%25220%2522%252C%2522nickname%2522%253A%2522%25E7%2599%25BD%25E8%25B5%25B7%2522%252C%2522integrity%2522%253A%25220%2525%2522%252C%2522privateMessagePoint%2522%253A%25220%2522%252C%2522state%2522%253A%25220%2522%252C%2522announcementPoint%2522%253A%25220%2522%252C%2522isClaim%2522%253A%25220%2522%252C%2522vipManager%2522%253A%25220%2522%252C%2522discussCommendCount%2522%253A%25220%2522%252C%2522monitorUnreadCount%2522%253A%25224%2522%252C%2522onum%2522%253A%25220%2522%252C%2522claimPoint%2522%253A%25220%2522%252C%2522token%2522%253A%2522eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMzQyMjgyMDcyMSIsImlhdCI6MTU1ODU3NDEyMSwiZXhwIjoxNTkwMTEwMTIxfQ.QtfsbeQnO7hclIN8u91-lGGjpA9IAnGD7oV6iUT6X3L-9MASeA2_sg6n3HY1CMuuEs9sXHQibat0Ovm2WGbgkA%2522%252C%2522pleaseAnswerCount%2522%253A%25220%2522%252C%2522redPoint%2522%253A%25220%2522%252C%2522bizCardUnread%2522%253A%25220%2522%252C%2522vnum%2522%253A%25220%2522%252C%2522mobile%2522%253A%252213422820721%2522%257D; auth_token=eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMzQyMjgyMDcyMSIsImlhdCI6MTU1ODU3NDEyMSwiZXhwIjoxNTkwMTEwMTIxfQ.QtfsbeQnO7hclIN8u91-lGGjpA9IAnGD7oV6iUT6X3L-9MASeA2_sg6n3HY1CMuuEs9sXHQibat0Ovm2WGbgkA; Hm_lpvt_e92c8d65d92d534b0fc290df538b4758=1558574102; cloud_token=33904acac4d444f694a3f0512fb7ca64; cloud_utm=c9a3948de7934cd9b148c0fca7ddcac3"
# 將上面哪個cookie轉化成字典類型
cookie_dict = {i.split("=")[0]:i.split("=")[-1] for i in cookie.split("; ")}

這個cookies是我上週的,在登陸時有選保持一週登錄的話就還可以使用,不過最穩妥的辦法就是cookies+proxies.

這個時打印的頁面,關鍵字是“百度”頁數是5

3.一般我們會把這個url存入數據庫中,稱之爲種子,不是那些mp4rmvb的種子,是對於我們下一步爬取的種子,接下來可以根據這個url來爬取企業具體信息了。這個詳情頁面大概率會出現字體反爬,也就是我之前說的tyc-num

剛開始我還覺得能拿title來繼續做,到了後面發現經營範圍這個字段真的是太煩了

而且這個在有cookies,sleep10秒以上的情況下還有機會給我個極驗3代的驗證碼。。

雖然這個頁面在我登錄時也有機會出現的,但是這個頁面讓我有了一些思路,仔細看看這個return_url,這個是返回到我們剛剛的公司信息頁面,也就是我們提交完驗證碼後跳轉回公司詳情頁會有個reference

果然有這個,有了這個我就不用打極驗三代驗證碼了,省了一筆小錢,而我們再看看網頁源碼,發現竟然沒有加tyc-num這個屬性了,於是我做個大膽推測,當我們繞過天眼查的機器人識別後,他們就會以爲我們是正常用戶了,所以頁面上的反爬都消失了,當然沒有換IP作死也有可能被查出來,儘量還是利用代理。

這裏貼上我爬數據的源碼,利用referer來繞過驗證碼以及字體反爬是個有效措施。我想要爬取字體加密的信息,這個有難度,之前也有嘗試過破解字體加密(也就是我的fontchange),但是沒辦法自動化,得用機器學習來做ocr纔可以,如果有興趣可以查看項目源碼(博文末尾)

def crawl_item(keyword):
    for item in db[keyword].find({}):
        sleep(random.randrange(1, 15))
        headers["Referer"] = "https://antirobot.tianyancha.com/captcha/verify?return_url=https%3A%2F%2Fwww.tianyancha.com%2Fcompany%"+ item["url"][35::] +"&rnd="
        response = requests.get(url=item["url"], headers=headers, cookies=cookie_dict)
        doc = pq(response.text)
        str1 = doc('.tyc-num').text()
        if str1:
            print(str1)
            str2 = fontchange(str1)
            print(str2)
        else:
            text2 = doc("#_container_baseInfo .table:nth-child(2)").text().split("\n")
            my_dict = {}
            my_dict["name"] = item["name"]
            for i in range(0, len(text2) - 1, 2):
                my_dict[text2[i]] = text2[i + 1]
            yield my_dict

記住,爬蟲要健壯的話必須加上cookies和proxies,不然各大網站都可能因此封ip,短則1-2小時,長則1-3天,這樣會超級難受的。https://github.com/triangle959/TianYanCha


貼一組字體反爬的圖,運用邏輯在於項目內的fontchange,將網頁的文字與font字體文件連接起來

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章