如何用 Python 爬取社交网络

Python025

如何用 Python 爬取社交网络,第1张

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Author: Administrator

# @Date: 2015-10-31 15:45:27

# @Last Modified by: Administrator

# @Last Modified time: 2015-11-23 16:57:31

import requests

import sys

import json

import re

reload(sys)

sys.setdefaultencoding('utf-8')

#获取到匹配字符的字符串

def find(pattern,test):

finder = re.search(pattern, test)

start = finder.start()

end = finder.end()

return test[start:end-1]

cookies = {

'_ga':'GA1.2.10sdfsdfsdf', '_za':'8d570b05-b0b1-4c96-a441-faddff34',

'q_c1':'23ddd234234',

'_xsrf':'234id':'"ZTE3NWY2ZTsdfsdfsdfWM2YzYxZmE=|1446435757|15fef3b84e044c122ee0fe8959e606827d333134"',

'z_c0':'"QUFBQXhWNGZsdfsdRvWGxaeVRDMDRRVDJmSzJFN1JLVUJUT1VYaEtZYS13PT0=|14464e234767|57db366f67cc107a05f1dc8237af24b865573cbe5"',

'__utmt':'1', '__utma':'51854390.109883802f8.1417518721.1447917637.144c7922009.4',

'__utmb':'518542340.4.10.1447922009', '__utmc':'51123390', '__utmz':'5185435454sdf06.1.1.utmcsr=zhihu.com|utmcgcn=(referral)|utmcmd=referral|utmcct=/',

'__utmv':'51854340.1d200-1|2=registration_date=2028=1^3=entry_date=201330318=1'}

headers = {'user-agent':

'Mozilla/5.0 (Windows NT 6.1WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36',

'referer':'http://www.zhihu.com/question/following',

'host':'www.zhihu.com','Origin':'http://www.zhihu.com',

'Content-Type':'application/x-www-form-urlencodedcharset=UTF-8',

'Connection':'keep-alive','X-Requested-With':'XMLHttpRequest','Content-Length':'81',

'Accept-Encoding':'gzip,deflate','Accept-Language':'zh-CN,zhq=0.8','Connection':'keep-alive'

}

#多次访问之后,其实一加载时加载20个问题,具体参数传输就是offset,以20递增

dicc = {"offset":60}

n=20

b=0

# 与爬取图片相同的是,往下拉的时候也会发送http请求返回json数据,但是不同的是,像模拟登录首页不同的是除了

# 发送form表单的那些东西后,知乎是拒绝了我的请求了,刚开始以为是headers上的拦截,往headers添加浏览器

# 访问是的headers那些信息添加上,发现还是拒绝访问。

#想了一下,应该是cookie原因。这个加载的请求和模拟登录首页不同

#所以补上其他的cookies信息,再次请求,请求成功。

for x in xrange(20,460,20):

n = n+20

b = b+20

dicc['offset'] = x

formdata = {'method':'next','params':'{"offset":20}','_xsrf':'20770d88051f0f45e941570645f5e2e6'}

#传输需要json串,和python的字典是有区别的,需要转换

formdata['params'] = json.dumps(dicc)

# print json.dumps(dicc)

# print dicc

circle = requests.post("http://www.zhihu.com/node/ProfileFollowedQuestionsV2",

cookies=cookies,data=formdata,headers=headers)

#response内容 其实爬过一次之后就大同小异了。 都是

#问题返回的json串格式

# {"r":0,

# "msg": ["<div class=\"zm-profile-section-item zg-clear\">\n

# <span class=\"zm-profile-vote-count\">\n<div class=\"zm-profile-vote-num\">205K<\/div>\n

# <div class=\"zm-profile-vote-type\">\u6d4f\u89c8<\/div>\n

# <\/span>\n<div class=\"zm-profile-section-main\">\n

# <h2 class=\"zm-profile-question\">\n

# <a class=\"question_link\" target=\"_blank\" href=\"\/question\/21719532\">

# \u4ec0\u4e48\u4fc3\u4f7f\u4f60\u8d70\u4e0a\u72ec\u7acb\u5f00\u53d1\u8005\u4e4b\u8def\uff1f<\/a>\n

