Fuwafuwa's memorandum

Fuwafuwa's memorandum

Data analysis, development, reading, daily feeling.
MENU

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Python: webページ上のリンク先htmlをダウンロード

webページ上のリンク先htmlをダウンロードする。
クローリングの際の時間はどの程度が常識なのかいまいちわからなかったので
人間がやる時くらいの時間幅をもたせました。

from bs4 import BeautifulSoup
from urllib.request import *
from urllib.parse import * 
import os.path, time, re


def download_file(url,savepath):
    savepath = savepath
    try:
        print("download=",url)
        urlretrieve(url,savepath)
        time.sleep(10)
        print("ダウンロード成功")
        return savepath
    except:
        print("ダウンロード失敗",url)
        return None

base = "http://www.xxxxx.com/" ##リンク先は短縮されている場合もあるためbaseとなるhtmlを用意する

url = "xxxxx.webarchive"
res = urlopen(url)
soup = BeautifulSoup(res, "html.parser")

lists = soup.find_all("a")

for list in lists:
    href = list.attrs['href']
    text = list.string
    url = urljoin(base,href)
    download_file(url,savepath+text+'.html')
参考
Pythonによるスクレイピング&機械学習 開発テクニック BeautifulSoup,scikit-learn,TensorFlowを使ってみようPythonによるスクレイピング&機械学習 開発テクニック BeautifulSoup,scikit-learn,TensorFlowを使ってみよう
クジラ飛行机

ソシム 2016-12-06
売り上げランキング : 11855

Amazonで詳しく見る
by G-Tools

スポンサーサイト

Python: webからダウンロードする

htmlでもpngでも可。

import urllib.request

url = "http://xxxxx.com"
savename = "web-page.html"

mem = urllib.request.urlopen(url).read()

with open(savename,mode="wb") as f:
    f.write(mem)
    print("saved")

Python: Twitterにおけるトレンドを取得する

下記の引き写しです。
https://github.com/ideoforms/python-twitter-examples/blob/master/twitter-trends.py

# -*- coding: utf-8 -*-

from twitter import * 

CK = 'XXXXX'    # Consumer Key
CS = 'XXXXX'    # Consumer Secret
AT = 'XXXXX'    # Access Token
AS = 'XXXXX'    # Accesss Token Secert

twitter = Twitter(auth = OAuth(AT,AS,CK,CS))

##idは地域IDにおける日本を指定
results = twitter.trends.place(_id = 23424856)

for location in results:
    for trend in location["trends"]:
        print(trend["name"])
簡単ですね。

Python: TweetをmongoDBに格納する

こちらも下記の引き写しです。
http://ailaby.com/twitter_api/(こちらのコードをtwitterAPI.pyとして保存しました)
http://ailaby.com/tweet2mongo/
記載されている内容そのままで動きました。
ありがとうございます!

mongoDBへの格納

from pymongo import MongoClient
from twitterAPI import TweetsGetter
 
client = MongoClient('localhost', 27017)
 
db = client.mydb
 
tweets = TweetsGetter.bySearch(u'パナマ文書').collect(total=2000)
for tweet in tweets:
    tweet2 = {}
    tweet2['id'] = tweet['id']
    tweet2['text'] = tweet['text']
    tweet2['created_at'] = tweet['created_at']
    tweet2['user'] = {'screen_name' : tweet['user']['screen_name']}
    tweet2['favorite_count'] = tweet['favorite_count']
    tweet2['retweet_count'] = tweet = ['retweet_count']
 
    db.panama.insert(tweet2)
DBの読み取り。
from pymongo import MongoClient

client = MongoClient('localhost', 27017)
db = client.mydb

cnt = 0

for record in db.panama.find():
    cnt += 1 
    print('---',cnt)
    print(record['text'])
シェルで確認。
use mydb
db.panama.count()
db.panama.findOne()  

Python: TwitterAPIからTweetを取得

