いわゆる Web クローラーは、インターネット上のあらゆる場所または特定の方向にデータをクロールするプログラムです。もちろん、この説明では、特定の Web サイトのページの HTML データをクロールするというと専門的ではありません。ただし、Web サイトには多数の Web ページがあり、すべての Web ページの URL アドレスを事前に知ることは不可能であるため、Web サイトのすべての HTML ページを確実にキャプチャする方法は検討が必要な問題です。一般的な方法は、入口ページを定義し、通常、あるページには他のページの URL が含まれるため、これらの URL が現在のページから取得されてクローラーのクローリング キューに追加され、新しいページに入った後、上記のこの操作は実際には深さのトラバーサルまたは幅のトラバーサルと同じです。
Scrapy は、Twisted をベースにした純粋な Python で実装されたクローラー フレームワークです。ユーザーは、いくつかのモジュールをカスタマイズして開発するだけで、Web コンテンツやさまざまな画像をクロールするクローラーを簡単に実装できます。Scrapy Twisted を使用すると、非常に便利です。ネットワーク通信を処理する非同期ネットワークライブラリであり、明確なアーキテクチャを持ち、さまざまなニーズに柔軟に対応できるさまざまなミドルウェアインターフェイスが含まれています。全体的なアーキテクチャは次の図に示されています。
緑色の線は、最初の URL から開始して、ダウンロード後にダウンローダーに渡します。分析のために Spider に渡されます。Spider によって分析された結果は 2 つあります。1 つは、以前に分析された「次のページ」リンクなど、さらにクロールする必要があるリンクです。スケジューラー。もう 1 つは保存する必要があるデータで、アイテム パイプラインに送信され、データの後処理 (詳細な分析、フィルタリング、保存など) が行われます。また、データフローチャネルには各種ミドルウェアを実装し、必要な処理を実行することができます。
Scrapy はすでにインストールされていると思います。インストールしていない場合は、この記事を参照してください。
この記事では、Scrapy を使用してクローラー プログラムを構築し、指定した Web サイトのコンテンツをクロールする方法を学びます
1. 新しい Scrapy プロジェクトを作成します
2. Web ページから抽出する必要がある要素アイテムを定義します。
3. Spider クラスを実装して、インターフェイスを介して URL をクロールし、Item を抽出する機能を完成させます
4. Items PipeLine クラスを実装して、Item ストレージ機能を完成させます
例として、Tencent の公式採用 Web サイトを使用します。
Githubソースコード: https://github.com/maxliaops/scrapy-itzhaopin
目標: Tencent採用公式Webサイトから求人情報を取得し、JSON形式で保存します。
新しいプロジェクト
まず、クローラー用の新しいプロジェクトを作成し、最初にディレクトリ (コードの保存に使用する任意のディレクトリ) を入力し、次のコマンドを実行します。
scrapy startprojectitzhaopin
最後の itzhaopin はプロジェクト名です。このコマンドは、現在のディレクトリに次の構造を持つ新しいディレクトリ itzhaopin を作成します:
.
§── itzhaopin
│ っていかに itzhaopin
│ │ §── __init__.py
│ │ っていか─ items .py
│ │ ├─ Pipelines.py
│ │ ├─ settings.py
│ │ └─ スパイダー
│ │ └─ __init__.py
│ └── スクレイピー。 cfg
scrapy.cfg: プロジェクト構成ファイル
items.py: 抽出する必要があるデータ構造定義ファイル
pipelines.py: アイテムから抽出されたデータをさらに処理するために使用されるパイプライン定義 (保存など)など。
settings .py: クローラー設定ファイル
spiders: スパイダーが配置されるディレクトリ
Item を定義する
items.py でクロールするデータを定義する:
from scrapy.item import Item, Field class TencentItem(Item): name = Field() # 职位名称 catalog = Field() # 职位类别 workLocation = Field() # 工作地点 recruitNumber = Field() # 招聘人数 detailLink = Field() # 职位详情页链接 publishTime = Field() # 发布时间
Spider を実装する
Spider はScrapy からの継承。 contrib.spiders.CrawlSpider の Python クラスには 3 つの必須の定義済みメンバーがあります
name: このスパイダーの識別子
start_urls: スパイダーがクロールを開始する URL のリスト
parse(): start_urls の Web ページがクロールされると、このメソッドを呼び出して Web ページのコンテンツを解析する必要があります。同時に、クロールされる次の Web ページを返すか、項目リストを返す必要があります
ので、新しいメソッドを作成します。 Spider ディレクトリの tencent_spider.py:
import re import json from scrapy.selector import Selector try: from scrapy.spider import Spider except: from scrapy.spider import BaseSpider as Spider from scrapy.utils.response import get_base_url from scrapy.utils.url import urljoin_rfc from scrapy.contrib.spiders import CrawlSpider, Rule from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor as sle from itzhaopin.items import * from itzhaopin.misc.log import * class TencentSpider(CrawlSpider): name = "tencent" allowed_domains = ["tencent.com"] start_urls = [ "http://hr.tencent.com/position.php" ] rules = [ # 定义爬取URL的规则 Rule(sle(allow=("/position.php\?&start=\d{,4}#a")), follow=True, callback='parse_item') ] def parse_item(self, response): # 提取数据到Items里面,主要用到XPath和CSS选择器提取网页数据 items = [] sel = Selector(response) base_url = get_base_url(response) sites_even = sel.css('table.tablelist tr.even') for site in sites_even: item = TencentItem() item['name'] = site.css('.l.square a').xpath('text()').extract() relative_url = site.css('.l.square a').xpath('@href').extract()[0] item['detailLink'] = urljoin_rfc(base_url, relative_url) item['catalog'] = site.css('tr > td:nth-child(2)::text').extract() item['workLocation'] = site.css('tr > td:nth-child(4)::text').extract() item['recruitNumber'] = site.css('tr > td:nth-child(3)::text').extract() item['publishTime'] = site.css('tr > td:nth-child(5)::text').extract() items.append(item) #print repr(item).decode("unicode-escape") + '\n' sites_odd = sel.css('table.tablelist tr.odd') for site in sites_odd: item = TencentItem() item['name'] = site.css('.l.square a').xpath('text()').extract() relative_url = site.css('.l.square a').xpath('@href').extract()[0] item['detailLink'] = urljoin_rfc(base_url, relative_url) item['catalog'] = site.css('tr > td:nth-child(2)::text').extract() item['workLocation'] = site.css('tr > td:nth-child(4)::text').extract() item['recruitNumber'] = site.css('tr > td:nth-child(3)::text').extract() item['publishTime'] = site.css('tr > td:nth-child(5)::text').extract() items.append(item) #print repr(item).decode("unicode-escape") + '\n' info('parsed ' + str(response)) return items def _process_request(self, request): info('process ' + str(request)) return request
PipeLine の実装
PipeLine は Spider によって返されたアイテム リストを保存するために使用され、ファイル、データベースなどに書き込むことができます。
PipeLine には実装する必要があるメソッドが 1 つだけあります: process_item。たとえば、Item を JSON 形式のファイルに保存します:
pipelines.py
from scrapy import signals import json import codecs class JsonWithEncodingTencentPipeline(object): def __init__(self): self.file = codecs.open('tencent.json', 'w', encoding='utf-8') def process_item(self, item, spider): line = json.dumps(dict(item), ensure_ascii=False) + "\n" self.file.write(line) return item def spider_closed(self, spider): self.file.close( )
ここまでで、基本的なクローラーの実装が完了しました。次のコマンドを入力できます。 このスパイダーを開始するには:
scrapy crawl tencent
クローラーの実行が完了すると、現在のディレクトリに tencent.json という名前のファイルが生成され、求人情報が JSON 形式で保存されます。
内容の一部は以下の通りです
{"recruitNumber": ["1"]、"name": ["SD5-シニア モバイル ゲーム プランニング (深セン)"]、"detailLink": "http://hr.tencent.com/position_detail.php?id =15626&keywords=&tid=0&lid=0", "publishTime": ["2014-04-25"]、"catalog": ["製品/プロジェクト カテゴリ"]、"workLocation": ["深セン"]}
{ "recruitNumber": ["1"]、"name": ["TEG13-バックエンド開発エンジニア (深セン)"]、"detailLink": "http://hr.tencent.com/position_detail.php?id=15666&keywords= &tid=0&lid=0", "publishTime": ["2014-04-25"]、"catalog": ["技術カテゴリ"]、"workLocation": ["深セン"]}
{"recruitNumber": [ "2"]、"name": ["TEG12-データ センター シニア マネージャー (深セン)"]、"detailLink": "http://hr.tencent.com/position_detail.php?id=15698&keywords=&tid=0&lid= 0"、"publishTime": ["2014-04-25"]、"catalog": ["テクノロジー"]、"workLocation": ["深セン"]}
{"recruitNumber": ["1"] 、 "name": ["GY1-WeChat Pay ブランド プランニング マネージャー (深セン)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15710&keywords=&tid=0&lid=0", " publicTime": ["2014-04-25"]、"catalog": ["Market Class"]、"workLocation": ["Shenzhen"]}
{"recruitNumber": ["2"]、"name " : ["SNG06-バックエンド開発エンジニア (深セン)"]、"detailLink": "http://hr.tencent.com/position_detail.php?id=15499&keywords=&tid=0&lid=0"、"publishTime": [ " 2014-04-25"]、"catalog": ["テクノロジー"]、"workLocation": ["深セン"]}
{"recruitNumber": ["2"]、"name": ["OMG01 -Tencentファッションビデオ企画編集者(北京)"], "detailLink": "http://hr.tencent.com/position_detail.php?id=15694&keywords=&tid=0&lid=0", "publishTime": ["2014- 04- 25"], "catalog": ["コンテンツ編集クラス"], "workLocation": ["北京"]}
{"recruitNumber": ["1"], "name": ["HY08-QT クライアント Windows開発エンジニア (深セン)"]、"detailLink": "http://hr.tencent.com/position_detail.php?id=11378&keywords=&tid=0&lid=0"、"publishTime": ["2014-04 -25" ], "catalog": ["Technology"], "workLocation": ["Shenzhen"]}
{"recruitNumber": ["5"], "name": ["HY1-モバイル ゲーム テスト マネージャー (上海) "], "detailLink": "http://hr.tencent.com/position_detail.php?id=15607&keywords=&tid=0&lid=0", "publishTime": ["2014-04-25"] , "カタログ" : ["技術"]、"勤務場所": ["上海"]}
{"採用番号": ["1"]、"名前": ["HY6-インターネット カフェ プラットフォーム シニア プロダクト マネージャー (深セン)"]、 "detailLink": "http://hr.tencent.com/position_detail.php?id=10974&keywords=&tid=0&lid=0"、"publishTime": ["2014-04-25"]、"カタログ ": ["製品/プロジェクト カテゴリ"], "勤務場所": ["深セン"]}
{"採用番号": ["4"], "名前": ["TEG14-クラウド ストレージ R&D エンジニア (深セン)" ], "detailLink ": "http://hr.tencent.com/position_detail.php?id=15168&keywords=&tid=0&lid=0"、"publishTime": ["2014-04-24"]、"catalog": ["テクニカル" ], "workLocation": ["深セン"]}
{"recruitNumber": ["1"]、"name": ["CB-Compensation Manager (Shenzhen)"]、"detailLink": "http:// hr.tencent.com/position_detail.php?id=2309&keywords=&tid=0&lid=0"、"publishTime": ["2013-11-28"]、"catalog": ["Functional Class"] 、"workLocation": [「深セン」]}