# <\/h2>\n<div class=\"meta zg-gray\">\n<a data-follow=\"q:link\" class=\"follow-link zg-unfollow meta-item\"

# href=\"javascript:\" id=\"sfb-868760\">

# <i class=\"z-icon-follow\"><\/i>\u53d6\u6d88\u5173\u6ce8<\/a>\n<span class=\"zg-bull\">•<\/span>\n63 \u4e2a\u56de\u7b54\n<span class=\"zg-bull\">•<\/span>\n3589 \u4eba\u5173\u6ce8\n<\/div>\n<\/div>\n<\/div>",

# "<div class=\"zm-profile-section-item zg-clear\">\n

# <span class=\"zm-profile-vote-count\">\n

# <div class=\"zm-profile-vote-num\">157K<\/div>\n

# <div class=\"zm-profile-vote-type\">\u6d4f\u89c8<\/div>\n

# <\/span>\n<div class=\"zm-profile-section-main\">\n

# <h2 class=\"zm-profile-question\">\n

# <a class=\"question_link\" target=\"_blank\" href=\"\/question\/31764065\">

# \u672c\u79d1\u6e23\u6821\u7684\u5b66\u751f\u5982\u4f55\u8fdb\u5165\u7f8e\u5e1d\u725b\u6821\u8bfbPhD\uff1f<\/a>\n

# <\/h2>\n<div class=\"meta zg-gray\">\n

# <a data-follow=\"q:link\" class=\"follow-link zg-unfollow meta-item\" href=\"javascript:\" id=\"sfb-4904877\">

# <i class=\"z-icon-follow\"><\/i>\u53d6\u6d88\u5173\u6ce8<\/a>\n<span class=\"zg-bull\">•

# <\/span>\n112 \u4e2a\u56de\u7b54\n<span class=\"zg-bull\">•<\/span>\n1582 \u4eba\u5173\u6ce8\n

# <\/div>\n<\/div>\n<\/div>"]}

# print circle.content

#同样json串需要自己 转换成字典后使用

jsondict = json.loads(circle.text)

msgstr = jsondict['msg']

# print len(msgstr)

#根据自己所需要的提取信息规则写出正则表达式

pattern = 'question\/.*?/a>'

try:

for y in xrange(0,20):

wholequestion = find(pattern, msgstr[y])

pattern2 = '>.*?<'

finalquestion = find(pattern2, wholequestion).replace('>','')

print str(b+y)+" "+finalquestion

#当问题已经访问完后再传参数 抛出异常 此时退出循环

except Exception, e:

print "全部%s个问题" %(b+y)

break

经过一周,现已初步完成,其中多出代码不够美观以及效率不高,还请指点

# _*_ coding:utf-8 _*_

# ==================================================================================

#

# Description: Influence Maximization on Multiple Social Networks

#

# ==================================================================================

import matplotlib.pyplot as plt

import networkx as nx

import heapq

#总图

G = nx.DiGraph()

def load_graph(file):

'''

加载文件为列表格式,并得到G,画出图结构

'''

#将总列表设成全局格式

global gllist

#迭代文件中每个元素

with open(file) as f:

lines = f.readlines()

mylist = [line.strip().split() for line in lines]

gllist = []

#将字符串型转换为整型

for i in mylist:

gllist.append(i[:-2]+map(lambda x: float(x), i[-2:]))

print '初始全局列表:'

print gllist

drawlist=[]

#提取二维列表mylist每行前三个元素,赋给新的列表drawlist

for i in range(len(mylist)):

drawlist.append([])

for j in range(3):

drawlist[i].append(mylist[i][j])

#将列表drawlist加载为有向加权图

G.add_weighted_edges_from(drawlist)

nx.draw(G, with_labels=True, width=1, node_color='y', edge_color='b')

plt.show()

print 'G图中所有节点:',G.nodes()

print 'G图中所有边:',G.edges()

print '\n'

def get_self_node(gllist, target=None):

