Pythonは簡易Web爬虫類の詳細を実現

8391 ワード

概要:
ネットワーク爬虫類(ウェブクモとも呼ばれる)は、ネットワークロボットであり、一定の規則に従って、自動的に情報をつかむプログラムやスクリプトである.インターネットが大きなクモの巣であり、各ページ間がハイパーリンクという線で相互に接続されていると仮定すると、私たちの爬虫類ウィジェットはこれらの線を通じて新しいページを絶えず探すことができます.
Pythonは単純主義思想を代表する解釈型で、対象向けで、機能が強い高級プログラミング言語である.文法が簡潔で、動的データ型と高レベルの抽象データ構造を有しているため、プラットフォーム間特性が良好で、特に爬虫類などのプログラムの実現に適している.また、PythonはSpyderのような爬虫類フレームワーク、BeautifulSoupのような解析フレームワークを提供し、様々な複雑な爬虫類プログラムを簡単に開発することができる.
この記事では、Pythonが持参したurllibとBeautifulSoupライブラリを使用して、各URLアドレスと対応するタイトルコンテンツを這い出すための簡単なweb爬虫類を実現しています.
プロセス:
爬虫類アルゴリズムは、入力から読み出したURLを初期アドレスとして、そのアドレスにRequest要求を発行する.
要求されたアドレスは、すべてのコンテンツを含むString変数を返し、この変数を使用してBeautifulSoupオブジェクトをインスタンス化し、コンテンツをDOMツリーに解析できます.
自分のニーズに合わせて正規表現を作成し、最後にHTMLタグで必要な内容と新しいURLを解析し、新しいものをキューに入れます.
現在のURLアドレスと登った内容については,一定のフィルタリング,整理を行った後にインデックスが作成され,単語−ページの記憶構造である.ユーザーが検索文を入力すると、対応する分詞関数が文を分解してキーワードを取得し、各キーワードに基づいて対応するURLを検索します.この構成により,この単語に対応するアドレスリストを迅速に取得できる.ここではツリー構造の格納方式を用いて,Pythonの辞書やリストタイプが単語辞書ツリーをより良く構築できる.
キューから現在のURLアドレスをポップアップし、キューを空にしない条件で、アルゴリズムはキューから新しいページアドレスを取得し続け、上記の手順を繰り返します.
実装:
環境:
Python3.5orAnaconda3
BeautifulSoup4
次のコマンドを使用してBeautifulSoup 4をインストールできます.Ubuntuユーザーの場合は、コマンドの前にsudoを付けてください.pip install beautifulsoup4
プログラムは、URLアドレス管理、Htmlコンテンツリクエスト、Htmlコンテンツ解析、インデックス作成、爬虫類マスタープロセスにそれぞれいくつかのクラスを実現しています.私はプログラム全体をClassごとに分けて説明して、最後に彼らを一緒に置くだけでコードを実行することができます.
UrlManagerクラス
このクラスはURLアドレスを管理するために使用されます.new_urlsは、まだ登録されていないURLアドレスを保存するために使用されます.old_urlsはすでに登ったアドレスを保存し、2つの変数はsetタイプを使用してコンテンツの一意性を保証します.サイクルごとにadd_new_urls()はnew_に提供されています.urls変数に新しいurlsを追加する方法.add_new_url()メソッドは、urlアドレスごとに重複性検査を行い、条件に合致した場合にのみ追加操作を行う.get_urls()は、新しいurlアドレスを取得する方法を外部に提供する.has_new_url()メソッドは、キューが空であるかどうかを確認するために使用されます.

import re
import urllib.request
import urllib.parse
from bs4 import BeautifulSoup


class UrlManager(object):
  def __init__(self):
    self.new_urls = set()
    self.old_urls = set()

  def add_new_url(self, url):
    if url is None:
      return
    if url not in self.new_urls and url not in self.old_urls:
      self.new_urls.add(url)

  def add_new_urls(self, urls):
    if urls is None or len(urls) == 0:
      return
    for url in urls:
      self.add_new_url(url)

  def has_new_url(self):
    return len(self.new_urls) != 0

  def get_new_url(self):
    new_url = self.new_urls.pop()
    self.old_urls.add(new_url)
    return new_url


HtmlDownloaderクラス
このクラスはurlアドレスにRequestリクエストを送信し,その応答を取得する方法を実現し,クラス内のdownload()メソッドを呼び出すことで実現できる.ここで注意したいのはページの符号化の問題で、ここで私はUTF-8を使ってdecode復号を行って、あるページはGBK符号化を使うかもしれなくて、実際の情況によって修正します.

class HtmlDownloader(object):
  def download(self, url):
    if url is None:
      return None
    try:
      request = urllib.request.Request(url)
      response = urllib.request.urlopen(request)
      content = response.read().decode('utf-8').encode('utf-8')
      if content is None:
        return None
      if response.getcode() != 200:
        return None
    except urllib.request.URLError as e:
      print(e)
      return None

    return content

