Python爬蟲(chóng)json和JsonPath系列之十一

1践宴,json中四個(gè)重要的方法

  • Json結(jié)構(gòu)清晰鲸匿,可讀性高,復(fù)雜度低阻肩,非常容易匹配带欢。

1. json.loads()

把Json格式字符串解碼轉(zhuǎn)換成Python對(duì)象

從json到python的類(lèi)型轉(zhuǎn)化對(duì)照如下:

這里寫(xiě)圖片描述

2. json.dumps()

實(shí)現(xiàn)python類(lèi)型轉(zhuǎn)化為json字符串,返回一個(gè)str對(duì)象 烤惊。

從python原始類(lèi)型向json類(lèi)型的轉(zhuǎn)化對(duì)照如下:

這里寫(xiě)圖片描述

3. json.dump()

將Python內(nèi)置類(lèi)型序列化為json對(duì)象后寫(xiě)入文件

4. json.load()

讀取文件中json形式的字符串元素 轉(zhuǎn)化成python類(lèi)型

5乔煞,注意事項(xiàng):

json.loads() 是把 Json格式字符串解碼轉(zhuǎn)換成Python對(duì)象,如果在json.loads的時(shí)候出錯(cuò)柒室,要注意被解碼的Json字符的編碼渡贾,如果傳入的字符串的編碼不是UTF-8的話,需要指定字符編碼的參數(shù)encoding

如:

dataDict = json.loads(jsonStrGBK);

jsonStrGBK是JSON字符串雄右,假設(shè)其編碼本身是非UTF-8的話而是GBK 的空骚,那么上述代碼會(huì)導(dǎo)致出錯(cuò),改為對(duì)應(yīng)的:

 dataDict = json.loads(jsonStrGBK, encoding="GBK");
  • 任何平臺(tái)的任何編碼 都能和 Unicode 互相轉(zhuǎn)換
  • decode的作用是將其他編碼的字符串轉(zhuǎn)換成 Unicode 編碼
  • encode的作用是將 Unicode 編碼轉(zhuǎn)換成其他編碼的字符串
  • 一句話:UTF-8是對(duì)Unicode字符集進(jìn)行編碼的一種編碼方式

2擂仍,JsonPath

JsonPath 是一種信息抽取類(lèi)庫(kù)囤屹,是從JSON文檔中抽取指定信息的工具。

  • JsonPath與XPath語(yǔ)法對(duì)比:
這里寫(xiě)圖片描述

3逢渔,爬取某招聘網(wǎng)站職位信息案例

import requests
import json
import jsonpath


class LagouSpider:
    def __init__(self):
        self.headers = {
            # 模擬真實(shí)的瀏覽器肋坚,把請(qǐng)求頭全部都加上
            # "Accept" : "application/json, text/javascript, */*; q=0.01",
            # "Accept-Encoding" : "gzip, deflate, br",
            # "Accept-Language" : "zh-CN,zh;q=0.8",
            # "Connection" : "keep-alive",
            # "Content-Length" : "43",
            # "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
            "Cookie": "user_trace_token=20170626172300-2aa5eb9c81db4093b6491f60c504f9a1; LGUID=20170626172300-0c74fdbf-5a51-11e7-89d3-525400f775ce; index_location_city=%E5%8C%97%E4%BA%AC; JSESSIONID=ABAAABAACDBABJB0A65566C403D46573532367CBEEF2AB5; PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; _gid=GA1.2.327690172.1500516674; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1498468981,1500406505,1500516674; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1500518676; _ga=GA1.2.764300251.1498468981; LGSID=20170720104259-2462b23d-6cf5-11e7-ae7e-525400f775ce; LGRID=20170720104435-5db33ef4-6cf5-11e7-ae8d-525400f775ce; TG-TRACK-CODE=search_code; SEARCH_ID=36027e19a74f4ceaab54f35baae12a30",
            "Host": "www.lagou.com",
            "Origin": "https://www.lagou.com",

            # 反爬第二步,標(biāo)記瀏覽器的來(lái)源肃廓,從查看網(wǎng)頁(yè)源碼可知
            "Referer": "https://www.lagou.com/jobs/list_python%E7%88%AC%E8%99%AB?labelWords=&fromSearch=true&suginput=",
            # 反爬第一步
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
            "X-Anit-Forge-Code": "0",
            "X-Anit-Forge-Token": "None",
            "X-Requested-With": "XMLHttpRequest"
        }

        # url地址固定部分
        self.baseURL = "https://www.lagou.com/jobs/positionAjax.json?"
        self.positionName = input("請(qǐng)輸入需要查詢的職位名:")
        self.cityName = input("請(qǐng)輸入需要查詢的城市名:")
        self.endPage = int(input("請(qǐng)輸入需要爬取的頁(yè)數(shù):"))
        # post的頁(yè)碼數(shù)據(jù)
        self.page = 1
        # 添加代理
        # self.proxy = {"http" : "123.23.232.11:8080"}

    def startWrok(self):
        # 存儲(chǔ)loadPage()返回的所有職位信息
        item_list = []
        while self.page <= self.endPage:
            # 獲取每一頁(yè)的職位信息列表
            position_list = self.loadPage()
            # 合并所有頁(yè)的職位信息
            item_list += position_list
            # 每獲取一頁(yè)智厌,頁(yè)碼自增1
            self.page += 1
        # 禁用ascii處理中文,返回json格式的字符串盲赊,返回Unicode
        content = json.dumps(item_list, ensure_ascii=False)
        # 將數(shù)據(jù)寫(xiě)入到磁盤(pán)文件里
        with open("lagou_info.json", "w") as f:
            f.write(content)

    def loadPage(self):
        # url的查詢字符串峦剔,post請(qǐng)求采參數(shù)
        params = {"city": self.cityName, "needAddtionalResult": "false"}
        # post的表單數(shù)據(jù)
        formdata = {"first": "true", "pn": self.page, "kd": self.positionName}
        try:
            print("[LOG]: 正在抓取 %d 頁(yè)..." % self.page)
            response_result = requests.post(self.baseURL, params=params, data=formdata, headers=self.headers)
            # 代理使用: proxies = self.proxy)
        except Exception as e:
            print("[LOG]: 抓取失敗...")
            print(e)
        # time.sleep(2)
        # html = response.content
        # jsonobj = json.loads(html)

        # 按json格式獲取requests響應(yīng),Python數(shù)據(jù)類(lèi)型
        jsonobj = response_result.json()

        """
        # urllib2 的用法
        params = urllib.urlencode(params)
        data = urllib.urlencode(formdata)
        url = self.baseURL + params
        request = urllib2.Request(url, data = data, headers = self.headers)
        response = urllib2.urlopen(request)
        jsonobj = json.loads(response.read())
        """

        try:
            # 通過(guò)jsonpath獲取json里的result部分
            result_list = jsonpath.jsonpath(jsonobj, "$..result")[0]
            # 存儲(chǔ)當(dāng)前頁(yè)的職位信息
            position_list = []
            # 處理每一條職位信息
            for result in result_list:
                # 獲取每條職位信息的部分?jǐn)?shù)據(jù)
                item = {}
                item['城市'] = result['city'] if result['city'] else "NULL"
                item['公司名'] = result['companyFullName'] if result['companyFullName'] else "NULL"
                item['發(fā)布時(shí)間'] = result['createTime'] if result['createTime'] else "NULL"
                item['區(qū)域'] = result['district'] if result['district'] else "NULL"
                item['職位'] = result['positionName'] if result['positionName'] else "NULL"
                item['薪水'] = result['salary'] if result['salary'] else "NULL"

                position_list.append(item)
            return position_list

        except Exception as  e:
            print("[ERR]: 獲取數(shù)據(jù)失敗...")
            print(e)
            return []