'''

获取目标节点的自传播节点,返回selflist并包含目标节点

'''

#初始化自传播节点列表

selflist = [target]

#存放已传播节点列表

haslist = []

flag = 0

while (flag != 0):

flag = 0

for target in selflist:

if target not in haslist:

for i in range(len(gllist)):

#判断二维列表中,每行第三个元素是否为1,若为1,则为自传播节点

if ((gllist[i][0] == target)or(gllist[i][1]==target))and(gllist[i][3]==1.0):

if gllist[i][0] == target:

if gllist[i][1] not in haslist:

selflist.append(gllist[i][1])

haslist.append(gllist[i][1])

flag += 1

else:

if gllist[i][0] not in haslist:

selflist.append(gllist[i][0])

haslist.append(gllist[i][0])

flag += 1

#去除重复元素

haslist = set(haslist)

selflist = set(selflist)

#去除重复元素

selflist = set(selflist)

return selflist

def longest_path(gllist,source=None,target=None):

'''

获取起始点到实体的最大路径集合,返回为longestpath列表

'''

longestpath = []

newlist = []

for i in range(len(gllist)):

newlist.append([])

for j in range(3):

newlist[i].append(gllist[i][j])

#构建图结构

G1 = nx.DiGraph()

#添加带权有向边

G1.add_weighted_edges_from(newlist)

#获取目标节点的所有自传播街边,并存入selflist中

selflist = get_self_node(gllist, target)

max_path = 0

val_path = 1

#获取初始节点到目标节点及目标节点的自传播节点的最大路径

for v in selflist:

if v != source:

#遍历两点之间所有路径,并进行比对

for path in nx.all_simple_paths(G1,source=source,target=v):

#判断路径后两个元素是否为相同实体(如:b1->b2)

if is_self_transmit_node(path[-2], v) == 0:

for i in range(0, len(path)-1):

val_path *= G1.get_edge_data(path[i], path[i+1])['weight']

if max_path <val_path:

max_path = val_path

val_path = 1

#若目标节点为起始节点则直接跳出

else: continue ############ 有待商榷 ##############

longestpath.append(max_path)

#返回初始节点到实体的最大路径

return longestpath

def is_self_transmit_node(u, v):

'''

判断目标节点不为起始节点的自传播点

'''

flag = 0

#获得起始节点的所有自传播点

selflist = get_self_node(gllist, v)

for x in selflist:

if u == x:

flag = 1

return flag

def single_strong_infl(longestpath):

'''

计算起始点到实体的传播概率(影响强度),返回影响强度stronginfl

'''

temp = 1

for x in longestpath:

temp *= 1-x

stronginfl = 1-temp

return stronginfl

def all_strong_infl(G):

'''

获得每个节点对实体的影响概率

'''

allstrong = [] #初始化所有节点的加权影响范围列表

gnodes = [] #初始化节点列表

tempnodes = [] #初始化临时节点列表

gnodes = G.nodes()

for u in gnodes:

strong = 0 #存储初始节点对每个实体的影响范围加权,初始化为0

#重置临时节点列表

tempnodes = G.nodes()

for v in tempnodes:

#非自身节点

if u != v:

#判断目标节点不为起始节点的自传播点

if is_self_transmit_node(v, u) == 0:

#获取起始节点到实体间最大加权路径,并存入longestpath

longestpath = longest_path(gllist, u, v)

#去除已遍历目标节点的所有自传播节点

renode = get_self_node(gllist, v)

for x in renode:

if x != v:

tempnodes.remove(x)

#计算起始节点到实体间传播概率(影响强度)

stronginfl = single_strong_infl(longestpath)

strong += stronginfl

#添加单个节点到所有实体的加权影响范围

allstrong.append([u, round(strong, 2)])

#返回每个节点到所有实体的加权影响范围

return allstrong

#output allstrong : [['a1', 2.48], ['a2', 1.6880000000000002], ['b1', 0.7], ['b2', 0], ['c1', 0], ['d2', 0.6]]

def uS_e_uppergain(u, ev, S):

