社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

用Python对空间进行爬取

python • 7 年前 • 618 次点击  


运行环境

版本

Python3.5

系统

Windows 10

IDE

pycharm

数据处理软件Excel

附录:带好小板凳,前排出售瓜子饮料


需要的库

需求分析及源码

分析

        QQ空间是需要登陆才能爬取的,所以说首先要做的事进行登陆,这里有两种思路进行模拟登陆:

(1)、用selenium+Chrome 进行自动化检测登陆,接着用扫码或者账号自动输入都是可以的,然后获取cookies,再传入requests.Session().get()对要爬取好友的空间进行爬取。

(2)、用opener 和 cookielib 进行对网站cookie的获取,然后再传入requests.Session().get()

我在这里使用的是第一种方法。

Cookies的使用详情在这里: cuiqingcai.com/968.html

Session的使用详情在这里:cnblogs.com/whatbeg/p/5

2、当我们登陆上的时候进行抓包(炒鸡重要),然后在开发者工具里,找到这个文件,打开之后发现这就是我们想要的数据,所以......我们想要抓取的文件是找到了,但是对应的请求头呢?

        在这里的headers,点开后发现,这里有个Request URL,这个就是我们要的URL

        再点开Query发现,URL的数据这里都有,但是仔细分析后发现。。。。这里有些东西我们不知道是怎么来的,就是这里的g_tk和qzone_token,不是那么很规则,这个时候,我们多点开几个页面试试,我们会发现,只有这两个参数是改变的,其余的参数都是不变的,所以我们只要解决这两个参数,我们就可以请求到这个json数据。好,接下来要解决的问题就是如何获得g_tk和qzonetoken这两个数据。


        这里有个找参数的方法1、可以先在网页上对源代码进行查找,有些参数是隐藏在网页的源码里的,看存不存在,如果存在,用xpath或者bs4库进行解析(我在这里用的是正则表达式来提取),如果不存在,就要用下面的方法。

查找参数

        如果网页源码里找不到,可能就是被加密了,水平实在有限,没能破解的出,所以 就百度了一下QQ空间的加密方式,在CSDN的博客上发现了这个解密的代码。

        所以在这个登陆模块,我们完成的是登陆上去,获取到相应的参数,然后返回来,以备后用。好啦,参数获取完了,要获取数据了,下面这个模块就是对数据的获取。

数据获取

        有了上面的获取的三个数据,那登陆到QQ空间就是一点问题都木有啦,然后创建一个会话(Session()),保持本地与服务器的连接。一个get,我们就把json格式的数据爬取下来了。

但是!!!不能一直爬取下去,所以要对爬取的内容进行一个判别是否爬取结束

如果爬取结束了,就break出循环了,然后再爬取下一个好友的动态。

数据的清洗

        还没有学习数据库的内容,所以就将爬取的json文件转为字典,然后对字典进行处理保存为csv文件。用了一个xlwt的库,这个库可以建立并读写数据

然后保存为文件。

注意!!!这里一定要加入异常的处理,因为有些人的QQ空间是不开放的,所以遇到不开放的空间就会出错,为了让程序能够正常的执行,所以必须要加异常处理。

点击运行按钮,一段时间后,就可以查看你爬取的成果了,爬取了6W+的数据.....

数据处理

        Python有丰富的数据处理的库,numpy pandas scipy ,由于存储为csv文件,当然电脑上也有tableau和matlab,但是对这两个软件不太熟悉,就就直接用Excel软件进行处理。

以下是我用Excel做的几张图:

源码:


import requestsfrom selenium import webdriverfrom PIL import Imageimport xlwtimport timeimport reimport jsonfrom collections import Iterableimport csvn = 1header = {'Host': 'h5.qzone.qq.com',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0',
    'Accept': '*/*',
    'Accept-Language':'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Accept-Encoding': 'gzip, deflate, br',
    'Referer': 'https://user.qzone.qq.com/790178228?_t_=0.22746974226377736',
    'Connection':


    
'keep-alive'}#对表格进行处理file = xlwt.Workbook()table = file.add_sheet('sheet name', cell_overwrite_ok= True)table.write(0,1,"日期")table.write(0,2,"时间")table.write(0,3,"年份")table.write(0,4,"月份")table.write(0,5,"时间点")table.write(0,6,"图片数量")table.write(0,7,"评论数量")table.write(0,8,"手机型号")table.write(0,9,"经度")table.write(0,10,"地点")table.write(0,11,"纬度")table.write(0,12,"位置")table.write(0,13,"内容")#从邮箱里到导出的联系人,然后进行读取操作def getfriends():
    


    
csv_reader = csv.reader(open('qq.csv'))
    friend = []
    for row in csv_reader:
        friend.append(row[3])
    friend.pop(0)
    friends = []
    for f in friend:
        f = f[:-7]
        friends.append(f)
    return friends# 这个函数用来解决腾讯g_tk加密算法的函数def get_g_tk(cookie):
    hashes = 5381
    for letter in cookie['p_skey']:
        hashes += (hashes << 5) + ord(letter)  # ord()是用来返回字符的ascii码
    return hashes & 0x7fffffff#这个函数是用来获取cookie,g_tk,g_qzontoken这三个数据def Login_QQ():
    driver = webdriver.Chrome()             
    start_url = "https://qzone.qq.com/"
    driver.get(start_url)
    time.sleep(10)
    cookie = {}
    for elem in driver.get_cookies():
        cookie[elem['name']] = elem['value']
    html = driver.page_source
    g_qzonetoken = re.search(r'window\.g_qzonetoken = \(function\(\)\{ try\{return (.*?);\} catch\(e\)',html)
    g_tk = get_g_tk


    
(cookie)
    driver.quit()
    print(g_qzonetoken.group(1))
    return (cookie, g_tk, g_qzonetoken.group(1))def spyder_info():
    s = requests.session()
    friends = getfriends()
    cookie, g_tk, g_qzonetoken = Login_QQ()
    for qq in friends:
        global n
        for i in range(1000):
            pos = i*20
            param = {
                'uin': qq,
                'ftype': '0',
                'sort': '0',
                'pos': pos,
                'num': '20',
                'replynum': '100',
                'g_tk': g_tk,
                'callback': '_preloadCallback',
                'code_version': '1',
                'format': 'jsonp',
                'need_private_comment': '1',
                'qzonetoken': g_qzonetoken
            }
            respond = s.get("https://h5.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6",
                                params=param, headers = header,cookies=cookie)
            r = re.sub("_preloadCallback", "", respond.


    
text)
            test = r[1:-2]
            Data = json.loads(test)
            if not re.search('lbs', test):  # 通过lbs判断此qq的说说是否爬取完毕
                print('%s说说下载完成' % qq)
                break
            try:
                for each_data in Data["msglist"]:
                    # 说说发表的日期1
                    table.write(n, 1, each_data["createTime"])
                    # 说说发表的时间2
                    table.write(n, 2, time.strftime("%H:%M:%S", time.localtime(each_data["created_time"])))
                    # 说说发表的年份3
                    table.write(n, 3, time.strftime("%Y", time.localtime(each_data["created_time"])))
                    # 说说发表的月份4
                    table.write(n, 4, time.strftime("%m", time.localtime(each_data["created_time"])))
                    # 说说发表的小时5
                    table.write(n, 5, time.strftime("%H", time.localtime(each_data[


    
"created_time"])))
                    # 统计图片的数量6,以及用的手机型号8
                    if "pic" in each_data:
                        table.write(n, 6, each_data["pictotal"])
                        table.write(n, 8, each_data["source_name"])
                    else:
                        table.write(n, 6, 0)
                        table.write(n, 8, "")

                    # 统计每个说说的评论数量7
                    if each_data["commentlist"]:
                        table.write(n, 7, each_data["commentlist"][-1]["tid"])
                    else:
                        table.write(n, 7, 0)

                    # 获取该条说说的发表位置:9,10,11,12
                    if "story_info" in each_data:
                        table.write(n, 9, each_data["story_info"]["lbs"]["pos_x"])
                        table.write(n, 11, each_data["story_info"]["lbs"]["name"])
                        table.write(n, 10, each_data["story_info"]["lbs"]["pos_y"])
                        table.write(n, 12,


    
 each_data["story_info"]["lbs"]["idname"])
                    else:
                        table.write(n, 9, "")
                        table.write(n, 11, "")
                        table.write(n, 10, "")
                        table.write(n, 12, "")

                    # 获取每一条说说的内容13
                    if each_data["content"]:
                        table.write(n, 13, each_data["conlist"][0]["con"])
                    else:
                        table.write(n, 13, "")
                    n = n + 1
            except:
                print("error")


    file.save("demo6.xls")#if '__name__' == '__main__':spyder_info()




今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/TKJzNdHGOk
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/4161
 
618 次点击