Tweetたくさんほしいな~と思っていたらこんなページにこんなコードが。
http://ailaby.com/twitter_api/#id6

# -*- coding: utf-8 -*-
 
from requests_oauthlib import OAuth1Session
import json
import datetime, time, sys
from abc import ABCMeta, abstractmethod
 
CK = 'XXXXX'                             # Consumer Key
CS = 'XXXXX'    # Consumer Secret
AT = 'XXXXX'    # Access Token
AS = 'XXXXX'         # Accesss Token Secert
 
class TweetsGetter(object):
    __metaclass__ = ABCMeta
 
    def __init__(self):
        self.session = OAuth1Session(CK, CS, AT, AS)
 
    @abstractmethod
    def specifyUrlAndParams(self, keyword):
        '''
        呼出し先 URL、パラメータを返す
        '''
 
    @abstractmethod
    def pickupTweet(self, res_text, includeRetweet):
        '''
        res_text からツイートを取り出し、配列にセットして返却
        '''
 
    @abstractmethod
    def getLimitContext(self, res_text):
        '''
        回数制限の情報を取得 (起動時)
        '''
 
    def collect(self, total = -1, onlyText = False, includeRetweet = False):
        '''
        ツイート取得を開始する
        '''
 
        #----------------
        # 回数制限を確認
        #----------------
        self.checkLimit()
 
        #----------------
        # URL、パラメータ
        #----------------
        url, params = self.specifyUrlAndParams()
        params['include_rts'] = str(includeRetweet).lower()
        # include_rts は statuses/user_timeline のパラメータ。search/tweets には無効
 
        #----------------
        # ツイート取得
        #----------------
        cnt = 0
        unavailableCnt = 0
        while True:
            res = self.session.get(url, params = params)
            if res.status_code == 503:
                # 503 : Service Unavailable
                if unavailableCnt > 10:
                    raise Exception('Twitter API error %d' % res.status_code)
 
                unavailableCnt += 1
                print ('Service Unavailable 503')
                self.waitUntilReset(time.mktime(datetime.datetime.now().timetuple()) + 30)
                continue
 
            unavailableCnt = 0
 
            if res.status_code != 200:
                raise Exception('Twitter API error %d' % res.status_code)
 
            tweets = self.pickupTweet(json.loads(res.text))
            if len(tweets) == 0:
                # len(tweets) != params['count'] としたいが
                # count は最大値らしいので判定に使えない。
                # ⇒  "== 0" にする
                # https://dev.twitter.com/discussions/7513
                break
 
            for tweet in tweets:
                if (('retweeted_status' in tweet) and (includeRetweet is False)):
                    pass
                else:
                    if onlyText is True:
                        yield tweet['text']
                    else:
                        yield tweet
 
                    cnt += 1
                    if cnt % 100 == 0:
                        print ('%d件 ' % cnt)
 
                    if total > 0 and cnt >= total:
                        return
 
            params['max_id'] = tweet['id'] - 1
 
            # ヘッダ確認 (回数制限)
            # X-Rate-Limit-Remaining が入ってないことが稀にあるのでチェック
            if ('X-Rate-Limit-Remaining' in res.headers and 'X-Rate-Limit-Reset' in res.headers):
                if (int(res.headers['X-Rate-Limit-Remaining']) == 0):
                    self.waitUntilReset(int(res.headers['X-Rate-Limit-Reset']))
                    self.checkLimit()
            else:
                print ('not found  -  X-Rate-Limit-Remaining or X-Rate-Limit-Reset')
                self.checkLimit()
 
    def checkLimit(self):
        '''
        回数制限を問合せ、アクセス可能になるまで wait する
        '''
        unavailableCnt = 0
        while True:
            url = "https://api.twitter.com/1.1/application/rate_limit_status.json"
            res = self.session.get(url)
 
            if res.status_code == 503:
                # 503 : Service Unavailable
                if unavailableCnt > 10:
                    raise Exception('Twitter API error %d' % res.status_code)
 
                unavailableCnt += 1
                print ('Service Unavailable 503')
                self.waitUntilReset(time.mktime(datetime.datetime.now().timetuple()) + 30)
                continue
 
            unavailableCnt = 0
 
            if res.status_code != 200:
                raise Exception('Twitter API error %d' % res.status_code)
 
            remaining, reset = self.getLimitContext(json.loads(res.text))
            if (remaining == 0):
                self.waitUntilReset(reset)
            else:
                break
 
    def waitUntilReset(self, reset):
        '''
        reset 時刻まで sleep
        '''
        seconds = reset - time.mktime(datetime.datetime.now().timetuple())
        seconds = max(seconds, 0)
        print ('\n     =====================')
        print ('     == waiting %d sec ==' % seconds)
        print ('     =====================')
        sys.stdout.flush()
        time.sleep(seconds + 10)  # 念のため + 10 秒
 
    @staticmethod
    def bySearch(keyword):
        return TweetsGetterBySearch(keyword)
 
    @staticmethod
    def byUser(screen_name):
        return TweetsGetterByUser(screen_name)
 
 
