首页 > 其他分享 >基于社交网络爬虫分析人物兴趣属性(一)

基于社交网络爬虫分析人物兴趣属性(一)

时间:2023-07-27 23:06:34浏览次数:33  
标签:min text 爬虫 re json position line 社交 属性


这次做的一个项目中涉及人物画像,做人物画像中兴趣属性很关键的一点就是要收集足够多的人物数据,基础工作就是进行爬虫的书写,收集数据集。对于一个社交网络来说,这里最大最实用的数据集合就是用户发布的帖子,因为里面的东西会关联到个人的兴趣爱好,甚至工作生活,从中做主题提取就可以大致的看出来人物在这个社交网络上所体现出来的一个兴趣属性。
经久不衰的话题----白帽子安全条款:不用爬虫爬取个人隐私!

所以我对于社交网络的选择标准:
1.国外社交网络-----推特;
2.只爬取网站上公开发布的用户信息。

由于模拟登录过于频繁还是会被网站封ip和账号,因此就想能不能实现免登录状态下的爬虫,爬取用户数据。

用户id爬取

推特上用来标识用户身份的标志可不是用户名,因为用户名是可以重复的,比如我搜索tolly这个用户,会发现有好多用户名叫tolly的。

基于社交网络爬虫分析人物兴趣属性(一)_用户名

但是他们的用户id却是唯一的:

基于社交网络爬虫分析人物兴趣属性(一)_用户名_02

红色框中的就是用户id。即使用户名相同,id也不会相同,那么我们来看一下用户主页:
这里随便找了一个国外小哥的主页,发现其实域名就是twitter.com + 用户id。

基于社交网络爬虫分析人物兴趣属性(一)_json_03

因此我们首先要通过爬虫获取到用户id,才能进行下一步的数据爬取:
查询的api接口为:
https://twitter.com/search?f=users&vertical=default&q=smity&src=unkn

q参数输入的就是在你要查询的昵称大致是什么样子,也就是你在搜索框输入的东西。

如果我们直接requests请求这个连接,那么返回的东西就会是一堆带着html标签的文本,很难看。所以我们必须分析用户名在哪种标签里,id在哪种标签里。

基于社交网络爬虫分析人物兴趣属性(一)_twitter_04

基于社交网络爬虫分析人物兴趣属性(一)_json_05

上图就是爬取出来的带有很多html标签的文本,我们可以看到用户名是在<div>标签中的data-name参数中,然后data-screnn-name和下一段的<span class中都有着MrNastyPantz这个id,影响不大,你选择哪个标签做正则都是可以的。

我选择的是data-name和span,个人观念是最好不在同一个标签中做正则提取,会有很多意想不到的问题。
因此这个正则这么写:
用户名:

data-name="(.*?) data-protected="false"
Id:
<span class="username u-dir" dir="ltr">@<b class="u-linkComplex-target">(.*?)</b></span>

所以加入正则以后的爬虫代码为:

import requests
import re
import sys
#查询用户名id
url='https://twitter.com/search?f=users&vertical=default&q='+sys.argv[1]+'&src=unkn'
proxies={'http': 'http://127.0.0.1:10809', 'https': 'http://127.0.0.1:10809'}
search = requests.get(url,proxies=proxies)


search.encoding = 'utf-8'
print('查询成功')
text=search.text
print(re.findall(r'data-name="(.*?) data-protected="false"',text))
print('\n')
print(re.findall(r'<span class="username u-dir" dir="ltr">@<b class="u-linkComplex-target">(.*?)</b></span>',text))

运行命令为:
Python twitter_userid_sucess.py + 你要爬取的用户名(在搜索框输入的东西)
运行效果为:

基于社交网络爬虫分析人物兴趣属性(一)_json_06

上面为用户名,对应下面的id。
因为有输入一个smity会有很多用户与之相似,所以会有不止一个结果。

用户tweets爬取
做完了id的爬取,我们自然就可以直接通过id定位到你想爬取的用户tweets主页。
我选取的是https://twitter.com/BeSmity
一个社交网络类似*博,推特,脸书这样的,有没有实现免登录爬取信息的可能性,就要看你在不登录的状态下,能否通过浏览器页面看到你想看的信息,推特页面如下:

基于社交网络爬虫分析人物兴趣属性(一)_用户名_07