'''

获取节点u在集合S的基础上对实体ev的影响增益, 传入候选节点,上界gain(u|S, ev)

'''

#获取目前实体的所有自传播节点

selflist = get_self_node(gllist, ev)

stronglist = []

#遍历自传遍节点

for v in selflist:

'''

判断节点v是否存在种子集合S中

其中v为单个节点,如v(ev, Gi)

S为种子节点集合,如['a1','a2','b1','b2','c1','d2']

'''

if v in S:

ppSv = 1

else:

longestpath = []

#遍历种子集合

for s in S:

#初始化路径权值与最大路径权值

val_path = 1

max_path = 0

#遍历两点之间所有路径,并进行比对

for path in nx.all_simple_paths(G,source=s,target=v):

#判断路径后两个元素是否为相同实体(如:b1->b2)

if is_self_transmit_node(path[-2], v) == 0:

for i in range(0, len(path)-1):

val_path *= G.get_edge_data(path[i], path[i+1])['weight']

if max_path <val_path:

max_path = val_path

#重置路径权值为1

val_path = 1

#将最大加权路径存入longestpath列表

longestpath.append(max_path)

#得到上界pp(S,v)的影响概率,上界pp(S,v)

ppSv = single_strong_infl(longestpath)

stronglist.append(ppSv)

#得到上界pp(S,ev)的影响概率,上界pp(S,ev)

ppSev = single_strong_infl(stronglist)

#获取pp(u,ev)

ppuev = single_strong_infl(longest_path(gllist, u, ev))

#计算上界gain(u|S,ev)

uSevgain = (1 - ppSev) * ppuev

return uSevgain

def uppergain(u, emu, ems, S):

'''

在已有种子集合S的基础上,求得节点u的影响增益上界,

其中传进参数ems为二维列表,如[['a1',2.48],['a2',1.688]],S则为['a1','a2']

'''

uSgain = 0.0

#遍历emu得到列表形式,得到如['a1',2.48]形式

for ev in emu:

#判断节点是否存在种子集合中

if ev[0] in S:

uSgain += uS_e_uppergain(u, ev[0], S)

else:

uSgain += ev[1]

#返回上界gain(u|S)

return uSgain

def bound_base_imms(G, k):

'''

完全使用影响增益上界的方式选择top-k个种子节点的过程

'''

#初始化emu,H,初始化ems=空集,S=空集

Htemp = []

Htemp = all_strong_infl(G)

H = []

#遍历Htemp=[['a1',2.48],['a2',1.688]],得到如['a1',2.48]形式

for x in Htemp:

#逐个获取二维列表中每一行,形式为['a1',2.48,0]

H.append([x[0],x[1],0])

emu = []

emu = all_strong_infl(G)

ems = []

S = []

for i in range(k):

#提取堆顶元素,tnode的形式为['a1',2.48,0]

tnode = heapq.nlargest(1, H, key=lambda x: x[1])

#将[['b2', 3.1, 0]]格式改为['b2', 3.1, 0]格式

tnode = sum(tnode, [])

while (tnode[2] != i):

gain = 0.0

#获取节点u的影响增益上界

gain = uppergain(tnode, emu, ems, S)

#赋值影响范围

tnode[1] = gain

#修改status

tnode[2] = i

#对堆进行排序

H = heapq.nlargest(len(H), H, key=lambda x: x[1])

#获取堆顶元素

tnode = heapq.nlargest(1, H, key=lambda x: x[1])

tnode = sum(tnode, [])

#添加node到种子集合

S.append([tnode[0]])

#更新ems,添加新节点及节点对每个实体的影响范围加权

ems.append([tnode[0], tnode[1]])

#删除堆顶元素

H.remove(tnode)

print ems

return sum(S, [])

if __name__=='__main__':

#大小为k的种子集合S

k = 60

#加载文件数据,得到图G和初始列表gllist

load_graph('test.txt')

#完全使用影响增益上界值的计算过程函数,打印种子集合S

print '种子集合:',bound_base_imms(G, k)

test.txt

a1 b1 0.2 0

a1 c1 0.8 0

a2 b2 0.4 0

