2016-08-11 31 views
5

Here is the Website I am trying to scrape http://livingwage.mit.edu/Python-> Beautifulsoup-> Webscraping-> URL(1〜53)の上にループして保存結果

特定のURLが

http://livingwage.mit.edu/states/01 

http://livingwage.mit.edu/states/02 

http://livingwage.mit.edu/states/04 (For some reason they skipped 03) 

...all the way to... 

http://livingwage.mit.edu/states/56 

からそして、これらのURLのそれぞれに、私が必要としています第二表の最後の行:http://livingwage.mit.edu/states/01

必要な年収のため

例税引前$ 20260 $ 42786 $ 51642 $ 64767 $ 34325 $ 42305 $ 47345 $ 53206 $ 34325 $ 47691 $ 56934 $ 66997

欲望出力:

アラバマ$ 20260 $ 42786 $ 51642 $ 64767 $ 34325 $ 42305 $ 47345 $ 53206 $ 34325 $ 47691 $ 56934 $ 66997

アラスカ$2.407万$ 49295 $ 60933 $ 79,871 $ 38,561 $ 47,136 $ 52,233 $ 61,531 $ 38,561 $ 54,433 $ 66,316 $ 82,403

...

...

ワイオミング$ 20867 $ 42689 $ 52007 $ 65892 $ 34988 $ 41887 $ 46983 $ 53549 $ 34988 $ 47826 $ 57391いじりの2時間後に$ 68424

、これは私が(私は初心者です)これまで持っているものです。

私はPythonコンソールにSTATE_NAMEと行を見たとき
import requests, bs4 

res = requests.get('http://livingwage.mit.edu/states/01') 

res.raise_for_status() 
states = bs4.BeautifulSoup(res.text) 


state_name=states.select('h1') 

table = states.find_all('table')[1] 
rows = table.find_all('tr', 'odd')[4:] 


result=[] 

result.append(state_name) 
result.append(rows) 

それは私のhtml要素

[<h1>Living Wag...Alabama</h1>] 
を与えます

