2

一部のWebページをクロールしてHTMLとして保存したいと思います。たとえば、何百もの人気のあるWebサイトにクロールして、そのフロントページと「About」ページを保存するだけです。

私は多くの質問を調べましたが、WebクロールまたはWebスクレイピングの質問からこれに対する答えは見つかりませんでした。

ソリューションを構築するには、どのライブラリまたはツールを使用する必要がありますか?または、これを処理できる既存のツールもありますか?

4

6 に答える 6

6

Pythonに移行するときは、 mechanizeBeautifulSoupに興味があるかもしれません。

Mechanizeは、ブラウザをシミュレートし(プロキシ、ブラウザIDの偽造、ページリダイレクトなどのオプションを含む)、フォーム、リンクなどを簡単に取得できるようにします。ただし、ドキュメントは少しラフ/まばらです。

あなたにアイデアを与えるためのいくつかのサンプルコード(機械化ウェブサイトから):

import mechanize
br = mechanize.Browser()
br.open("http://www.example.com/")
# follow second link with element text matching regular expression
html_response = br.follow_link(text_regex=r"cheese\s*shop", nr=1)
print br.title()
print  html_response

BeautifulSoupを使用すると、htmlコンテンツ(mechanizeでフェッチできた可能性があります)を非常に簡単に解析でき、正規表現をサポートします。

いくつかのサンプルコード:

from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup(html_response)

rows = soup.findAll('tr')
for r in rows[2:]:  #ignore first two rows
    cols = r.findAll('td')
    print cols[0].renderContents().strip()    #print content of first column

したがって、上記の10行は、Webサイトのすべてのテーブル行の最初の列のコンテンツを印刷するためのコピーアンドペーストの準備がほぼ整っています。

于 2011-10-11T07:57:30.697 に答える
4

ここには本当に良い解決策はありません。正規表現が非常に強力にサポートされているため、Pythonがおそらく開始するのに最適な方法であると思われるのは正しいことです。

このようなものを実装するには、検索エンジンのWebページを効果的に最適化することで検索エンジンの動作がわかるため、SEO(検索エンジン最適化)に関する深い知識が役立ちます。私はSEOMozのようなサイトから始めます。

「Aboutus」ページを特定する限り、2つのオプションしかありません。

a)ページごとに、About usページのリンクを取得し、クローラーにフィードします。

b)「aboutus 」、「about」、「learn more」などの特定のキーワードについて、ページのすべてのリンクを解析します。

オプションbを使用する場合、特にリンクがヘッダーまたはフッターにある場合は、ページがそれ自体にリンクして戻る可能性があるため、Webサイトは同じページに何度もリンクするため、無限ループに陥る可能性があるので注意してください。これを回避するには、訪問したリンクのリストを作成し、それらを再訪問しないようにする必要があります。

最後に、ファイル内の指示をクローラーに尊重させることをお勧めします。これらは主に外部リンクで使用されるため、robot.txtマークされたリンクをたどらないことをお勧めします。rel="nofollow"繰り返しになりますが、SEOを読んで、これ以上のことを学びましょう。

よろしく、

于 2011-10-11T07:59:51.097 に答える
3

スクレイピーを試してみてください。Python用のWebスクレイピングライブラリです。単純なpythonスクリプトが必要な場合は、 pythonでurllib2を試してください。

于 2011-10-11T07:55:22.260 に答える
3

Python ==>Curl<-クローラーの最適な実装

次のコードは、優れたサーバー上で300秒で10,000ページをクロールできます。

#! /usr/bin/env python
# -*- coding: iso-8859-1 -*-
# vi:ts=4:et
# $Id: retriever-multi.py,v 1.29 2005/07/28 11:04:13 mfx Exp $

#
# Usage: python retriever-multi.py <file with URLs to fetch> [<# of
#          concurrent connections>]
#

import sys
import pycurl

# We should ignore SIGPIPE when using pycurl.NOSIGNAL - see
# the libcurl tutorial for more info.
try:
    import signal
    from signal import SIGPIPE, SIG_IGN
    signal.signal(signal.SIGPIPE, signal.SIG_IGN)
except ImportError:
    pass


# Get args
num_conn = 10
try:
    if sys.argv[1] == "-":
        urls = sys.stdin.readlines()
    else:
        urls = open(sys.argv[1]).readlines()
    if len(sys.argv) >= 3:
        num_conn = int(sys.argv[2])
except:
    print "Usage: %s <file with URLs to fetch> [<# of concurrent connections>]" % sys.argv[0]
    raise SystemExit


# Make a queue with (url, filename) tuples
queue = []
for url in urls:
    url = url.strip()
    if not url or url[0] == "#":
        continue
    filename = "doc_%03d.dat" % (len(queue) + 1)
    queue.append((url, filename))


# Check args
assert queue, "no URLs given"
num_urls = len(queue)
num_conn = min(num_conn, num_urls)
assert 1 <= num_conn <= 10000, "invalid number of concurrent connections"
print "PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM)
print "----- Getting", num_urls, "URLs using", num_conn, "connections -----"


# Pre-allocate a list of curl objects
m = pycurl.CurlMulti()
m.handles = []
for i in range(num_conn):
    c = pycurl.Curl()
    c.fp = None
    c.setopt(pycurl.FOLLOWLOCATION, 1)
    c.setopt(pycurl.MAXREDIRS, 5)
    c.setopt(pycurl.CONNECTTIMEOUT, 30)
    c.setopt(pycurl.TIMEOUT, 300)
    c.setopt(pycurl.NOSIGNAL, 1)
    m.handles.append(c)


# Main loop
freelist = m.handles[:]
num_processed = 0
while num_processed < num_urls:
    # If there is an url to process and a free curl object, add to multi stack
    while queue and freelist:
        url, filename = queue.pop(0)
        c = freelist.pop()
        c.fp = open(filename, "wb")
        c.setopt(pycurl.URL, url)
        c.setopt(pycurl.WRITEDATA, c.fp)
        m.add_handle(c)
        # store some info
        c.filename = filename
        c.url = url
    # Run the internal curl state machine for the multi stack
    while 1:
        ret, num_handles = m.perform()
        if ret != pycurl.E_CALL_MULTI_PERFORM:
            break
    # Check for curl objects which have terminated, and add them to the freelist
    while 1:
        num_q, ok_list, err_list = m.info_read()
        for c in ok_list:
            c.fp.close()
            c.fp = None
            m.remove_handle(c)
            print "Success:", c.filename, c.url, c.getinfo(pycurl.EFFECTIVE_URL)
            freelist.append(c)
        for c, errno, errmsg in err_list:
            c.fp.close()
            c.fp = None
            m.remove_handle(c)
            print "Failed: ", c.filename, c.url, errno, errmsg
            freelist.append(c)
        num_processed = num_processed + len(ok_list) + len(err_list)
        if num_q == 0:
            break
    # Currently no more I/O is pending, could do something in the meantime
    # (display a progress bar, etc.).
    # We just call select() to sleep until some more data is available.
    m.select(1.0)


# Cleanup
for c in m.handles:
    if c.fp is not None:
        c.fp.close()
        c.fp = None
    c.close()
m.close()
于 2011-11-29T13:02:29.263 に答える
2

クローラーを構築する場合は、次のことを行う必要があります(Java固有)。

  1. java.net.URLおよびjava.net.URLConnectionクラスの使用方法、またはHttpClientライブラリの使用方法を学習します
  2. httpリクエスト/レスポンスヘッダーを理解する
  3. リダイレクトを理解する(HTTP、HTML、Javascriptの両方)
  4. コンテンツエンコーディング(文字セット)を理解する
  5. 不正な形式のHTML(cyberNecko、Jericho、JSoupなど)を解析するための優れたライブラリを使用する
  6. 異なるホストに対して同時HTTPリクエストを作成しますが、最大5秒ごとに同じホストに対して発行するのは1つだけにしてください。
  7. フェッチしたページを永続化するため、頻繁に変更されない限り、毎日再フェッチする必要はありません(HBaseが役立つ場合があります)。
  8. 現在のページからリンクを抽出して次にクロールする方法
  9. robots.txtに従う

他にもたくさんあります。

それほど難しいことではありませんが、厄介なエッジケースがたくさんあります(リダイレクト、エンコーディングの検出(チェックアウトTika)など)。

より基本的な要件については、wgetを使用できます。Heretrixは別のオプションですが、学習するためのさらに別のフレームワークです。

About usページの識別は、さまざまなヒューリスティックを使用して実行できます。

  1. インバウンドリンクテキスト
  2. ページタイトル
  3. ページのコンテンツ
  4. URL

それについてより定量的にしたい場合は、機械学習と分類器(おそらくベイジアン)を使用できます。

フロントページの保存は明らかに簡単ですが、フロントページのリダイレクト(場合によっては異なるドメインへのリダイレクト、多くの場合HTMLメタリダイレクトタグまたはJSで実装されることもあります)は非常に一般的であるため、これを処理する必要があります。

于 2011-10-11T08:07:52.390 に答える
1

Heritrixの学習曲線は少し急ですが、ホームページと、(正規表現フィルターを使用して)「似ている」ページのみがクロールされるように構成できます。

その他のオープンソースJava(Web)クローラー:http://java-source.net/open-source/crawlers

于 2011-10-11T07:58:57.937 に答える