a2 d2 1 0

b1 c1 0.7 0

c2 a2 0.8 0

d2 b2 0.6 0

a1 a2 1 1

a2 a1 0.1 1

....

a1 l1 0.5 0

a1 m1 0.5 0

a1 q1 0.5 0

a1 v1 0.5 0

a1 z1 0.5 0

a1 s1 0.5 0

a1 w1 0.5 0

a1 u1 0.5 0

其中前两列为传播实体,第三列为实体间传播概率,最后一列为0代表同一网络传播,为1代表网络间自传播。

下来要进行优化:

1.采用独立级联模型,设置阈值

2.将最大路径改为最短路径,利用log

python的用途

1、Web开发

Python的诞生历史比Web还要早,由于Python是一种解释型的脚本语言,开发效率高,所以非常适合用来做Web开发。

Python有上百种Web开发框架,有很多成熟的模板技术,选择Python开发Web应用,不但开发效率高,而且运行速度快。

常用的web开发框架有:Django、Flask、Tornado 等。

许多知名的互联网企业将python作为主要开发语言:豆瓣、知乎、果壳网、Google、NASA、YouTube、Facebook……

由于后台服务器的通用性,除了狭义的网站之外,很多App和游戏的服务器端也同样用 Python实现。

2、网络爬虫

许多人对编程的热情始于好奇,终于停滞。

距离真枪实干做开发有技术差距,也无人指点提带,也不知当下水平能干嘛?就在这样的疑惑循环中,编程技能止步不前,而爬虫是最好的进阶方向之一。

网络爬虫是Python比较常用的一个场景,国际上,google在早期大量地使用Python语言作为网络爬虫的基础,带动了整个Python语言的应用发展。以前国内很多人用采集器搜刮网上的内容,现在用Python收集网上的信息比以前容易很多了,如:

从各大网站爬取商品折扣信息,比较获取最优选择;

对社交网络上发言进行收集分类,生成情绪地图,分析语言习惯;

爬取网易云音乐某一类歌曲的所有评论,生成词云;

按条件筛选获得豆瓣的电影书籍信息并生成表格……

应用实在太多,几乎每个人学习爬虫之后都能够通过爬虫去做一些好玩有趣有用的事。

3、人工智能

人工智能是现在非常火的一个方向,AI热潮让Python语言的未来充满了无限的潜力。现在释放出来的几个非常有影响力的AI框架,大多是Python的实现,为什么呢?

因为Python有很多库很方便做人工智能,比如numpy, scipy做数值计算的,sklearn做机器学习的,pybrain做神经网络的,matplotlib将数据可视化的。在人工智能大范畴领域内的数据挖掘、机器学习、神经网络、深度学习等方面都是主流的编程语言,得到广泛的支持和应用。

人工智能的核心算法大部分还是依赖于C/C++的,因为是计算密集型,需要非常精细的优化,还需要GPU、专用硬件之类的接口,这些都只有C/C++能做到。

而Python是这些库的API binding,使用Python是因为CPython的胶水语言特性,要开发一个其他语言到C/C++的跨语言接口,Python是最容易的,比其他语言的门槛要低不少,尤其是使用Cython的时候。

4、数据分析

数据分析处理方面,Python有很完备的生态环境。“大数据”分析中涉及到的分布式计算、数据可视化、数据库操作等,Python中都有成熟的模块可以选择完成其功能。对于Hadoop-MapReduce和Spark,都可以直接使用Python完成计算逻辑,这无论对于数据科学家还是对于数据工程师而言都是十分便利的。

5、自动化运维

Python对于服务器运维而言也有十分重要的用途。由于目前几乎所有Linux发行版中都自带了Python解释器,使用Python脚本进行批量化的文件部署和运行调整都成了Linux服务器上很不错的选择。Python中也包含许多方便的工具,从调控ssh/sftp用的paramiko,到监控服务用的supervisor,再到bazel等构建工具,甚至conan等用于C++的包管理工具,Python提供了全方位的工具集合,而在这基础上,结合Web,开发方便运维的工具会变得十分简单。