可以看到这里我们是在一个没有登录的状态下,看到了该用户的tweets和个人简介还有用户id,然后我们利用鼠标滚轮下滑。不断的往下翻就可以看到这个用户的所有推文,代表着其实我们不用登录推特账户就可以看到这个用户的很多信息。

基于社交网络爬虫分析人物兴趣属性(一)_用户名_08

但是也有一部分信息看不到,比如我们点击这个用户的粉丝和关注页面,或者点击用户头像,会发现其实还是需要登录以后才可查看。

基于社交网络爬虫分析人物兴趣属性(一)_用户名_09

有了这个,我们就来看我们当然想到可以用requests直接请求页面,于是这里很多人就会考虑到直接,requests.get(‘https://twitter.com/BeSmity’),我们看一下返回结果:

基于社交网络爬虫分析人物兴趣属性(一)_twitter_10

确实有抓到这个用户的tweets,但是发现好像这个只是一条在11月25号的tweets,这个帖子之后还有很多帖子我们没有看到,但是我们明明是可以看到所有的推文的啊,这里却显示了一部分,这个是怎么回事呢?

基于社交网络爬虫分析人物兴趣属性(一)_用户名_11

我们尝试着继续滚轮下滑,然后发现每滚过一段距离,就会有一个短暂的卡顿,于是我们截取那个卡顿发送的网络数据包:

基于社交网络爬虫分析人物兴趣属性(一)_用户名_12

原来这个卡顿是发送了一个ajax请求,来进行进一步的页面获取,俗称异步页面更新,也就是在不刷新页面的情况下,直接更新页面的内容,可以保证用户不用每次都重新打开页面查看新内容。

所以我们只请求https://twitter.com/BeSmity是绝对不够,他只会返回第一次异步更新之前的值,所以我们需要自己手动模拟这个ajax请求。
观察数据包,我们可以看到红色箭头指向的地方有一个max_position,为什么关注这个,一个是因为它有position这个标志位,另外一个是因为这个请求的返回包里面有一个min_position。

基于社交网络爬虫分析人物兴趣属性(一)_twitter_13

这个min_position恰好就在第一个,所以我们记录一下当前的这两个标志位。
max_position=1197617887390900237
min_position=1184647192977514496
然后我们继续滚动鼠标滚轮翻页看看会有什么内容

突然又是一阵卡顿,我们知道这个时候网页又发送了一个异步更新请求了,赶紧截取查看一下流量包:

基于社交网络爬虫分析人物兴趣属性(一)_json_14

复制一下请求的url,我们发现这个时候的max_position变成了上一次ajax请求时返回包中的min_position。

https://twitter.com/i/profiles/show/BeSmity/timeline/tweets?include_available_features=1&include_entities=1&max_position=1184647192977514496&reset_error_state=false

基于社交网络爬虫分析人物兴趣属性(一)_用户名_15

并且它还继续在返回包里面给我们发送了一个min_position,我们大胆猜测,其实max_posotion记录的就是当前页的位置编码,然后在请求包中会返回一个下一页的请求编码,那么如果用户想查看下一页的内容,网页就会用这个min_position作为下一页的max_position发送请求来更新下一页内容。

那么如果到了最后一页呢,果不其然,最后一页的响应包中min_position的值位null,意味着没有下一页了。

基于社交网络爬虫分析人物兴趣属性(一)_twitter_16

现在关键是要获取第一个min_position,我们尝试着去访问一下不带max_position的请求,https://twitter.com/i/profiles/show/BeSmity/timeline/tweets?include_available_features=1&include_entities=1

基于社交网络爬虫分析人物兴趣属性(一)_twitter_17

果然就是最初始的min_position,那么我们的爬虫流程就是先访问初始url,获取到第一个min_position后,循环获取以上一个min_position作为max_position的url的页面内容,并且接受它返回的min_position,再作为下一个页面的max_position。

这下我们的爬虫就很好写了,首先利用json.loads解析返回的响应包,获取min_position。
text_json=json.loads(tweets.text)
然后根据第一次的json数据我们很容易得知”items_html”就是我们需要的页面内容。

提取步骤一
这里有几个做提取的坑给大家填了,一个是items_html里面有些地方有回车符,正则表达式匹配回车符将会变得十分麻烦,所以一定要先去掉html内容中所有回车符,没有去除回车的效果如下:

基于社交网络爬虫分析人物兴趣属性(一)_用户名_18

红框处都是回车符,会导致内容截断,所以我们需要如下操作:

text=text_json["items_html"].replace('\n','')

提取步骤二
第二个是想要提取帖子内容一定要用取的形式,从标签里面先取,然后再删除多余内容,直接删除所有标签会导致代码没有重用性而且去除很麻烦。
帖子的内容位于这个标签内:

<p class="TweetTextSize TweetTextSize--normal js-tweet-text tweet-text" data-aria-label-part="0">*****</p>

但是由于语言的不同,这个标签还会有如下形式:

<p class="TweetTextSize TweetTextSize--normal js-tweet-text tweet-text" data-aria-label-part="0">*****</p>
<p class="TweetTextSize TweetTextSize--normal js-tweet-text tweet-text" data-aria-label-part="0">*****</p>

因此我们依据标签中都有的data-aria-label-part属性设置取出帖子文本的正则为:

content=re.findall(r'data-aria-label-part="0">(.*?)</p>',text)

这样提取之后,我们的内容就被简化为如下效果:

基于社交网络爬虫分析人物兴趣属性(一)_用户名_19

会发现还是有很多杂质在里面

提取步骤三
因此我们继续做如下处理,首先分析提取的东西结构,里面含有很多<a>标签和unicode编码字符,@其他用户的语句,以及一些固定的url,我们都将其去除或者替换。

基于社交网络爬虫分析人物兴趣属性(一)_用户名_20

pattern =re.compile(r'<[^>]+>|pic.twitter.com/.*|http(.*?) |',re.S)
line = re.sub(pattern ,'',line)
line = re.sub(''' ,'\'',line)
line = re.sub('<','<',line)
line = re.sub('>','>',line)
line = re.sub('&','&',line)
line = re.sub('"','"',line)
line = re.sub(r'^@(.*?) @(.*?) |^@(.*?) ','',line)

这样的到的就是我们干净的文本,每一行的内容都是一个tweets。

基于社交网络爬虫分析人物兴趣属性(一)_json_21

最后加上我们的新请求构造,取下一个max_position的页面内容

tweets=requests.get(url+'&max_position='+text_json["min_position"]+'&reset_error_state=false',proxies=proxies)

整体代码如下:

import requests
import json
import re
import sys
#返回一个json,里面有min-position
#这个地方可以用下面这个url获取到最开始的max_position,当前页面用的是max_position,然后响应包json里的min_position就是下一页的max_position,循环获取,直到没有min_position。
url="https://twitter.com/i/profiles/show/"+sys.argv[1]+"/timeline/tweets?include_available_features=1&include_entities=1"
proxies={'http':'127.0.0.1:10809','https':'127.0.0.1:10809'}
tweets=requests.get(url,proxies=proxies)
tweets.encoding="utf-8"
#这个地方一定要写入一行content作为标题,不然后面的lda.py会报错
with open("./text.txt",'w',encoding='utf-8') as f:
  f.write("content"+'\n')
with open("./text.txt",'a',encoding='utf-8') as f:
  text_json=json.loads(tweets.text)
  while(text_json["min_position"]):
    print(text_json["min_position"]+'\n')
    #items_html里面有些地方有回车符,导致正则不能提取帖子文本,一定要先去掉所有回车符
    text=text_json["items_html"].replace('\n','')
    #这个地方应该要用取得形式,从标签里面先取,然后再删除,版本一是直接删除所有标签这样做代码没有重用性而且去除很麻烦
    content=re.findall(r'data-aria-label-part="0">(.*?)</p>',text)
    for line in content:
      #把多余标签,pic.twitter.com和url去掉
      pattern = re.compile(r'<[^>]+>|pic.twitter.com/.*|http(.*?) |',re.S)
      line = re.sub(pattern ,'',line)
      line = re.sub(''' ,'\'',line)
      line = re.sub('<','<',line)
      line = re.sub('>','>',line)
      line = re.sub('&','&',line)
      line = re.sub('"','"',line)
      line = re.sub(r'^@(.*?) @(.*?) |^@(.*?) ','',line)
      if(len(line)):
        #continue
        f.write(line+'\n')
    tweets=requests.get(url+'&max_position='+text_json["min_position"]+'&reset_error_state=false',proxies=proxies)
    text_json=json.loads(tweets.text)
print("finish work")

代码运行后,每爬取一个页面就会返回下一个页面的max_position,如果没有下一页,就会结束爬取。

基于社交网络爬虫分析人物兴趣属性(一)_twitter_22

可以提前用ctrl+c结束脚本运行,不论是否爬取完毕,都会在同目录下生成一个text.txt文件用于存放爬取的数据。
下一章节我们将继续分析如何利用这些爬取的数据进行主题提取。


标签:min,text,爬虫,re,json,position,line,社交,属性
From: https://blog.51cto.com/u_14601424/6874968

相关文章

  • 爬虫 | 产品经理书单抓取
    本实验将讲解BeautifulSoup4库解析HTML的常见用法,它的中文名字是「美丽汤」。在使用pip安装该库时的名字是beautifulsoup4,在使用该库时包的名字是bs4,要注意它们的区别。BeautifulSoup4专注于解析HTML/XML源码并提取想要的信息,也就是我们在使用爬虫工具爬取页......
  • 爬虫基本工具:urllib丶requests丶selenium丶pytesseract
    urllib来实现cookie和ip代理1fromurllib.requestimportRequest,build_opener,urlopen2fromfake_useragentimportUserAgent3fromurllib.parseimporturlencode4fromurllib.requestimportHTTPCookieProcessor5fromhttp.cookiejarimportCookieJ......
  • 基于Python的HTTP代理爬虫开发初探
     在数字化时代,网络数据的获取对于企业和个人都变得至关重要。然而,许多网站为了保护其数据和资源,采取了反爬虫措施,使得我们无法直接访问和获取所需的信息。这时,HTTP代理爬虫就成为了一项强大的工具,它可以帮助我们绕过限制,有效地进行数据采集。在本文中,将介绍基于Python的HTTP代理......
  • 24质量属性易用性和可测试性
    易用性:完成某个期望任务的容易程度和系统所提供的用户支持种类如:界面友好、新用户学习系统时间不超过2小时可测试性:通过测试揭示软件缺陷的容易程度如:提供远程测试接口,支持远程测试 ......
  • 22质量属性安全性
    安全性:系统向合法用户提供服务的同时可以拒绝非授权用户使用的企图或拒绝服务的能力。安全性分,机密性(防泄密)、完整性(防止被篡改)、不可否认性(防止抵赖)、可控性(信息的传播具有控制能力)如:可抵御SQL注入攻击对计算机操作有完整记录授权必须保证99.9%可用 提高安全性的策略:抵抗......
  • 23质量属性可修改性
    可修改性:能够够快的以较高的性价比对系统进行变更的能力。如:更改系统报表必须在2人周内完成、进行修改,必须在4人月内完成提高可修改性策略:局部修改:维持语义一致性、预期期望的变更、泛化模块、限制可能的选择、抽象通用服务防止连锁反应:隐藏信息、维持现有的接口、限制通信路径......
  • 20质量属性-性能
    性能:指系统的响应能力,多长时间能对某事进行响应,或者时间内可以处理的事件的个数。如:同时支持1000个并发,响应时间小于1S,分辨率达到4K提升性能的策略:资源需求:提高计算效率、减少计算开销、管理事件率、控制采样频率资源管理:引入并发、维持多个副本、增加可用资源资源仲裁:先进先......
  • 爬虫例子:抓取电影信息
    1importrequests2fromtimeimportsleep3fromlxmlimportetree4fromfake_useragentimportUserAgent5fromrandomimportrandint6importre7fromthreadingimportThread8fromqueueimportQueue9fromosimportremove10from......
  • swagger文档请求参数为文件属性添加选择文件按钮
    在编写接口时,将所有参数封装到实体中,其中就包含MultipartFile类型的参数eg:参数实体:User@ApiModel(value="用户实体类")@DatapublicclassUser{@ApiModelProperty(value="用户名")publicStringuserName;@ApiModelProperty(value="密码")public......
  • [爬虫]2.3.1 使用Python操作文件系统
    Python提供了许多内置库来处理文件系统,如os、shutil和pathlib等,这些库可以帮助你创建、删除、读取、写入文件和目录。读取文件在Python中,你可以使用内置的open函数来打开一个文件。open函数返回一个文件对象,你可以对这个对象进行各种操作。以下是一个读取文件的例子:withopen(......