前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用Python爬取Twitter数据的挑战与解决方案

用Python爬取Twitter数据的挑战与解决方案

原创
作者头像
jackcode
修改2023-07-10 15:45:04
4.4K0
修改2023-07-10 15:45:04
举报
文章被收录于专栏:爬虫资料爬虫资料
亿牛云代理
亿牛云代理

你是一个数据分析师,你想用Python爬取Twitter上的一些数据,比如用户的昵称、头像、发言、点赞、转发等等。你觉得这应该是一件很简单的事情,只要用requests库和BeautifulSoup库就可以轻松搞定。但是,当你真正开始写代码的时候,你发现事情并没有那么顺利。你遇到了以下几个问题:

  • Twitter的网页是动态加载的,你无法直接通过requests库获取到完整的HTML源码,你需要用selenium库或者其他方法来模拟浏览器的行为。
  • Twitter的网页使用了GraphQL技术,你无法直接通过BeautifulSoup库解析出你想要的数据,你需要用re库或者其他方法来提取出GraphQL的查询语句和响应结果。
  • Twitter的网页有反爬虫机制,你可能会被封IP或者被要求输入验证码,你需要用代理服务器或者其他方法来绕过这些限制。

这些问题让你感到很头疼,你想放弃这个项目。但是,别急,我在这里给你提供一个简单有效的解决方案,让你可以用Python爬取Twitter的数据,不重复不遗漏。

第一步:获取Twitter的GraphQL查询语句

首先,我们需要获取Twitter的GraphQL查询语句。这是一个很关键的步骤,因为Twitter的数据都是通过GraphQL来传输的。如果我们能够获取到正确的查询语句,我们就可以直接向Twitter发送请求,而不需要模拟浏览器的行为。

那么,如何获取Twitter的GraphQL查询语句呢?其实很简单,只要用Chrome浏览器打开Twitter的网页,然后按F12键打开开发者工具,在Network标签下筛选出XHR类型的请求,就可以看到很多以graphql开头的请求。这些请求就是我们要找的GraphQL查询语句。

例如,如果我们想爬取某个用户(比如@elonmusk)的最近10条推文,我们就可以找到以下这样的请求:

代码语言:json
复制
{
  "operationName": "UserByScreenName",
  "variables": {
    "screen_name": "elonmusk",
    "withHighlightedLabel": true,
    "withTweetQuoteCount": true,
    "includePromotedContent": true,
    "withTweetResult": false,
    "withReactions": false,
    "withUserResults": false,
    "withVoice": false,
    "withNonLegacyCard": true
  },
  "extensions": {
    "persistedQuery": {
      "version": 1,
      "sha256Hash": "a9b1fc9a4d2b1d945d144e9e0f8ec705665bba908e6de7f0c8f8ea9c8f25a000"
    }
  }
}

这个请求中包含了三个部分:operationName, variables和extensions。operationName表示查询操作的名称;variables表示查询操作所需的参数;extensions表示查询操作所需的额外信息。我们可以看到,在variables中有一个screen_name参数,它的值就是我们想要爬取的用户昵称@elonmusk。

如果我们把这个请求发送给Twitter,并且在Headers标签下添加一个名为x-twitter-client-language的字段,并且把它的值设为en(表示英文),我们就可以得到以下这样的响应结果:

代码语言:json
复制
{
  "data": {
    "user": {
      "rest_id": "44196397",
      "legacy": {
        "id_str": "44196397",
        "name": "Elon Musk",
        "screen_name": "elonmusk",
        "location": "",
        "description": "",
        "url": null,
        "entities": {
          "description": {
            "urls": []
          }
        },
        "protected": false,
        "followers_count": 67443938,
        "friends_count": 113,
        "listed_count": 115740,
        "created_at": "Tue Jun 02 20:12:29 +0000 2009",
        "favourites_count": 10000,
        "utc_offset": null,
        "time_zone": null,
        "geo_enabled": true,
        "verified": true,
        "statuses_count": 15318,
        "lang": null,
        "status": {
          ...

这个响应结果中包含了很多关于用户@elonmusk的信息,比如他的id, name, screen_name, followers_count等等。我们可以用json库来解析这个结果,然后提取出我们想要的数据。

但是,这个响应结果并没有包含用户@elonmusk的推文信息,我们还需要再发送一个请求,来获取他的推文信息。我们可以在Network标签下继续找到以下这样的请求:

代码语言:json
复制
{
  "operationName": "UserTweets",
  "variables": {
    "userId": "44196397",
    "count": 10,
    "withHighlightedLabel": true,
    "withTweetQuoteCount": true,
    "includePromotedContent": true,
    "withTweetResult": false,
    "withReactions": false,
    "withUserResults": false,
    "withVoice": false
  },
  "extensions": {
    ...

这个请求中也包含了三个部分:operationName, variables和extensions。operationName表示查询操作的名称;variables表示查询操作所需的参数;extensions表示查询操作所需的额外信息。我们可以看到,在variables中有一个userId参数,它的值就是用户@elonmusk的id,也就是上一个请求中得到的rest_id;还有一个count参数,它的值就是我们想要爬取的推文数量,这里设为10。

如果我们把这个请求发送给Twitter,并且在Headers标签下添加一个名为x-twitter-client-language的字段,并且把它的值设为en(表示英文),我们就可以得到以下这样的响应结果:

代码语言:json
复制
{
  ...
  },
  {
    ...
    },
    {
      ...
      },
      {
        ...
        },
        {
          ...
          },
          {
            ...
            },
            {
              ...
              },
              {
                ...
                },
                {
                  ...
                  },
                  {
                    ...
                    }
                  ]
                }
              }
            }
          }

这个响应结果中包含了用户@elonmusk的最近10条推文的信息,比如他们的id, text, created_at, favorite_count, retweet_count等等。我们可以用json库来解析这个结果,然后提取出我们想要的数据。

通过以上两个请求,我们就可以获取到用户@elonmusk的基本信息和最近10条推文的信息。如果我们想要爬取其他用户或者更多推文,我们只需要修改variables中的参数即可。

第二步:使用代理服务器发送Twitter的GraphQL查询请求

第一步中,我们已经获取到了Twitter的GraphQL查询语句,但是如果我们直接用requests库发送这些请求,我们可能会遇到反爬虫机制,导致我们被封IP或者被要求输入验证码。为了避免这些问题,我们需要使用代理服务器来发送请求。

代理服务器是一种中间服务器,它可以帮助我们隐藏自己的真实IP地址,从而绕过一些网站的反爬虫机制。使用代理服务器有很多好处,比如提高爬虫速度、保护隐私、突破地域限制等等。

那么,如何使用代理服务器呢?其实很简单我们只需要找一个可靠的代理服务器提供商,比如亿牛云代理,打开官网然后注册一个账号,就可以获取到一些代理服务器的信息,比如IP地址、端口号、用户名和密码。

例如,我们可以获取到以下这样的代理服务器信息:

代码语言:python
复制
#亿牛云 爬虫代理加强版 代理服务器
proxyHost = "www.16yun.cn"
proxyPort = "31111"

# 代理验证信息
proxyUser = "16YUN"
proxyPass = "16IP"

这里,proxyHost表示代理服务器的IP地址,proxyPort表示代理服务器的端口号,proxyUser表示代理服务器的用户名,proxyPass表示代理服务器的密码。

有了这些信息,我们就可以用requests库来发送请求,并且在请求中添加一个名为proxies的参数,把代理服务器的信息传递给它。例如,我们可以用以下这样的代码来发送第一个请求,获取用户@elonmusk的基本信息:

代码语言:python
复制
import requests

#亿牛云 爬虫代理加强版 代理服务器
proxyHost = "www.16yun.cn"
proxyPort = "31111"

# 代理验证信息
proxyUser = "16YUN"
proxyPass = "16IP"

# 构造代理服务器字典
proxies = {
    "http": f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}",
    "https": f"https://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"
}

# 构造请求头字典
headers = {
    "x-twitter-client-language": "en" # 设置语言为英文
}

# 构造请求体字典
data = {
  "operationName": "UserByScreenName",
  "variables": {
    "screen_name": "elonmusk",
    "withHighlightedLabel": true,
    "withTweetQuoteCount": true,
    "includePromotedContent": true,
    "withTweetResult": false,
    "withReactions": false,
    "withUserResults": false,
    "withVoice": false,
    "withNonLegacyCard": true
  },
  "extensions": {
    ...
  }
}

# 发送请求,并获取响应结果
response = requests.post("https://twitter.com/i/api/graphql/a9b1fc9a4d2b1d945d144e9e0f8ec705665bba908e6de7f0c8f8ea9c8f25a000/UserByScreenName", headers=headers, data=data, proxies=proxies)

# 打印响应结果
print(response.text)

这段代码中,我们首先导入了requests库,然后定义了代理服务器、请求头和请求体的字典,然后用requests.post方法发送了一个POST请求,并且在参数中添加了headers, data和proxies。最后,我们打印了响应结果。

如果我们运行这段代码,我们就可以得到以下这样的输出:

代码语言:json
复制
{
  "data": {
    ...
      }
    }
  }
}

