Scrapy定向爬蟲教程(六)——分析表單並回帖

本節內容

在某些時候,網站的某些內容的訪問不僅僅需要用戶登錄,而且需要回復才能看到全部內容,如下圖。所以我們需要通過模擬表單提交實現用爬蟲回帖,進而獲取到隱藏內容。本節就來介紹模擬表單提交的方法,github地址:https://github.com/kongtianyi/heartsong/tree/reply

隱藏

前提

你已經瞭解了HTML表單的相關知識(這個很好找)和scrapy的簡單功能以及配置Cookie,如果還不會,請戳Scrapy定向爬蟲教程(五)——保持登陸狀態

分析表單

在帖子頁面的底部找到表單,右鍵檢查,查看這一部分的源代碼

檢查

我們知道,表單提交的數據都在<form>標籤裏,明顯這裏也沒有多選框之類的東西,我們只需要把有name屬性的元素如<input><textarea>都找出來就好了

分析

圖中提到這時的提交地址並不全,咋辦呢,我們就先手動回覆一下,看看都發生了什麼

勾選


action


檢查


編碼

轉碼的話,網上有許多現成的工具,也可以自己寫個小腳本。

代碼

把上面的四張圖看完並且實踐之後局勢就很清晰了,剩下的就是輕輕鬆鬆寫代碼了。ok,上代碼,思路就是先訪問一個頁面,查找這個頁面是否需要回復可見,如果需要,則回覆之。這裏我把判斷是否需要回復註釋掉了,隨便一個帖子id直接運行就會回覆。推薦移步去github上把代碼下載到本地來看,重要部分的我都寫了註釋。

因爲本節只介紹回覆,所以只要網頁上出現了我們用爬蟲回覆出來的內容就算成功了,就不跟下載分析什麼的整合到一起了。

heartsong_spider.py

# -*- coding: utf-8 -*-

# import scrapy # 可以用這句代替下面三句,但不推薦
from scrapy.spiders import Spider
from scrapy.selector import Selector
from scrapy import Request
from scrapy import FormRequest  # 帶表單的請求
import random