if __name__ == "__main__":
    spider = LagouSpider()
    spider.startWrok()

4角钩,把json格式的文件轉(zhuǎn)為csv格式的文件

# 處理json文本
import json
# 處理csv
import csv

# 創(chuàng)建csv文件對(duì)象
csvFile = open("lagou_info.csv", "w")
# 創(chuàng)建csv文件的讀寫(xiě)對(duì)象,可以用來(lái)對(duì)csv進(jìn)行讀寫(xiě)操作
csv_writer = csv.writer(csvFile)

# 創(chuàng)建json文件對(duì)象
jsonFile = open("lagou_info.json", "r")
# 讀取本地磁盤(pán)json文件呻澜,返回原本的數(shù)據(jù)類(lèi)型:列表
content_list = json.load(jsonFile)

# 獲取表頭部分
sheet = content_list[0].keys()

# 將所有的數(shù)據(jù)放到一個(gè)大列表里
data = [content.values() for content in content_list]

# writerow 表示寫(xiě)入一行數(shù)據(jù)递礼,參數(shù)是一個(gè)列表
csv_writer.writerow(sheet)
# writerows 表示寫(xiě)入多行數(shù)據(jù),參數(shù)是一個(gè)列表(包含所有數(shù)據(jù))
csv_writer.writerows(data)

csvFile.close()
jsonFile.close()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末羹幸,一起剝皮案震驚了整個(gè)濱河市脊髓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌栅受,老刑警劉巖将硝,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恭朗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡依疼,警方通過(guò)查閱死者的電腦和手機(jī)痰腮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)律罢,“玉大人膀值,你說(shuō)我怎么就攤上這事∥蠹” “怎么了沧踏?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)巾钉。 經(jīng)常有香客問(wèn)我翘狱,道長(zhǎng),這世上最難降的妖魔是什么砰苍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任潦匈,我火速辦了婚禮,結(jié)果婚禮上师骗,老公的妹妹穿的比我還像新娘历等。我一直安慰自己,他們只是感情好辟癌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布寒屯。 她就那樣靜靜地躺著,像睡著了一般黍少。 火紅的嫁衣襯著肌膚如雪寡夹。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天厂置,我揣著相機(jī)與錄音菩掏,去河邊找鬼。 笑死昵济,一個(gè)胖子當(dāng)著我的面吹牛智绸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播访忿,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼瞧栗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了海铆?” 一聲冷哼從身側(cè)響起迹恐,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卧斟,沒(méi)想到半個(gè)月后殴边,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體憎茂,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年锤岸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了竖幔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡能耻,死狀恐怖赏枚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晓猛,我是刑警寧澤饿幅,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站戒职,受9級(jí)特大地震影響栗恩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜洪燥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一磕秤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捧韵,春花似錦市咆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至芒篷,卻和暖如春搜变,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背针炉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工挠他, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人篡帕。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓殖侵,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親镰烧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拢军,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容