[<tr class = "odd... </td> </tr>] 

問題1:これらは私が所望の出力にしたいものですが、どのように私はPythonのではなく、HTMLよりも上記のような文字列形式で私にそれを与えるために得ることができますか?

問題2:どのようにrequest.get(url01〜url56)をループするのですか?

ありがとうございました。

コード内のrows変数に効率的にアクセスできる方法を提供できる場合は、PythonのPythonではないので、私は非常に感謝しています。

答えて

5

ただ、最初のページからすべての状態を取得し、その後、2番目のテーブルを選択し、必要TRを取得するために奇妙な結果にCSSクラスを使用することができ、クラスとしてスライスする必要はありません名前は一意である:

import requests 
from bs4 import BeautifulSoup 
from urllib.parse import urljoin # python2 -> from urlparse import urljoin 


base = "http://livingwage.mit.edu" 
res = requests.get(base) 

res.raise_for_status() 
states = [] 
# Get all state urls and state name from the anchor tags on the base page. 
# td + td skips the first td which is *Required annual income before taxes* 
# get all the anchors inside each li that are children of the 
# ul with the css class "states list". 
for a in BeautifulSoup(res.text, "html.parser").select("ul.states.list-unstyled li a"): 
    # The hrefs look like "/states/51/locations". 
    # We want everything before /locations so we split on/from the right -> /states/51/ 
    # and join to the base url. The anchor text also holds the state name, 
    # so we return the full url and the state, i.e "http://livingwage.mit.edu/states/01 "Alabama". 
    states.append((urljoin(base, a["href"].rsplit("/", 1)[0]), a.text)) 


def parse(soup): 
    # Get the second table, indexing in css starts at 1, so table:nth-of-type(2)" gets the second table. 
    table = soup.select_one("table:nth-of-type(2)") 
    # To get the text, we just need find all the tds and call .text on each. 
    # Each td we want has the css class "odd results", td + td starts from the second as we don't want the first. 
    return [td.text.strip() for td in table.select_one("tr.odd.results").select("td + td")] 


# Unpack the url and state from each tuple in our states list. 
for url, state in states: 
    soup = BeautifulSoup(requests.get(url).content, "html.parser") 
    print(state, parse(soup)) 

あなたがコードを実行する場合は以下のような出力が表示されます。あなたは、ARのループ

Alabama ['$21,144', '$43,213', '$53,468', '$67,788', '$34,783', '$41,847', '$46,876', '$52,531', '$34,783', '$48,108', '$58,748', '$70,014'] 
Alaska ['$24,070', '$49,295', '$60,933', '$79,871', '$38,561', '$47,136', '$52,233', '$61,531', '$38,561', '$54,433', '$66,316', '$82,403'] 
Arizona ['$21,587', '$47,153', '$59,462', '$78,112', '$36,332', '$44,913', '$50,200', '$58,615', '$36,332', '$52,483', '$65,047', '$80,739'] 
Arkansas ['$19,765', '$41,000', '$50,887', '$65,091', '$33,351', '$40,337', '$45,445', '$51,377', '$33,351', '$45,976', '$56,257', '$67,354'] 
California ['$26,249', '$55,810', '$64,262', '$81,451', '$42,433', '$52,529', '$57,986', '$68,826', '$42,433', '$61,328', '$70,088', '$84,192'] 
Colorado ['$23,573', '$51,936', '$61,989', '$79,343', '$38,805', '$47,627', '$52,932', '$62,313', '$38,805', '$57,283', '$67,593', '$81,978'] 
Connecticut ['$25,215', '$54,932', '$64,882', '$80,020', '$39,636', '$48,787', '$53,857', '$61,074', '$39,636', '$60,074', '$70,267', '$82,606'] 

ができ1から53までのアンガーが基本ページからアンカーを抽出すると、そのページからのh1を使用して州名も表示されます。Alabamaの生活賃金計算いくつかの州が1つの単語の名前を多く持っていると考えると、些細なことではない名前を取得するだけです。

+1

ありがとう、これは私が必要とするものです。さて、私はこれを私の質問の受け入れられた答えとどのようにマークするのですか? –

+0

@OmiSlash。心配しないで、私はあなたがそれを理解したのを見ます。 –

+0

私はあなたのコードを勉強している最後の数日間を過ごしました、そして、それは私の頭の上に右に行った非常にpythonicだと言う必要があります。 男に魚を与えるという言葉があります。あなたは一日彼に餌を与え、魚を釣るように教えて、あなたは一生の間彼に餌を与えます。私はリクエストのドキュメントを読んでいて、いくつかの基本的なhtmlを理解しています。 私はあなたからの魚を受け取りました。あなたがいつもウェブスクラップであなたの助けを請うために戻ってくることを望んでいない限り(そしてあなたはいくつかの正しい点を獲得するでしょう)、思考やワークフロープロセスあなたはこのコードを作成しますか? –

2

問題1:これらは私が望む出力ですが、上記のようにHTMLではなく文字列形式で私に与えるためにPythonをどのように入手できますか?

あなたはの行に何かをすることによって、単純にしてテキストを取得することができます:

state_name=states.find('h1').text 

同じことがあまりにも行ごとに適用することができます。

問題2:どのようにrequest.get(url01からurl56)をループするのですか?

同じコードブロックがそうような1から56までのループの内側に置くことができる。

for i in range(1,57): 
    res = requests.get('http://livingwage.mit.edu/states/'+str(i).zfill(2)) 
    ...rest of the code... 

zfillそれらの先行ゼロを追加します。また、requests.gettry-exceptブロックに囲まれていると、URLが間違っていてもループが正常に続きます。

+1

あなたの答えをありがとう、それは私のコーディングの方法に従うので、多くを助けます。しかし、私はPadraic Cunninghamの答えを受け入れました。なぜなら、それは私がコード化した方法よりもずっとPythonであるからです(私は恥ずかしいです!!)。そしてパドレイク・カニンガムの答えから、私はウェブスクレーピングのための新しい技術をいくつか学びました。新しいスキルを学ぶことは常に目標です。 –

+0

完全に真実です! – dunder

関連する問題