Web Scraping爬虫 好友关系网 (1)通过BFS制作图、用Networkx 画可视化图表 关系网

文章目录

  • 初始化
    • 介绍
    • 安装包
  • 通过BFS创建一个Graph
    • 通过networkx&BFS创建graph
    • 让我们来看一下这2个graph
      • dictionary
  • 再看一下nx做的graph
  • 好友列表的特质
  • 画图(Networkx)
    • dictionary -> NX object
      • nx object -> 图表
    • 用另一个G2画个图

初始化

介绍

  1. 今天我们爬的是一个好友关系网。原网站:[http://py4e-data.dr-chuck.net/]
  2. 我们可以看到的是每个人的好友列表。
  3. 好友列表里,每个好友都是一个链接。(链接在html里超链接的tag是a
  4. 我们将从一个叫小F的人开始,查看他前五个好友,再点进去他前五个好友的链接里面找到这五个好友的好友。
  5. 当我们找到足够多的人后,用networkx制作可视化的graph。
  6. networkx的documentation文件:https://networkx.github.io/documentation/stable/reference/functions.html

安装包

import urllib.request, urllib.parse, urllib.error
from bs4 import BeautifulSoup
import ssl
import re
from collections import deque

ctx = ssl.create_default_context()
ctx.check_hostname=False
ctx.verify_mode=ssl.CERT_NONE

通过BFS创建一个Graph

  1. 创建一个字典graph(dictionary)。每个人的名字就是一个key,value是一个list,list包括他所有的好友名字
  2. 用BFS从root开始traverse,每次只将这个人前五个好友姓名放进我们的queue中
  3. 只爬k个人。(我这里设置的是20)
  4. 没有被“爬”到,但是是已经被爬到的人的好友的人,仍然放入我们的graph dictionary中,但是list是empty的。
  5. 当爬完k个人,break the loop
  6. 我们最后的graph的长度应该为100.
from collections import deque



graph = {} # 我们的graph


def create_graph(name,level): #name就相当于root 起始人名
    search_queue = deque() # deque是一个数据结构 适用于bfs(dfs用stack)
    search_queue.append(name) # 将我们找到的好友(邻居)都放入这个queue中
    searched = [] # 该数组用于记录检查过的人
    counter = 0 #用于控制我们爬的人数,这里我只爬20人。
    while search_queue: # 只要队列不为空
        if level == counter: #如果到了20人,就自动break
            break
        person = search_queue.popleft() # 就取出其中的第一个人
        if not person in searched: # 仅当这个人没检查过时才检查
            
            person_url = "http://py4e-data.dr-chuck.net/known_by_"+person+".html" #我们的root网站
            html=urllib.request.urlopen(person_url).read()
            soup=BeautifulSoup(html,'html.parser')
            friends = soup("a")
            friends_names = []
            for i in friends[:5]:
                string = i.string
                friends_names.append(string)
                if not string in graph.keys():
                    graph[string] = []
            search_queue+=friends_names
            graph[person] = friends_names
            counter+=1
            
            
            
            
    return graph 
create_graph("Fikret",20)

通过networkx&BFS创建graph

import networkx as nx
G2 = nx.Graph()

def create_nx_graph(name,level):
    search_queue = deque()
    search_queue.append(name) # 将你的邻居都加入到这个搜索队列中
    searched = [] # 该数组用于记录检查过的人
    counter = 0
    while search_queue: # 只要队列不为空
        if level == counter:
            break
        person = search_queue.popleft() # 就取出其中的第一个人
        print(person)
        if not person in searched: # 仅当这个人没检查过时才检查
            
            person_url = "http://py4e-data.dr-chuck.net/known_by_"+person+".html"
            html=urllib.request.urlopen(person_url).read()
            soup=BeautifulSoup(html,'html.parser')
            friends = soup("a")
            friends_names = []
            for i in friends[:5]:
                string = i.string
                friends_names.append(string)
                G2.add_edge(person,string)
                
            search_queue+=friends_names
            
            counter+=1

create_nx_graph("Fikret",20)

让我们来看一下这2个graph

dictionary

print(len(graph))
graph.keys()
100
dict_keys(['Aniqa', 'Ogheneruno', 'Montgomery', 'Owain', 'Haniyah', 'Fikret', 'Klevis', 
'Beatriz', 'Isimeli', 'Mahum', 'Bhaaldeen', 'Peyton', 'Romi', 'Reis', 'Turki', 'Aria', 'Joris', 
'Lexis', 'Mhairade', 'Boudicca', 'Anay', 'Jazmine', 'Cahlum', 'Thierry', 'Filip', 'Billy', 'Demira', 
'Kaydie', 'Mehmet', 'Tabbitha', 'Amii', 'Nawfal', 'Gioia', 'Bryson', 'Liyah', 'Braydon', 'Mathew', 
'Sabila', 'Fergal', 'Nagib', 'Harold', 'Sajid', 'Ceitidh', 'Caisey', 'Aroob', 'Munashe', 'Saharra', 
'Sanaa', 'Cathal', 'Maryk', 'Titi', 'Autumn', 'Kasper', 'Jessamy', 'Merissa', 'Rico', 'Amyrose',
 'Aiyana', 'Christianna', 'Siya', 'Alfy', 'Francesco', 'Sohera', 'Ismail', 'Jules', 'Israa', 'Eamon',
 'Korbyn', 'Carri', 'Jonatan', 'Frances', 'Jemima', 'Jeremy', 'Kdi', 'Chibudom', 'Alvin', 
 'Nerisse', 'Wardah', 'Juliana', 'Atika', 'Bezalel', 'Avsta', 'Carly', 'Leland', 'Lyall', 'Dagon', 
 'Lanah', 'Fion', 'Tanith', 'Mena', 'Aneliese', 'Seze', 'Butchi', 'Kaily', 'Macey', 'Devon', 
 'Argyle', 'Archibald', 'Johansson', 'Amarah'])

果然是爬到了100个人。

再看一下nx做的graph

print(G2.number_of_nodes())
G2.nodes()

也是100人~~ 是完全一样的两个图

100
NodeView(('Fikret', 'Aniqa', 'Ogheneruno', 'Montgomery', 'Owain', 'Haniyah', 'Klevis', 'Beatriz', 'Isimeli', 'Mahum', 'Bhaaldeen', 'Peyton', 'Romi', 'Reis', 'Turki', 'Aria', 'Joris', 'Lexis', 'Mhairade', 'Boudicca', 'Anay', 'Jazmine', 'Cahlum', 'Thierry', 'Filip', 'Billy', 'Demira', 'Kaydie', 'Mehmet', 'Tabbitha', 'Amii', 'Nawfal', 'Gioia', 'Bryson', 'Liyah', 'Braydon', 'Mathew', 'Sabila', 'Fergal', 'Nagib', 'Harold', 'Sajid', 'Ceitidh', 'Caisey', 'Aroob', 'Munashe', 'Saharra', 'Sanaa', 'Cathal', 'Maryk', 'Titi', 'Autumn', 'Kasper', 'Jessamy', 'Merissa', 'Rico', 'Amyrose', 'Aiyana', 'Christianna', 'Siya', 'Alfy', 'Francesco', 'Sohera', 'Ismail', 'Jules', 'Israa', 'Eamon', 'Korbyn', 'Carri', 'Jonatan', 'Frances', 'Jemima', 'Jeremy', 'Kdi', 'Chibudom', 'Alvin', 'Nerisse', 'Wardah', 'Juliana', 'Atika', 'Bezalel', 'Avsta', 'Carly', 'Leland', 'Lyall', 'Dagon', 'Lanah', 'Fion', 'Tanith', 'Mena', 'Aneliese', 'Seze', 'Butchi', 'Kaily', 'Macey', 'Devon', 'Argyle', 'Archibald', 'Johansson', 'Amarah'))

好友列表的特质

好友是“互相”的,而不是“单箭头的”。所以我们的图应该是一个non-directional Graph

画图(Networkx)

dictionary -> NX object

在Networkx中,我们可以要求graph为non-directional或者directional
因为是“好友关系网”不是“关注关系网”,所以我们应该选择没有指向性的nx.Graph().
还可以选的包括:nx.DiGraph(),nx.MultiGraph()

接下来,我将graph dictionary中的所有node和edge添加到这个新建的nx graph中。

import networkx as nx # 载入networkx安装包
G = nx.Graph() 
for i in graph.keys():
    G.add_node(i)
    for j in graph[i]:
        G.add_edge(i,j)

nx object -> 图表

我们可以修改图表大小
我们还可以在nx.draw里面修改字体大小、node小圆点大小,以及小圆点颜色和edge颜色~

import matplotlib.pyplot as plt

plt.figure(figsize = (10,9)) #这是我选定的size
nx.draw(G,pos = nx.random_layout(G),node_color = 'b',edge_color = 'grey',with_labels = True,font_size =8,node_size =20)

在这里插入图片描述
Web Scraping爬虫 好友关系网 (1)通过BFS制作图、用Networkx 画可视化图表 关系网_第1张图片

用另一个G2画个图

其实是一毛一样的,只是画图有一定的随机性 所以长得不一样~~

lt.figure(figsize = (10,9))
nx.draw(G2,pos = nx.random_layout(G2),node_color = 'b',edge_color = 'grey',with_labels = True,font_size =8,node_size =20)
plt.show()

Web Scraping爬虫 好友关系网 (1)通过BFS制作图、用Networkx 画可视化图表 关系网_第2张图片

谢谢大家~~
下次想试一下用英雄联盟的官方api 爬韩服前100的rank?

你可能感兴趣的:(爬虫,图论)