1. 程式人生 > >pyspider框架之ajax資料爬取

pyspider框架之ajax資料爬取

pyspider框架之記錄1

  • 由於公司業務需求,目前做的爬蟲就是爬取全國各個政府釋出的各種政策,平時寫的程式碼,沒有多少想寫成部落格的,後續可能都會寫出來,今天遇到了一個政府網站採用了ajax非同步更新技術,那就做個記錄吧。。
  • 目標政府的url地址為http://www.hangzhou.gov.cn/col/col1255929/index.html
    1. 首先網頁進行簡單分析,因為目標網站存在多頁的情況的,一般情況,進行翻頁,上邊位址列的url地址會跟著翻頁跳轉發生有規律的變化,但是此網站不是這樣,因為採用了ajax非同步更新技術。如下圖
      翻頁1
      翻頁2
    2. 對於ajax非同步請求的資料來說,首先考慮從右鍵->檢查->network裡抓包分析,如果不容易進行抓包分析,可以藉助抓包工具fiddler等,還可以可以藉助selenuim自動化網頁測試等工具。本次爬蟲比較簡單,通過簡單的抓包就可以獲取到ajax非同步請求的url地址。如下圖
      抓包

      由上圖可以,翻一次頁,會多一個左下角的請求檔案,從右下角即可看到傳送請求的url地址,並且採用的是post請求方式,爬蟲時需要有請求體data資料,data資料的內容如下圖
      這裡寫圖片描述
    3. 接下來,就可以用pyspider框架進行爬取資料了,pyspider是一個相對Scrapy簡單的框架,本文不對其使用進行詳細描述,後續會單獨寫pyspider的相關教程。分析完畢,將爬取的資料儲存至本地的mongodb資料庫。現將完整程式碼附上
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2018-06-01 14:20:47
# Project: guojiatongji
# 杭州市人民政府 -. 資訊公開 -> 市政府資訊公開目錄 from pyspider.libs.base_handler import * from pymongo import MongoClient import datetime import re DB_IP = '127.0.0.1' DB_PORT = 27017 DB_NAME = 'research' DB_COL = 'hangzhou' client = MongoClient(host=DB_IP, port=DB_PORT) db = client[DB_NAME] col = db[DB_COL] class
Handler(BaseHandler):
url = 'http://www.hangzhou.gov.cn/col/col1255929/index.html' crawl_config = { "headers": { "User-Agent": "Mozilla/5.0 (X11;Linux x86_64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/66.0.3359.181 Safari/537.36" } } def format_date(self, date): return datetime.datetime.strptime(date, '%Y-%m-%d') @every(minutes=24 * 60) def on_start(self): self.crawl(self.url, fetch_type='js', callback=self.index_page) @config(age=60) def index_page(self, response): page = response.etree total_page_str = page.xpath("//table[@class='tb_title']/tbody/tr/td/text()")[0].encode('utf-8') print total_page_str total_page = int(re.findall('共(\d+)頁', total_page_str)[0]) print total_page # 請求的url base_url = 'http://www.hangzhou.gov.cn/module/xxgk/search.jsp?' # 請求體 data = {"infotypeId": "", "jdid": 149, "area": "", "divid": "div1269023", "vc_title": "", "vc_number": "", "vc_filenumber": "", "vc_all": "", "texttype": 0, "fbtime": -1, "texttype": 0, "fbtime": -1, "vc_all": "", "vc_filenumber": "", "vc_title": "", "vc_number": "", "sortfield": "" } # 翻頁 for page_num in range(1, total_page + 1): page_url = base_url + 'currpage={}&'.format(page_num) print page_url self.crawl(page_url, callback=self.parse_page, method='POST', data=data) def parse_page(self, response): page = response.etree categories = ["中國杭州"] content_list = page.xpath("//div")[2].xpath(".//tr") # 每頁內容 for each in content_list: content_title = each.xpath("./td/a/@title")[0].encode('utf-8') content_url = each.xpath("./td/a/@href")[0] content_date = each.xpath("./td[3]/text()")[0] save = {"title": content_title, "url": content_url, "date": content_date, ### 在這裡不要格式化日期,因為save資料在傳輸的時候會被序列化,到下個函式再用的時候,會變成字串 "categories": categories } self.crawl(content_url, callback=self.parse_body, save=save) def parse_body(self, response): page = response.etree body_list = page.xpath("//td[@class='bt_content']//text()") body = '' for each in body_list: body += each.strip().encode('utf-8') result = {"title": response.save["title"], "categories": response.save["categories"], "date": self.format_date(response.save["date"]), "url": response.save["url"], "body": body, "update_time": datetime.datetime.now(), "source": "杭州市人民政府" } yield result def on_result(self, result): if result is None: return # print result update_key = { 'date': result['date'], 'title': result['title'] } col.update(update_key, {'$set': result}, upsert=True)