class HeartsongSpider(Spider):
    name = "heartsong"
    allowed_domains = ["heartsong.top"]  # 允許爬取的域名,非此域名的網頁不會爬取
    start_urls = [
        # 起始url,這裏只回復這一個頁面,多個頁面連續爬取請看mast分支
        "http://www.heartsong.top/forum.php?mod=viewthread&tid=136"
    ]

    # 用來保持登錄狀態,可把chrome上拷貝下來的字符串形式cookie轉化成字典形式,粘貼到此處
    cookies = {'QGfS_2132_lastvisit': '1478302547', 'QGfS_2132_seccode': '1.fa43f9a3cb6efdd635', 'QGfS_2132_smile': '1D1', 'QGfS_2132_lip': '202.102.144.8%2C1478307120', 'QGfS_2132_ulastactivity': '29d9HUFm42onqH11DCnfZh8MN%2FFmPt0TEe15bNf2oeHflNI%2BJiwJ', 'QGfS_2132_auth': 'd713PkyUoDmnvp%2BestZH5F4lo%2BK0ewxTT1A02ulX%2FbRufbG%2B6T%2FIATHA5uYS9yoQzeNH3qz%2BupceANNs4IWF9w', 'QGfS_2132_nofavfid': '1', 'QGfS_2132_lastact': '1478308730%09misc.php%09patch', 'QGfS_2132_viewid': 'tid_196', 'QGfS_2132_sid': 'wbBi5Q', 'pgv_info': 'ssi', 'QGfS_2132_st_p': '14%7C1478308725%7Cacf78675ed42e1121abb06c3d6b494cb', 'QGfS_2132_visitedfid': '36D48', 'QGfS_2132_saltkey': 'GN4BcGg4', 'QGfS_2132_lastcheckfeed': '14%7C1478307120', 'QGfS_2132_forum_lastvisit': 'D_48_1478306883D_36_1478306901', 'QGfS_2132_st_t': '0%7C1478306901%7C6c837d3b8b5892fd86ea3bb15bf4426e', 'pgv_pvi': '8246475216', 'QGfS_2132_security_cookiereport': '12adOGUyzEnhcSY%2FZb5MgT52%2BxCPi3KZn%2Fh7pNHlxvWLnqDlLbAd'}

    # 發送給服務器的http頭信息,有的網站需要僞裝出瀏覽器頭進行爬取,有的則不需要
    headers = {
        'Connection': 'keep - alive',
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'
    }

    # 對請求的返回進行處理的配置
    meta = {
        'dont_redirect': True,  # 禁止網頁重定向
        'handle_httpstatus_list': [301, 302]  # 對哪些異常返回進行處理
    }

    def start_requests(self):
        """
        這是一個重載函數,它的作用是發出第一個Request請求
        :return:
        """
        # 帶着headers、cookies去請求self.start_urls[0],返回的response會被送到
        # 回調函數parse中
        yield Request(self.start_urls[0],
                             callback=self.parse, headers=self.headers,
                             cookies=self.cookies, meta=self.meta)

    def parse(self, response):
        """
        用以處理主題貼的首頁
        :param response:
        :return:
        """
        selector = Selector(response)  # 創建選擇器

        table = selector.xpath('//*[starts-with(@id, "pid")]')  # 取出所有的樓層
        if not table:
            # 這個鏈接內沒有一個樓層,說明此主題貼可能被刪了,
            # 把這類url保存到一個文件裏,以便審查原因
            print "bad url!"
            f = open('badurl.txt', 'a')
            f.write(response.url)
            f.write('\n')
            f.close()
            return

        # 如有回覆可見的隱藏區域,進行回覆
        # locked = selector.xpath('//*[@class="locked"]')
        # if locked:
        #     re_a = locked.xpath('a/text()')
        #     if re_a and re_a.extract()[0] == u'回覆':
        # 找到表單要提交到的地址
        form_action = selector.xpath('//*[@id="fastpostform"]/@action').extract()[0]
        action = "http://www." + self.allowed_domains[0] + "/" + form_action + "&inajax=1"
        replys = [
            '&#x56DE;&#x590D;&#x770B;&#x770B; &#x6709;&#x7528;&#x4E0D;',
            '&#x5389;&#x5BB3;&#x5389;&#x5BB3;&#xFF0C;&#x8C22;&#x8C22;&#x5206;&#x4EAB;&#xFF01;'
        ]  # utf-8編碼的一些回覆,具體使用什麼編碼要看具體的網站的編碼
        reply = replys[random.randint(0, 1)]  #防止被管理員識別是機器回覆,要隨機一下
        formdata = {
            'formhash': selector.xpath('//*[@id="fastpostform"]/table/tr/td[2]/input[2]/@value').extract()[0],
            'usesig': selector.xpath('//*[@id="fastpostform"]/table/tr/td[2]/input[3]/@value').extract()[0],
            'subject': selector.xpath('//*[@id="fastpostform"]/table/tr/td[2]/input[4]/@value').extract()[0],
            'posttime': selector.xpath('//*[@id="posttime"]/@value').extract()[0],
            'message': reply
        }  # 表單數據,是從網頁表單代碼裏分析出來的
        # 發出帶表單的請求,當然,要有cookie
        yield FormRequest(action, callback=self.finish,
                          headers=self.headers,
                          cookies=self.cookies,
                          meta=self.meta,
                          formdata=formdata)
        return

    def finish(self, response):
        print "reply seccess!"

效果

與正常手動回覆無異。

小結

本節介紹瞭如何分析表單並回帖,希望對你有所幫助!剩下的部分還有配置代理和發送郵件,如果需要,請通知我更新,哈,懶癌需要驅動。

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