Python Language
PythonによるWebスクレイピング
サーチ…
前書き
Webスクレイピングは自動化されたプログラム的なプロセスで、データをウェブページから絶えず「掻き取る」ことができます。スクリーンスクレイピングまたはウェブ収穫とも呼ばれるウェブスクレイピングは、一般にアクセス可能なウェブページからインスタントデータを提供することができます。一部のウェブサイトでは、ウェブのスクレイピングが違法かもしれません。
備考
Webスクレイピング(アルファベット順)に役立つPythonパッケージ
リクエストの作成とデータの収集
requests
HTTPリクエストを作成するための単純で強力なパッケージです。
requests-cache
requests
キャッシュ。キャッシュデータは非常に便利です。開発中は、不必要にサイトにヒットすることを避けることができます。本当のコレクションを実行している間に、あなたのスクレーパーが何らかの理由でクラッシュした場合(おそらく、サイト上の珍しいコンテンツを処理していないかもしれません...おそらくサイトがダウンしたのでしょうか?)、コレクションをすばやく繰り返すことができますあなたが中断したところから。
scrapy
Webクローラーを構築するのに便利です。 requests
を使用してページを反復するよりも強力なものが必要です。
selenium
ブラウザ自動化のためのSelenium WebDriver用のPythonバインディング。 requests
を使用してHTTPリクエストを直接作成することは、ウェブページを取得するためにしばしば簡単です。しかし、 requests
単独で使用してサイトの望ましい振る舞いを再現することができない場合、特にJavaScriptがページ上の要素をレンダリングする必要がある場合は、これは便利なツールです。
HTML解析
BeautifulSoup
さまざまなパーサー(Pythonの組み込みHTMLパーサ、 html5lib
、 lxml
またはlxml.html
)を使用して、HTMLおよびXMLドキュメントをクエリします。
lxml
HTMLとXMLを処理します。 CSSセレクタとXPathを使用して、HTMLドキュメントからコンテンツをクエリして選択するために使用できます。
リクエストとlxmlを使ってデータをスクラップする基本的な例
# For Python 2 compatibility.
from __future__ import print_function
import lxml.html
import requests
def main():
r = requests.get("https://httpbin.org")
html_source = r.text
root_element = lxml.html.fromstring(html_source)
# Note root_element.xpath() gives a *list* of results.
# XPath specifies a path to the element we want.
page_title = root_element.xpath('/html/head/title/text()')[0]
print(page_title)
if __name__ == '__main__':
main()
リクエストによるWebスクレイピングセッションの維持
Cookieやその他のパラメータを永続化するためにWebスクレイプセッションを維持することをお勧めします。さらに、 requests.Session
は、基本TCP接続をホストに再利用するため、 パフォーマンスが向上します。
import requests
with requests.Session() as session:
# all requests through session now have User-Agent header set
session.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'}
# set cookies
session.get('http://httpbin.org/cookies/set?key=value')
# get cookies
response = session.get('http://httpbin.org/cookies')
print(response.text)
Scrapyフレームワークを使用したスクレイピング
まず、新しいScrapyプロジェクトをセットアップする必要があります。コードを保存するディレクトリを入力して実行します。
scrapy startproject projectName
スクラップするには、クモが必要です。スパイダーは、特定のサイトをどのように削り取るかを定義します。 StackOverflow上で投票された質問へのリンクをたどり、各ページ( ソース )からいくつかのデータをスクラップするスパイダーのコードは次のとおりです。
import scrapy
class StackOverflowSpider(scrapy.Spider):
name = 'stackoverflow' # each spider has a unique name
start_urls = ['http://stackoverflow.com/questions?sort=votes'] # the parsing starts from a specific set of urls
def parse(self, response): # for each request this generator yields, its response is sent to parse_question
for href in response.css('.question-summary h3 a::attr(href)'): # do some scraping stuff using css selectors to find question urls
full_url = response.urljoin(href.extract())
yield scrapy.Request(full_url, callback=self.parse_question)
def parse_question(self, response):
yield {
'title': response.css('h1 a::text').extract_first(),
'votes': response.css('.question .vote-count-post::text').extract_first(),
'body': response.css('.question .post-text').extract_first(),
'tags': response.css('.question .post-tag::text').extract(),
'link': response.url,
}
spiderクラスをprojectName\spiders
ディレクトリに保存します。この場合、 projectName\spiders\stackoverflow_spider.py
。
今あなたはあなたのクモを使うことができます。たとえば、(プロジェクトのディレクトリ内で)実行してみてください:
scrapy crawl stackoverflow
Scrapyユーザーエージェントを変更する
デフォルトのScrapyユーザーエージェント( "Scrapy/VERSION (+http://scrapy.org)"
)がホストによってブロックされることがあります。デフォルトのユーザエージェントを変更するには、 settings.pyを開き、次の行のコメントを外して編集します。
#USER_AGENT = 'projectName (+http://www.yourdomain.com)'
例えば
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
BeautifulSoup4を使用したスクレイピング
from bs4 import BeautifulSoup
import requests
# Use the requests module to obtain a page
res = requests.get('https://www.codechef.com/problems/easy')
# Create a BeautifulSoup object
page = BeautifulSoup(res.text, 'lxml') # the text field contains the source of the page
# Now use a CSS selector in order to get the table containing the list of problems
datatable_tags = page.select('table.dataTable') # The problems are in the <table> tag,
# with class "dataTable"
# We extract the first tag from the list, since that's what we desire
datatable = datatable_tags[0]
# Now since we want problem names, they are contained in <b> tags, which are
# directly nested under <a> tags
prob_tags = datatable.select('a > b')
prob_names = [tag.getText().strip() for tag in prob_tags]
print prob_names
Selenium WebDriverを使用したスクレイピング
いくつかのウェブサイトは掻き取られたくありません。このような場合、ブラウザを使って作業している実際のユーザをシミュレートする必要があります。 SeleniumはWebブラウザを起動して制御します。
from selenium import webdriver
browser = webdriver.Firefox() # launch firefox browser
browser.get('http://stackoverflow.com/questions?sort=votes') # load url
title = browser.find_element_by_css_selector('h1').text # page title (first h1 element)
questions = browser.find_elements_by_css_selector('.question-summary') # question list
for question in questions: # iterate over questions
question_title = question.find_element_by_css_selector('.summary h3 a').text
question_excerpt = question.find_element_by_css_selector('.summary .excerpt').text
question_vote = question.find_element_by_css_selector('.stats .vote .votes .vote-count-post').text
print "%s\n%s\n%s votes\n-----------\n" % (question_title, question_excerpt, question_vote)
セレンははるかに多くを行うことができます。ブラウザのCookieを変更したり、フォームに記入したり、マウスのクリックをシミュレートしたり、Webページのスクリーンショットを撮ったり、カスタムJavaScriptを実行したりすることができます。
urllib.requestによるシンプルなWebコンテンツのダウンロード
標準ライブラリモジュールurllib.request
を使用してWebコンテンツをダウンロードできます:
from urllib.request import urlopen
response = urlopen('http://stackoverflow.com/questions?sort=votes')
data = response.read()
# The received bytes should usually be decoded according the response's character set
encoding = response.info().get_content_charset()
html = data.decode(encoding)
同様のモジュールは、Python 2でも利用できます。
カールで掻く
輸入:
from subprocess import Popen, PIPE
from lxml import etree
from io import StringIO
ダウンロード:
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'
url = 'http://stackoverflow.com'
get = Popen(['curl', '-s', '-A', user_agent, url], stdout=PIPE)
result = get.stdout.read().decode('utf8')
-s
:サイレントダウンロード
-A
:ユーザエージェントフラグ
解析する:
tree = etree.parse(StringIO(result), etree.HTMLParser())
divs = tree.xpath('//div')