python 爬取世紀佳緣,經過js渲染過的網頁的爬取


#!/usr/bin/python
#-*- coding:utf-8 -*-

#爬取世紀佳緣
#這個網站是真的煩,剛開始的時候用scrapy框架寫,但是因為剛接觸框架,碰到js渲染的頁面之后就沒辦法了,所以就采用一般的爬蟲了
#js渲染過的數據,可能在網頁源碼里面沒有數據,需要js異步請求提取數據,然后展示,所以爬取這類的數據,只需要找到js發送請求的url就行了
#js發送的請求可能是post(比如這個例子)或者是get(比如豆瓣電影劇情的排行榜),所以要看好是什么請求

import sys
import json 
#from lxml import etree
import urllib
import urllib2 


reload(sys)
sys.setdefaultencoding("utf-8") #設置默認的編碼格式,把Unicode格式轉換成漢字寫到文件里面的時候需要用到,要配合decode("unicode_escape")使用

class shiji():
    def __init__(self):
        self.page = 1 #初始化頁面的第幾頁
        self.filename = open("sj.json","w") #打開文件用於寫入數據

    def parse_page(self):
        url = "http://search.jiayuan.com/v2/search_v2.php?" #初始url的前半段,加上后半段發送的是post請求
        headers = {"User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"}
        formdata = {
                "sex":"f",
                "key":"",
                "stc":"1:11,2:20.25,3:160.170,23:1",
                "sn":"default",
                "sv":"1",
                "p":self.page, #每次數據js異步提取數據的時候只有p變化了,p對應於當前頁面是第幾頁 
                "f":"select",
                "listStyle":"bigPhoto",
                "pri_uid":"170633820",
                "jsversion":"v5"
            }
        data = urllib.urlencode(formdata)
        request = urllib2.Request( url ,data = data , headers = headers)
        response = urllib2.urlopen(request)
#        print response.info().get('Content-Encoding') #這會打印出服務器返回數據的壓縮方式,如果未有壓縮則返回None
        js = response.read() #返回的response.read()是json格式的,但是首和尾多了一段字符串"##jiayse##"和"##jiayse##",所以下面就處理一下
        
        #print type(js) #字符串類型
        js = js.replace("##jiayser##","").replace("//","") #字符串里很牛X的一個函數replace()
        #print js 
        content = json.loads(js) #字典類型(這個字典是大字典,key只有isLogin、count、pageTotal、userInfo,其中userInfo是每個人的資料)
        
        self.parse_person(content['userInfo']) #調用parse_person函數處理大字典的ueerInfo(還是字典類型的),即每個人的資料
#            print type(content['userInfo'])#字典類型

    def parse_person(self,userinfo):
        for i in range(len(userinfo)):
            
            form = {"昵稱":userinfo[i]['nickname'],"年齡":userinfo[i]['age'],"內心獨白":userinfo[i]['shortnote']} #把要爬取的數據寫成一個字典
            
            #print form 
            #print type(form)
            
            #不能把dict和list類型直接寫入文件, 把字典寫入json文件的時候要把字典轉換成json字符串才行(json.dumps(form))
            #decode("unicode_escape")表示把unicode格式轉換成漢字,但用一個這竟然還不行!還要加上上面的import sys... , 真麻煩
            form = json.dumps(form).decode("unicode_escape") 
            
            self.filename.write(form+"\n") #寫入文件

        if self.page <10: #這里隨便寫self.page,只要不超過頁面加載的范圍就行
            self.page+=1
            self.parse_page() #自加一之后在調用parse_page()函數進行換頁,然后接着爬

if __name__ == "__main__":
    sj = shiji()
    sj.parse_page() #調用parse_page()函數開始爬取

寫這個爬蟲浪費了一天的時間。。。我是真的菜。

錯誤總結:
關於unicode編碼轉漢字的方法以及UnicodeEncodeError: 'ascii' codec can't encode characters in position問題: 
 https://www.cnblogs.com/technologylife/p/6071787.html   
 http://blog.sina.com.cn/s/blog_64a3795a01018vyp.html

把dict寫入文件的時候碰見的報的typeError的解決辦法: http://blog.csdn.net/guoweish/article/details/47106263

另外加一篇ubuntu vim撤銷操作的博客  http://blog.sina.com.cn/s/blog_7e9efc570101ays3.html

收獲:這次的收獲還可以,解決了很多沒見過的bug,第一次爬取js渲染的網頁的數據,值得記得的是:(1).js渲染過得網頁怎么找數據來源(f12 network XHR 找是post請求還是get請求),(2)字符串的強大替換函數replace,(3)字典寫入文件怎么處理  (先轉換成json的字符串再寫入),(4)unicode轉漢字怎么處理(import sys + decode("unicode_escape"))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM