「利用者:夜泣き/スクリプト」の版間の差分
ナビゲーションに移動
検索に移動
編集の要約なし
>Fet-Fe 編集の要約なし |
>Fet-Fe 編集の要約なし |
||
6行目: | 6行目: | ||
''' | ''' | ||
ver2.1. | ver2.1.5 2022/9/24恒心 | ||
当コードは恒心停止してしまったhttps://rentry.co/7298gの降臨ショーツイート自動収集スクリプトの復刻改善版です | 当コードは恒心停止してしまったhttps://rentry.co/7298gの降臨ショーツイート自動収集スクリプトの復刻改善版です | ||
65行目: | 65行目: | ||
##生きているのはhttps://github.com/zedeus/nitter/wiki/Instancesで確認 | ##生きているのはhttps://github.com/zedeus/nitter/wiki/Instancesで確認 | ||
##末尾にスラッシュ必須 | ##末尾にスラッシュ必須 | ||
NITTER_INSTANCE: Final[str] = 'http:// | NITTER_INSTANCE: Final[str] = 'http://26oq3gioiwcmfojub37nz5gzbkdiqp7fue5kvye7d4txv4ny6fb4wwid.onion/' | ||
##archive.todayの魚拓 | ##archive.todayの魚拓 | ||
141行目: | 141行目: | ||
self._txt_data: list[str] = [] | self._txt_data: list[str] = [] | ||
self._limit_count: int = 0 ##記録数 | self._limit_count: int = 0 ##記録数 | ||
self._proxy_is_needed: bool = False ## アクセスにプロキシが必要かどうか | |||
self._check_slash() ##スラッシュが抜けてないかチェック | self._check_slash() ##スラッシュが抜けてないかチェック | ||
self. | self._proxy_is_needed = self._check_tor_proxy_is_needed() ##Torが使えているかチェック | ||
self._check_instance() ##インスタンスが死んでないかチェック | self._check_instance() ##インスタンスが死んでないかチェック | ||
##Invidiousのインスタンスリストの正規表現パターンを取得 | |||
invidious_url_tuple: Final[tuple[str]] = self._invidious_instances() | |||
self._invidious_pattern: Final[re.Pattern] = re.compile('|'.join(invidious_url_tuple)) | |||
##ユーザー名取得 | ##ユーザー名取得 | ||
182行目: | 186行目: | ||
##失敗かどうかは呼出側で要判定 | ##失敗かどうかは呼出側で要判定 | ||
def _request_once(self, url: Final[str]) -> Response: | def _request_once(self, url: Final[str]) -> Response: | ||
res: Response = requests.get(url, timeout=self.REQUEST_TIMEOUT, headers=self.HEADERS, allow_redirects=False, proxies=self.PROXIES) | if self._proxy_is_needed: | ||
res: Response = requests.get(url, timeout=self.REQUEST_TIMEOUT, headers=self.HEADERS, allow_redirects=False, proxies=self.PROXIES) | |||
else: | |||
res: Response = requests.get(url, timeout=self.REQUEST_TIMEOUT, headers=self.HEADERS, allow_redirects=False) | |||
sleep(self.WAIT_TIME) ##DoS対策で待つ | sleep(self.WAIT_TIME) ##DoS対策で待つ | ||
return res | return res | ||
218行目: | 225行目: | ||
##Torが使えているかチェック | ##Torが使えているかチェック | ||
def | def _check_tor_proxy_is_needed(self) -> bool | NoReturn: | ||
initial_proxy_is_needed: bool = self._proxy_is_needed | |||
print('Torのチェック中ですを') | print('Torのチェック中ですを') | ||
# プロキシなしでTorにアクセスできるかどうか | |||
self._proxy_is_needed = False | |||
res: Response = self._request_once('https://check.torproject.org/api/ip') ##リクエスト | |||
is_tor: bool = json.loads(res.text)['IsTor'] | |||
if is_tor: | |||
print('Tor connection OK') | |||
self._proxy_is_needed = initial_proxy_is_needed | |||
return False | |||
# プロキシありでTorにアクセスできるかどうか | |||
self._proxy_is_needed = True | |||
try: | try: | ||
res | res = self._request_once('https://check.torproject.org/api/ip') ##リクエスト | ||
is_tor | is_tor = json.loads(res.text)['IsTor'] | ||
if is_tor: | if is_tor: | ||
print('Tor OK') | print('Tor proxy OK') | ||
self._proxy_is_needed = initial_proxy_is_needed | |||
return True | |||
else: | else: | ||
raise RuntimeError('サイトにTorのIPでアクセスできていないなりを') | raise RuntimeError('サイトにTorのIPでアクセスできていないなりを') | ||
245行目: | 266行目: | ||
print('インスタンスが死んでますを', file=sys.stderr) | print('インスタンスが死んでますを', file=sys.stderr) | ||
exit(1) | exit(1) | ||
##Invidiousのインスタンスのタプルを取得 | |||
def _invidious_instances(self) -> tuple[str] | NoReturn: | |||
print("Invidiousのインスタンスリストを取得中ですを") | |||
invidious_json: Response | None = self._request('https://api.invidious.io/instances.json') | |||
if invidious_json is None: | |||
print("Invidiousが死んでますを") | |||
exit(1) | |||
instance_list: list[str] = [] | |||
for instance_info in json.loads(invidious_json.text): | |||
instance_list.append(instance_info[0]) | |||
return tuple(instance_list) | |||
##ツイート収集するユーザー名を取得 | ##ツイート収集するユーザー名を取得 | ||
388行目: | 422行目: | ||
poll_txt: str = '' | poll_txt: str = '' | ||
if tweet_poll is not None: | if tweet_poll is not None: | ||
poll_meters = tweet_poll.select('.poll-meter') | poll_meters: Final[bs4.element.ResultSet] = tweet_poll.select('.poll-meter') | ||
poll_txt += '<br>\n' | poll_txt += '<br>\n' | ||
for poll_meter in poll_meters: | for poll_meter in poll_meters: | ||
poll_txt += '<br>\n ' + poll_meter.select_one('.poll-choice- | ratio: str = poll_meter.select_one('.poll-choice-value').text | ||
poll_txt += '<br>\n ' + tweet_poll.select_one('.poll-info').text | if 'leader' in poll_meter['class']: | ||
poll_txt += f'<br>\n <span style="display: inline-block; width: 30em; background: linear-gradient(to right, rgba(29, 155, 240, 0.58) 0 {ratio}, transparent {ratio} 100%); font-weight: bold;">' + ratio + ' ' + poll_meter.select_one('.poll-choice-option').text + '</span>' | |||
else: | |||
poll_txt += f'<br>\n <span style="display: inline-block; width: 30em; background: linear-gradient(to right, rgb(207, 217, 222) 0 {ratio}, transparent {ratio} 100%);">' + ratio + ' ' + poll_meter.select_one('.poll-choice-option').text + '</span>' | |||
poll_txt += '<br>\n <span style="font-size: small;">' + tweet_poll.select_one('.poll-info').text + '</span>' | |||
return poll_txt | return poll_txt | ||
405行目: | 443行目: | ||
continue | continue | ||
tweet_url: str = urljoin(self.TWITTER_URL, re.sub('#[^#]*$', '', tweet.find(class_='tweet-link').get('href'))) ##ツイートのURL作成 | tweet_url: str = urljoin(self.TWITTER_URL, re.sub('#[^#]*$', '', tweet.find(class_='tweet-link').get('href'))) ##ツイートのURL作成 | ||
date = self._tweet_date(tweet) | date: datetime = self._tweet_date(tweet) | ||
if date.year != self._date.year or date.month != self._date.month or date.day != self._date.day: | if date.year != self._date.year or date.month != self._date.month or date.day != self._date.day: | ||
self._next_day(date) | self._next_day(date) | ||
457行目: | 495行目: | ||
urls_in_tweet: Final[bs4.element.ResultSet] = tag.find_all('a') | urls_in_tweet: Final[bs4.element.ResultSet] = tag.find_all('a') | ||
for url in urls_in_tweet: | for url in urls_in_tweet: | ||
if | if url.get('href').startswith('https://') or url.get('href').startswith('http://'): ##先頭にhttpが付いていない物はハッシュタグの検索ページへのリンクなので処理しない | ||
if | if url.get('href').startswith('https' + self.NITTER_INSTANCE[4:]): | ||
#Nitter上のTwitterへのリンクを直す | #Nitter上のTwitterへのリンクを直す | ||
url_link: str = url.get('href').replace('https' + self.NITTER_INSTANCE[4:], self.TWITTER_URL) | url_link: str = url.get('href').replace('https' + self.NITTER_INSTANCE[4:], self.TWITTER_URL) | ||
url_link = re.sub('\?.*$', '', url_link) | url_link = re.sub('\?.*$', '', url_link) | ||
url.replace_with(self._archive_url(url_link, url_link)) ##テンプレートArchiveに変化 | url.replace_with(self._archive_url(url_link, url_link)) ##テンプレートArchiveに変化 | ||
elif | elif self._invidious_pattern.search(url.get('href')): | ||
# | #Nitter上のYouTubeへのリンクをInvidiousのものから直す | ||
url_link: str = url.get('href') | url_link: str = url.get('href') | ||
url_link = | url_link = self._invidious_pattern.sub('youtu.be', url_link) | ||
url.replace_with(self._archive_url(url_link, url_link)) ##テンプレートArchiveに変化 | url.replace_with(self._archive_url(url_link, url_link)) ##テンプレートArchiveに変化 | ||
else: | else: | ||
656行目: | 693行目: | ||
タトゥーに対してのアンケートを取りたいと思います。<br> | タトゥーに対してのアンケートを取りたいと思います。<br> | ||
<br> | <br> | ||
35% タトゥーは文化だ。<br> | <span style="display: inline-block; width: 30em; background: linear-gradient(to right, rgb(207, 217, 222) 0 35%, transparent 35% 100%);">35% タトゥーは文化だ。</span><br> | ||
65% タトゥーは文化じゃない。<br> | <span style="display: inline-block; width: 30em; background: linear-gradient(to right, rgba(29, 155, 240, 0.58) 0 65%, transparent 65% 100%); font-weight: bold;">65% タトゥーは文化じゃない。</span><br> | ||
717 votes • Final results | <span style="font-size: small;">717 votes • Final results</span> | ||
|- | |- | ||
|} | |} |