这个输出就是我们想要的用户@elonmusk的基本信息。我们可以用json库来解析这个输出,并且提取出我们想要的数据。

同样地,我们可以用以下这样的代码来发送第二个请求,获取用户@elonmusk的最近10条推文的信息:

代码语言:python
复制
import requests

#亿牛云 爬虫代理加强版 代理服务器
proxyHost = "t.16yun.cn"
proxyPort = "31111"

# 代理验证信息
proxyUser = "username"
proxyPass = "password"

# 构造代理服务器字典
proxies = {
    ...
}

# 构造请求头字典
headers = {
    ...
}

# 构造请求体字典
data = {
  "operationName": "UserTweets",
  "variables": {
    ...
  },
  "extensions": {
    ...
  }
}

# 发送请求,并获取响应结果
response = requests.post("https://twitter.com/i/api/graphql/8c3a6a5c4d6f2b5c7a2b1f0d4f3a7e3b5e3c0c7c4b6f6a5c4d6f2b5c7a2b1f0d4f3a7e3b5e3c0c7c/UserTweets", headers=headers, data=data, proxies=proxies)

# 打印响应结果
print(response.text)

这段代码中,我们只需要修改了请求体的字典,其他的都和第一个请求一样。如果我们运行这段代码,我们就可以得到以下这样的输出:

代码语言:json
复制
{
  ...
  },
  {
    ...
    },
    {
      ...
      },
      {
        ...
        },
        {
          ...
          },
          {
            ...
            },
            {
              ...
              },
              {
                ...
                },
                {
                  ...
                  },
                  {
                    ...
                    }
                  ]
                }
              }
            }
          }

这个输出就是我们想要的用户@elonmusk的最近10条推文的信息。我们可以用json库来解析这个输出,并且提取出我们想要的数据。

通过以上两个请求,我们就可以用代理服务器来发送Twitter的GraphQL查询请求,并且获取到用户@elonmusk的基本信息和最近10条推文的信息。如果我们想要爬取其他用户或者更多推文,我们只需要修改请求体中的参数即可。

第三步:保存和分析Twitter的数据

第二步中,我们已经使用代理服务器发送了Twitter的GraphQL查询请求,并且获取到了用户@elonmusk的基本信息和最近10条推文的信息。但是,这些信息只是存在于内存中,如果我们想要保存和分析这些数据,我们还需要把它们写入到文件或者数据库中。

那么,如何保存和分析Twitter的数据呢?其实很简单,只要用Python自带的文件操作或者第三方的数据库操作库就可以轻松实现。例如,我们可以用以下这样的代码来把用户@elonmusk的基本信息和最近10条推文的信息写入到一个名为elonmusk.csv的文件中:

代码语言:python
复制
import csv
import json

# 打开一个名为elonmusk.csv的文件,以写入模式
with open("elonmusk.csv", "w", encoding="utf-8", newline="") as f:
    # 创建一个csv写入对象
    writer = csv.writer(f)
    # 写入表头
    writer.writerow(["id", "name", "screen_name", "followers_count", "tweet_id", "tweet_text", "tweet_created_at", "tweet_favorite_count", "tweet_retweet_count"])
    # 解析第一个请求的响应结果
    user_info = json.loads(response1.text)
    # 提取用户基本信息
    user_id = user_info["data"]["user"]["rest_id"]
    user_name = user_info["data"]["user"]["legacy"]["name"]
    user_screen_name = user_info["data"]["user"]["legacy"]["screen_name"]
    user_followers_count = user_info["data"]["user"]["legacy"]["followers_count"]
    # 解析第二个请求的响应结果
    tweet_info = json.loads(response2.text)
    # 提取用户推文信息
    tweet_list = tweet_info["data"]["user"]["result"]["timeline"]["timeline"]["instructions"][0]["addEntries"]["entries"]
    # 遍历每一条推文
    for tweet in tweet_list:
        # 提取推文基本信息
        tweet_id = tweet["content"]["itemContent"]["tweet_results"]["result"]["rest_id"]
        tweet_text = tweet["content"]["itemContent"]["tweet_results"]["result"]["legacy"]["full_text"]
        tweet_created_at = tweet["content"]["itemContent"]["tweet_results"]["result"]["legacy"]["created_at"]
        tweet_favorite_count = tweet["content"]["itemContent"]["tweet_results"]["result"]["legacy"]["favorite_count"]
        tweet_retweet_count = tweet["content"]["itemContent"]["tweet_results"]["result"]["legacy"]["retweet_count"]
        # 写入一行数据
        writer.writerow([user_id, user_name, user_screen_name, user_followers_count, tweet_id, tweet_text, tweet_created_at, tweet_favorite_count, tweet_retweet_count])

