日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

【Python3爬蟲】當爬蟲碰到表單提交,有點意思

系統 1773 0

一、寫在前面

  我寫爬蟲已經寫了一段時間了,對于那些使用GET請求或者POST請求的網頁,爬取的時候都還算得心應手。不過最近遇到了一個有趣的網站,雖然爬取的難度不大,不過因為表單提交的存在,所以一開始還是有點摸不著頭腦。至于最后怎么解決的,請慢慢往下看。

?

二、頁面分析

  這次爬取的網站是:https://www.ctic.org/crm?tdsourcetag=s_pctim_aiomsg,該網站提供了美國的一些農田管理的數據。要查看具體的數據,需要選擇年份、單位、地區、作物種類等,如下圖:

【Python3爬蟲】當爬蟲碰到表單提交,有點意思_第1張圖片

  根據以往的經驗,這種表單提交都是通過ajax來完成的,所以熟練地按F12打開開發者工具,選擇XHR選項,然后點擊“View Summary”,結果卻什么都沒有......

【Python3爬蟲】當爬蟲碰到表單提交,有點意思_第2張圖片

  這是怎么回事?不急,切換到All看一下有沒有什么可疑的東西。果然就找到了下面這個,可以看到在Form Data中包含了很多參數,而且可以很明顯看出來是一些年份、地區等信息,這就是表單提交的內容:

【Python3爬蟲】當爬蟲碰到表單提交,有點意思_第3張圖片

  可以注意到在這些參數中有一個_csrf,很明顯是一個加密參數,那么要怎么得到這個參數呢?返回填寫表單的網頁,在開發者工具中切換到Elements,然后搜索_csrf看看,很快就找到了如下信息:

【Python3爬蟲】當爬蟲碰到表單提交,有點意思_第4張圖片

  其余參數都是表單中所選擇的內容,只要對應填寫就行了。不過這個請求返回的狀態碼是302,為什么會是302呢?302狀態碼的使用場景是請求的資源暫時駐留在不同的URI下,因此還需要繼續尋找。

【Python3爬蟲】當爬蟲碰到表單提交,有點意思_第5張圖片

  通過進一步查找可知,最終的URL是:https://www.ctic.org/crm/?action=result。

三、主要步驟?

1.爬取郡縣信息

  可以看到表單中包含了地區、州、郡縣選項,在填寫表單的時候,這一部分都是通過JS來實現的。打開開發者工具,然后在頁面上點選County,選擇Region和State,就能在開發者工具中找到相應的請求。主要有兩個請求,如下:

https://www.ctic.org/admin/custom/crm/getstates/

https://www.ctic.org/admin/custom/crm/getcounties/

  這兩個請求返回的結果格式如下圖:

【Python3爬蟲】當爬蟲碰到表單提交,有點意思_第6張圖片

  這里可以使用正則匹配,也可以使用lxml來解析,我選擇使用后者。示例代碼如下:

            
              1
            
            
              from
            
             lxml 
            
              import
            
            
               etree

            
            
              2
            
            
              3
            
            
              4
            
             html = 
            
              '
            
            
              "Autauga<\/option>Baldwin<\/option>Barbour<\/option>Bibb<\/option>Blount<\/option>Bullock<\/option>Butler<\/option>Calhoun<\/option>Chambers<\/option>Cherokee<\/option>Chilton<\/option>Choctaw<\/option>Clarke<\/option>Clay<\/option>Cleburne<\/option>Coffee<\/option>Colbert<\/option>Conecuh<\/option>Coosa<\/option>Covington<\/option>Crenshaw<\/option>Cullman<\/option>Dale<\/option>Dallas<\/option>Dekalb<\/option>Elmore<\/option>Escambia<\/option>Etowah<\/option>Fayette<\/option>Franklin<\/option>Geneva<\/option>Greene<\/option>Hale<\/option>Henry<\/option>Houston<\/option>Jackson<\/option>Jefferson<\/option>Lamar<\/option>Lauderdale<\/option>Lawrence<\/option>Lee<\/option>Limestone<\/option>Lowndes<\/option>Macon<\/option>Madison<\/option>Marengo<\/option>Marion<\/option>Marshall<\/option>Mobile<\/option>Monroe<\/option>Montgomery<\/option>Morgan<\/option>Perry<\/option>Pickens<\/option>Pike<\/option>Randolph<\/option>Russell<\/option>Shelby<\/option>St Clair<\/option>Sumter<\/option>Talladega<\/option>Tallapoosa<\/option>Tuscaloosa<\/option>Walker<\/option>Washington<\/option>Wilcox<\/option>Winston<\/option>"
            
            
              '
            
            
              5
            
             et =
            
               etree.HTML(html)

            
            
              6
            
             result = et.xpath(
            
              '
            
            
              //option/text()
            
            
              '
            
            
              )

            
            
              7
            
             result = [i.rstrip(
            
              '
            
            
              "
            
            
              '
            
            ) 
            
              for
            
             i 
            
              in
            
            
               result]

            
            
              8
            
            
              print
            
            (result)
          

  上面代碼輸出的結果為:

['Autauga', 'Baldwin', 'Barbour', 'Bibb', 'Blount', 'Bullock', 'Butler', 'Calhoun', 'Chambers', 'Cherokee', 'Chilton', 'Choctaw', 'Clarke', 'Clay', 'Cleburne', 'Coffee', 'Colbert', 'Conecuh', 'Coosa', 'Covington', 'Crenshaw', 'Cullman', 'Dale', 'Dallas', 'Dekalb', 'Elmore', 'Escambia', 'Etowah', 'Fayette', 'Franklin', 'Geneva', 'Greene', 'Hale', 'Henry', 'Houston', 'Jackson', 'Jefferson', 'Lamar', 'Lauderdale', 'Lawrence', 'Lee', 'Limestone', 'Lowndes', 'Macon', 'Madison', 'Marengo', 'Marion', 'Marshall', 'Mobile', 'Monroe', 'Montgomery', 'Morgan', 'Perry', 'Pickens', 'Pike', 'Randolph', 'Russell', 'Shelby', 'St Clair', 'Sumter', 'Talladega', 'Tallapoosa', 'Tuscaloosa', 'Walker', 'Washington', 'Wilcox', 'Winston']

  獲取所有郡縣信息的思路為分別選擇四個地區,然后遍歷每個地區下面的州,再遍歷每個州所包含的郡縣,最終得到所有郡縣信息。

2.爬取農田數據

?  在得到郡縣信息之后,就可以構造獲取農田數據的請求所需要的參數了。在獲取農田數據之前,需要向服務器發送一個提交表單的請求,不然是得不到數據的。在我測試的時候,發送提交表單的請求的時候,返回的狀態碼并不是302,不過這并不影響之后的操作,所以可以忽略掉。

  需要注意的是,參數中是有一個年份信息的,前面我一直是默認用的2011,不過要爬取更多信息的話,還需要改變這個年份信息。而通過選擇頁面元素可以知道,這個網站提供了16個年份的農田數據信息,這16個年份為:

            
              [1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,2002,2004,2006,2007,2008,2011]
            
          

  得到這些年份信息之后,就可以和前面的郡縣信息進行排列組合得到所有提交表單的請求所需要的參數。說道排列組合,一般會用for循環來實現,不過這里推薦一種方法,就是使用itertools.product,使用示例如下:

            
               1
            
            
              from
            
             itertools 
            
              import
            
            
               product

            
            
               2
            
            
               3
            
             a = [1, 2, 3
            
              ]

            
            
               4
            
             b = [2, 4
            
              ]

            
            
               5
            
             result =
            
               product(a, b)

            
            
               6
            
            
              for
            
             i 
            
              in
            
            
               result:

            
            
               7
            
            
              print
            
            (i, end=
            
              "
            
            
              "
            
            
              )

            
            
               8
            
            
               9
            
            
              10
            
            
              #
            
            
               (1, 2) (1, 4) (2, 2) (2, 4) (3, 2) (3, 4) 
            
          

  下面是農田數據的部分截圖,其中包含了很多種類的作物,還有對應的耕地面積信息,不過在這個表中有些我們不需要的信息,比如耕地面積總量信息,還有空白行,這都是干擾數據,在解析的時候要清洗掉。

【Python3爬蟲】當爬蟲碰到表單提交,有點意思_第7張圖片

  解析農田數據部分的代碼如下:

            
              
                1
              
               et =
              
                 etree.HTML(html)

              
              
                2
              
               crop_list = et.xpath(
              
                '
              
              
                //*[@id="crm_results_eight"]/tbody/tr/td[1]/text()
              
              
                '
              
              
                )  # 作物名稱

              
              
                3
              
               area_list = et.xpath(
              
                '
              
              
                //*[@id="crm_results_eight"]/tbody/tr/td[2]/text()
              
              
                '
              
              
                )  # 耕地面積

              
              
                4
              
               conservation_list = et.xpath(
              
                '
              
              
                //*[@id="crm_results_eight"]/tbody/tr/td[6]/text()
              
              
                '
              
              
                )  # 受保護耕地面積

              
              
                5
              
               crop_list = crop_list[:-3
              
                ]

              
              
                6
              
               area_list = area_list[:-3
              
                ]

              
              
                7
              
               conservation_list = conservation_list[:-3]
            
          

?

?完整代碼已上傳到GitHub!


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 射阳县| 泽库县| 郸城县| 湘潭市| 西充县| 同德县| 望谟县| 和平区| 镇沅| 三河市| 喀什市| 兴业县| 安化县| 五大连池市| 永清县| 高安市| 大化| 新乡县| 剑川县| 孟州市| 富顺县| 崇礼县| 天台县| 兴文县| 高州市| 阜康市| 墨玉县| 扎囊县| 文登市| 枣阳市| 广饶县| 安顺市| 凯里市| 肥东县| 鹤庆县| 洛阳市| 白山市| 西藏| 开化县| 商洛市| 南雄市|