HtmlParserクラス
このクラスでは、BeautifulSoupオブジェクトをインスタンス化してページの解析を行います.Pythonを使用して作成されたHTML/XMLドキュメント解析器です.ドキュメントをDOMツリーに解析することで、ユーザーにキャプチャする必要があるデータを提供し、ナビゲーション、検索、分析ツリーの変更などの機能を処理するための簡単な関数を提供します.
このクラスの鍵は_get_new_urls()、_get_new_content()、get_url_title()の3つの方法.最初の方法は、ページに含まれるハイパーリンクを解析するために使用され、最も重要なのは、解析するラベルを選択し、適切な正規表現を構築することです.ここでは、aラベルに一致する正則を定義し、以下のようにすべてのサイト内リンクを取得します.

links = soup.find_all('a', href=re.compile(r'^(%s).*(/|html)$' % self.domain))`

次の2つのクラスはいずれもHtmlタグを解析することによってtitleを取得する方法であり,最終的にparse()で呼び出し_get_new_content()を使用してtitleコンテンツを取得します.具体的なタグのアクセス方法については詳しくは述べませんが、読者はBeautifulSoupの公式ドキュメントを自分で閲覧することができます.

class HtmlParser(object):
  def __init__(self, domain_url):
    self.domain = domain_url
    self.res = HtmlDownloader()

  def _get_new_urls(self, page_url, soup):
    new_urls = set()
    links = soup.find_all('a', href=re.compile(r'^(%s).*(/|html)$' % self.domain))

    try:
      for link in links:
        new_url = link['href']
        new_full_url = urllib.parse.urljoin(self.domain, new_url)
        new_urls.add(new_full_url)

      new_urls = list(new_urls)
      return new_urls
    except AttributeError as e:
      print(e)
      return None

  def _get_new_content(self, page_url, soup):
    try:
      title_name = soup.title.string
      return title_name
    except AttributeError as e:
      print(e)
      return None

  def get_url_title(self):
    content = self.res.download(self.domain)

    try:
      soup = BeautifulSoup(content, 'html.parser', from_encoding='utf-8')
      title_name = soup.title.string
      return title_name
    except:
      title_name = 'None Title'
      return title_name

  def parse(self, page_url, html_cont):
    if page_url is None or html_cont is None:
      return None

    soup = BeautifulSoup(html_cont, 'html.parser', from_encoding='utf-8')
    new_data = self._get_new_content(page_url, soup)
    new_urls = self._get_new_urls(page_url, soup)

    return new_urls, new_data

BuildIndex
このクラスは、各URLアドレスと彼のタイトルに含まれるキーワードとのインデックス関係を確立し、1つのDict変数に保存し、各タイトルは複数のキーワードに対応し、各タイトルも複数のurlアドレスに対応するため、各キーワードも複数のurlアドレスに対応し、具体的な形式は以下の通りである.
index={'keyword':[url1,url2,...,urln],...}
ここでadd_page_index()メソッドは、各タイトルに対して分詞処理を行い、add_を呼び出した.key_index()メソッドはkeyword-urlの対応関係をインデックスに格納し,この中でも繰り返しチェックを行った.考えてみれば、この分詞方法は英語の文に限られており、中国語では特定の分詞ツールが必要です.

class BuildIndex(object):
  def add_page_index(self, index, url, content):
    words = content.split()
    for word in words:
      index = self.add_key_index(index, url, word)
    return index

  def add_key_index(self, index, url, keyword):
    if keyword in index:
      if url not in index[keyword]:
        index[keyword].append(url)
    else:
      temp = []
      index[keyword] = temp
      index[keyword].append(url)
    return index


SpiderMain
これは爬虫類のトピッククラスで、他のいくつかのクラスで生成されたオブジェクトを呼び出すことで爬虫類の実行を実現します.このクラスはインスタンス化されると永続的に上記のクラスのオブジェクトが生成され、craw()メソッドでユーザが提供するurlアドレスを取得すると、リクエスト、ダウンロード、解析、インデックスの作成が順次行われる.最後に、このメソッドはindex、graphの2つの変数を返します.
各キーワードセットに対応するアドレス、keyword-urlsインデックスは、以下の通りです.
index={'keyword':[url1,url2,...,urln],...}
各urlとそのページに含まれるurls,url-suburlsインデックスは、次のようになります.
graph={'url':[url1,url2,...,urln],...}

class SpiderMain(object):
  def __init__(self, root_url):
    self.root_url = root_url
    self.urls = UrlManager()
    self.downloader = HtmlDownloader()
    self.parser = HtmlParser(self.root_url)
    self.build = BuildIndex()

  def craw(self):
    index = graph = {}
    self.urls.add_new_url(self.root_url)
    while self.urls.has_new_url():
      try:
        new_url = self.urls.get_new_url()
        html_cont = self.downloader.download(new_url)
        new_urls, new_title = self.parser.parse(new_url, html_cont)
        index = self.build.add_page_index(index, new_url, new_title)
        graph[new_url] = list(new_urls)
        self.urls.add_new_urls(new_urls)
      except Exception as e:
        print(e)
        return None

    return index, graph


最後に、プログラムに次のコードを追加すると、爬虫類の実行に成功します.

if __name__ == '__main__':
  spider = SpiderMain('http://www.xael.org/')
  index, graph = spider.craw()
  print(index)
  print(graph)


まとめ
以上,Pythonの簡易Web爬虫類の実現に関する全文であり,皆さんの役に立つことを願っている.興味のある方は引き続き当駅の他の関連テーマを参照することができます.不足点があれば、伝言を歓迎します.友达の本駅に対する支持に感谢します!