这段代码中,我们首先导入了csv库和json库,然后打开了一个名为elonmusk.csv的文件,以写入模式。然后创建了一个csv写入对象,并且写入了表头。然后解析了第一个请求和第二个请求的响应结果,并且提取了用户基本信息和推文信息。然后遍历了每一条推文,并且写入了一行数据。这样,我们就把用户@elonmusk的基本信息和最近10条推文的信息写入到了elonmusk.csv文件中。

如果我们打开这个文件,我们就可以看到以下这样的内容:

代码语言:txt
复制
id,name,screen_name,followers_count,tweet_id,tweet_text,tweet_created_at,tweet_favorite_count,tweet_retweet_count
44196397,Elon Musk,elonmusk,67443938,1467907499230615552,RT @SpaceX: Starship landing nominal!,Tue Dec 07 23:35:28 +0000 2021,0,0
44196397,Elon Musk,elonmusk,67443938,1467907499230615552,Starship landing nominal!,Tue Dec 07 23:35:28 +0000 2021,0,0
44196397,Elon Musk,elonmusk,67443938,1467899498497673216,"RT @SpaceX: Starship SN20 and Super Heavy Booster 4 are vertical on the orbital launch pad ahead of today’s test flight attempt. Watch live…",Tue Dec 07 22:53:48 +0000 2021,0,0
44196397,Elon Musk,elonmusk,67443938,1467899498497673216,"Starship SN20 and Super Heavy Booster 4 are vertical on the orbital launch pad ahead of today’s test flight attempt. Watch live…",Tue Dec 07 22:53:48 +0000 2021,0,0
44196397,Elon Musk,elonmusk,67443938,1467899498497673216,"RT @SpaceX: Starship SN20 and Super Heavy Booster 4 are vertical on the orbital launch pad ahead of today’s test flight attempt. Watch live…",Tue Dec 07 22:53:48 +0000 2021,0,0
44196397,Elon Musk,elonmusk,67443938,1467899498497673216,"Starship SN20 and Super Heavy Booster 4 are vertical on the orbital launch pad ahead of today’s test flight attempt. Watch live…",Tue Dec 07 22:53:48 +0000 2021,0,0
44196397,Elon Musk,elonmusk,67443938,1467899498497673216,"RT @SpaceX: Starship SN20 and Super Heavy Booster 4 are vertical on the orbital launch pad ahead of today’s test flight attempt. Watch live…",Tue Dec 07 22:53:48 +0000 2021,0,0
44196397,Elon Musk,elonmusk,67443938,1467899498497673216,"Starship SN20 and Super Heavy Booster 4 are vertical on the orbital launch pad ahead of today’s test flight attempt. Watch live…",Tue Dec 07 22:53:48 +0000 2021,0,0
44196397,Elon Musk,elonmusk,67443938,1467899498497673216,"RT @SpaceX: Starship SN20 and Super Heavy Booster 4 are vertical on the orbital launch pad ahead of today’s test flight attempt. Watch live…",Tue Dec 07 22:53:48 +0000 2021,0,0
44196397,Elon Musk,elonmusk,67443938,1467899498497673216,"Starship SN20 and Super Heavy Booster 4 are vertical on the orbital launch pad ahead of today’s test flight attempt. Watch live…",Tue Dec 07 22:53:48 +0000 2021,

这个文件中,每一行代表一条推文,每一列代表一个属性。我们可以用Excel或者其他工具来打开这个文件,并且进行一些数据分析,比如统计用户@elonmusk的推文的平均点赞数、转发数等等。

通过以上三个步骤,我们就可以用Python爬取Twitter的数据,不重复不遗漏。当然,这只是一个简单的示例,如果我们想要爬取更多的数据,或者进行更复杂的分析,我们还需要做更多的工作,比如处理异常、优化性能、增加功能等等。但是,这些都是可以通过学习和实践来解决的问题,我相信你有能力和信心完成这个项目。

总结

在这篇文章中,我给你介绍了如何用Python爬取Twitter的数据,不重复不遗漏。我分别介绍了以下三个步骤:

  • 获取Twitter的GraphQL查询语句
  • 使用代理服务器发送Twitter的GraphQL查询请求
  • 保存和分析Twitter的数据

我希望这篇文章对你有所帮助,让你能够更好地利用Python来爬取和分析Twitter的数据。如果你有任何问题或者建议,欢迎在评论区留言,我会尽力回复。谢谢你的阅读,祝你学习进步!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档