「利用者:夜泣き/スクリプト」の版間の差分

編集の要約なし
>Fet-Fe
編集の要約なし
>Fet-Fe
編集の要約なし
6行目: 6行目:


'''
'''
ver2.1.4 2022/9/22恒心
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://nitterqdyumlovt7tjqpdjrluitgmtpa53qq3idlpgoe4kxo7gs3xvad.onion/'
   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._check_tor() ##Torが使えているかチェック
     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 _check_tor(self) -> None | NoReturn:
   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: Final[Response] = self._request_once('https://check.torproject.org/api/ip') ##リクエスト
       res = self._request_once('https://check.torproject.org/api/ip') ##リクエスト
       is_tor: Final[bool] = json.loads(res.text)['IsTor']
       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&nbsp; ' + poll_meter.select_one('.poll-choice-value').text + ' ' + poll_meter.select_one('.poll-choice-option').text
         ratio: str = poll_meter.select_one('.poll-choice-value').text
       poll_txt += '<br>\n&nbsp; ' + tweet_poll.select_one('.poll-info').text
        if 'leader' in poll_meter['class']:
          poll_txt += f'<br>\n&nbsp; <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&nbsp; <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&nbsp; <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 re.match('^https?://', url.get('href')) is not None: ##先頭にhttpが付いていない物はハッシュタグの検索ページへのリンクなので処理しない
       if url.get('href').startswith('https://') or url.get('href').startswith('http://'): ##先頭にhttpが付いていない物はハッシュタグの検索ページへのリンクなので処理しない
         if re.match('https' + self.NITTER_INSTANCE[4:], url.get('href')):
         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 re.match('piped.kavin.rocks/', url.text) or re.match('invidio.us/', url.text):
         elif self._invidious_pattern.search(url.get('href')):
           #Nitter上のYouTubeへのリンクを直す
           #Nitter上のYouTubeへのリンクをInvidiousのものから直す
           url_link: str = url.get('href')
           url_link: str = url.get('href')
           url_link = url_link.replace('piped.kavin.rocks/', 'youtu.be/')
           url_link = self._invidious_pattern.sub('youtu.be', url_link)
          url_link = url_link.replace('invidio.us/', 'youtu.be/')
           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>
&nbsp; 35% タトゥーは文化だ。<br>
&nbsp; <span style="display: inline-block; width: 30em; background: linear-gradient(to right, rgb(207, 217, 222) 0 35%, transparent 35% 100%);">35% タトゥーは文化だ。</span><br>
&nbsp; 65% タトゥーは文化じゃない。<br>
&nbsp; <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>
&nbsp; 717 votes • Final results
&nbsp; <span style="font-size: small;">717 votes • Final results</span>
|-
|-
|}
|}
匿名利用者