Twitter网站是用AJAX异步加载的,当对搜索关键词进行检索时,可以用requests请求到保存有数据的json文件,但是需要对url进行处理。
两者相同的参数有以下几个:
self.url = (
f'https://twitter.com/i/api/2/search/adaptive.json?'
f'include_profile_interstitial_type=1'
f'&include_blocking=1'
f'&include_blocked_by=1'
f'&include_followed_by=1'
f'&include_want_retweets=1'
f'&include_mute_edge=1'
f'&include_can_dm=1'
f'&include_can_media_tag=1'
f'&skip_status=1'
f'&cards_platform=Web-12'
f'&include_cards=1'
f'&include_ext_alt_text=true'
f'&include_quote_count=true'
f'&include_reply_count=1'
f'&tweet_mode=extended'
f'&include_entities=true'
f'&include_user_entities=true'
f'&include_ext_media_color=true'
f'&include_ext_media_availability=true'
f'&send_error_codes=true'
f'&simple_quoted_tweet=true'
f'&count=20'
f'&pc=1'
f'&spelling_corrections=1'
f'&ext=mediaStats%2ChighlightedLabel'
)
从网站中可以看到,搜索结果分为5种,下图:
以Top和Photos的参数为例:
self.url = self.url + '&query_source=trend_click'
经过测试cd参数可有可无
self.url = self.url + '&result_filter=image' + '&query_source=typed_query'
在搜索结果中,可以发现第二页的链接相比第一页增加了 cursor 参数,我们查看第一页的请求结果,可以在其中找到cursor的值,因此cursor是根据上一次请求的结果得到的,我们可以用正则表达式提取:
self.cursor_re = re.compile('"(scroll:[^"]*)"')
cursor = self.cursor_re.search(response.text).group(1)
url = self.url + '&cursor={}'.format(quote(cursor))
目前为止,我们已经得到了完整的url。
得到url后进行测试发现得不到对应的json数据,请求头参数如下:
经过测试,在不登陆的情况下,x-guest-token和authorization参数是必须的,通过对比,这两个参数是可重复使用的,authorization的值是固定不变的,而x-guest-token的值与cookie中的gt参数一样,因此我们要先获取cookie。
对于获取cookie的方法这里我使用的是selenium:
def get_cookie(self):
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--disable-infobars")
chrome_options.add_argument('--headless') # 无头浏览器
driver = webdriver.Chrome(options=chrome_options)
driver.get('https://twitter.com/explore')
try:
self.x_guest_token = driver.get_cookie('gt')['value'] # 得到参数的值
except Exception as e:
logging.info('cookie获取失败,请检查后重试!{}'.format(e))
sys.exit()
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
'authorization': 'Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA',
'x-guest-token': self.x_guest_token
}
print('*'*100 + '\n')
print(self.headers)
print('\n' + '*'*100 + '\n')
得到了headers的值,有了第一次请求的成功,就可以得到cursor ,通过更新cursor 参数就可以获取到此关键词下的所有搜索结果。
def start_request(self, cursor=None):
self.get_cookie()
while True:
print('开始关键词{}的第{}页内容抓取!'.format(self.key, self.page))
if cursor:
url = self.url + '&cursor={}'.format(quote(cursor))
else:
url = self.url
response = requests.get(url, headers=self.headers, proxies=self.proxies)
cursor = self.cursor_re.search(response.text).group(1)
json_resp = json.loads(response.text)['globalObjects']
if len(json_resp['tweets']) == 0:
print('关键词{}抓取结束!'.format(self.key))
break
self.parse_tweet_item(json_resp) # 处理得到的json数据
self.page += 1
time.sleep(1)