class TweetsGetterBySearch(TweetsGetter):
    '''
    キーワードでツイートを検索
    '''
    def __init__(self, keyword):
        super(TweetsGetterBySearch, self).__init__()
        self.keyword = keyword
        
    def specifyUrlAndParams(self):
        '''
        呼出し先 URL、パラメータを返す
        '''
        url = 'https://api.twitter.com/1.1/search/tweets.json'
        params = {'q':self.keyword, 'count':100}
        return url, params
 
    def pickupTweet(self, res_text):
        '''
        res_text からツイートを取り出し、配列にセットして返却
        '''
        results = []
        for tweet in res_text['statuses']:
            results.append(tweet)
 
        return results
 
    def getLimitContext(self, res_text):
        '''
        回数制限の情報を取得 (起動時)
        '''
        remaining = res_text['resources']['search']['/search/tweets']['remaining']
        reset     = res_text['resources']['search']['/search/tweets']['reset']
 
        return int(remaining), int(reset)
    
 
class TweetsGetterByUser(TweetsGetter):
    '''
    ユーザーを指定してツイートを取得
    '''
    def __init__(self, screen_name):
        super(TweetsGetterByUser, self).__init__()
        self.screen_name = screen_name
        
    def specifyUrlAndParams(self):
        '''
        呼出し先 URL、パラメータを返す
        '''
        url = 'https://api.twitter.com/1.1/statuses/user_timeline.json'
        params = {'screen_name':self.screen_name, 'count':200}
        return url, params
 
    def pickupTweet(self, res_text):
        '''
        res_text からツイートを取り出し、配列にセットして返却
        '''
        results = []
        for tweet in res_text:
            results.append(tweet)
 
        return results
 
    def getLimitContext(self, res_text):
        '''
        回数制限の情報を取得 (起動時)
        '''
        remaining = res_text['resources']['statuses']['/statuses/user_timeline']['remaining']
        reset     = res_text['resources']['statuses']['/statuses/user_timeline']['reset']
 
        return int(remaining), int(reset)
 
 
if __name__ == '__main__':
 
    # キーワードで取得
    getter = TweetsGetter.bySearch(u'渋谷')
    
    # ユーザーを指定して取得 (screen_name)
    #getter = TweetsGetter.byUser('AbeShinzo')
 
    cnt = 0
    for tweet in getter.collect(total = 3000):
        cnt += 1
        print('------ %d' % cnt)
        print('{} {} {}'.format(tweet['id'], tweet['created_at'], '@'+tweet['user']['screen_name']))
        print(tweet['text'])
Unicodeエラーが出たけどほぼほぼコピペでうごきました。
ありがとうございます!

該当の記事は見つかりませんでした。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。