Zhihu は、あらゆる階層のエリートを結び付ける、フレンドリーで合理的かつ真剣なコミュニティ雰囲気を持つ本物のオンライン Q&A コミュニティです。彼らはお互いの専門知識、経験、見識を共有し、中国のインターネットに質の高い情報を継続的に提供しています。
まず、3 ~ 5 分かけてロゴをデザインします =。 =プログラマーとして、私は常にアーティストになりたいという気持ちを持っていました。
まあ、ちょっとした間に合わせなので、とりあえずはこれで間に合います。
次にZhihuのクローラーを作り始めました。
まず、最初の目標である編集者の推薦を決定します。
Web リンク: http://www.zhihu.com/explore/recommendations
最初にページのコンテンツを取得できるようにするために、最後のコードを少し変更しました。
java.io.* をインポートします。
java.net.* をインポートします。
java.util.regex.* をインポートします。
パブリッククラス Main {
静的 String SendGet(String url) {
// Web ページのコンテンツを保存する文字列を定義します
文字列結果 = "";
//バッファリングされた文字入力ストリームを定義する
BufferedReader の = null;
試す {
//文字列をURLオブジェクトに変換
URL realUrl = 新しい URL(url);
// その URL へのリンクを初期化します
URLConnection 接続 = realUrl.openConnection();
// 実際の接続を開始します
接続.connect();
// URL の応答を読み取るために BufferedReader 入力ストリームを初期化します
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
// キャプチャされた各行のデータを一時的に保存するために使用されます
文字列行;
while ((line = in.readLine()) != null) {
// キャプチャされた各行を走査し、結果に格納します
結果 += 行;
}
} catch (例外 e) {
System.out.println("GET リクエストの送信中に例外が発生しました!" + e);
e.printStackTrace();
}
// 入力ストリームを閉じるには、finally を使用します。
ついに {
試す {
if (in != null) {
in.close();
}
} キャッチ (例外 e2) {
e2.printStackTrace();
}
}
結果を返します。
}
静的 String RegexString(String targetStr, String patternStr) {
// 正規表現を使用してスタイル テンプレートを定義します。キャプチャされるコンテンツは括弧内にあります
// 罠を埋めるのと同じで、一致すると落ちます。
パターン pattern = Pattern.compile(patternStr);
// マッチング用のマッチャーを定義する
マッチャー matcher = pattern.matcher(targetStr);
// 見つかった場合
if (matcher.find()) {
// 結果を出力します
matcher.group(1) を返します。
}
「何もない」を返します。
}
public static void main(String[] args) {
// アクセスするリンクを定義します
文字列 URL = "http://www.zhihu.com/explore/recommendations";
// リンクにアクセスしてページのコンテンツを取得します
文字列結果 = SendGet(url);
// 正規表現を使用して画像の src コンテンツと一致します
//String imgSrc = RegexString(result, "src=/"(.+?)/"");
// 結果を出力する
System.out.println(結果);
}
}
実行後は問題ありません。次は通常のマッチング問題です。
まず、このページにあるすべての質問を取得しましょう。
タイトルを右クリックして要素を調べます。
ああ、タイトルは実際にはハイパーリンクである a タグであることがわかります。他のハイパーリンクと区別できるのはクラス、つまりクラス セレクターであるはずです。
したがって、通常のステートメントは次のようになります: question_link.+?href=/"(.+?)/"
RegexString 関数を呼び出してパラメータを渡します。
public static void main(String[] args) {
// アクセスするリンクを定義します
文字列 URL = "http://www.zhihu.com/explore/recommendations";
// リンクにアクセスしてページのコンテンツを取得します
文字列結果 = SendGet(url);
// 正規表現を使用して画像の src コンテンツと一致します
String imgSrc = RegexString(result, "question_link.+?>(.+?)<");
// 結果を出力する
System.out.println(imgSrc);
}
ああ、タイトルを取得できたことがわかります (1 つだけであることに注意してください)。
ちょっと待って、この混乱は何ですか? !
緊張しないでください=。 =ただの文字化けです。
エンコードの問題については、HTML 文字セットを参照してください。
一般に、中国語のサポートが強化されている主流のエンコーディングは、UTF-8、GB2312、GBK エンコーディングです。
Web ページは、メタ タグの文字セットを通じて Web ページのエンコードを設定できます。次に例を示します。
<meta charset="utf-8" />
右クリックしてページのソースコードを表示してみましょう。
ご覧のとおり、Zhihu は UTF-8 エンコーディングを使用します。
ここでは、ページのソースコードの表示と要素の検査の違いについて説明します。
ページのソース コードを表示すると、HTML タグに従ってフォーマットされていないため、Web ページ全体の情報を表示する場合に便利です。メタ。
Inspect 要素、または一部のブラウザでは view 要素と呼ばれます。これは、div や img など、右クリックした要素を表示します。これは、オブジェクトの属性とタグを個別に表示するのに適しています。
さて、問題がエンコーディングにあることがわかりました。次のステップは、キャプチャされたコンテンツのエンコーディングを変換することです。
Java での実装は非常に簡単で、InputStreamReader でエンコード メソッドを指定するだけです。
// URL の応答を読み取るために BufferedReader 入力ストリームを初期化します
in = new BufferedReader(new InputStreamReader(
connection.getInputStream(),"UTF-8"));
この時点でプログラムを再度実行すると、タイトルが正常に表示されることがわかります。
わかりました!とても良い!
しかし、現在はタイトルが 1 つだけなので、すべてのタイトルが必要です。
正規表現を少し変更し、検索結果を ArrayList に保存します。
java.io.* をインポートします。
java.net.* をインポートします。
java.util.ArrayListをインポートします。
java.util.regex.* をインポートします。
パブリッククラス Main {
静的 String SendGet(String url) {
// Web ページのコンテンツを保存する文字列を定義します
文字列結果 = "";
//バッファリングされた文字入力ストリームを定義する
BufferedReader の = null;
試す {
//文字列をURLオブジェクトに変換
URL realUrl = 新しい URL(url);
// その URL へのリンクを初期化します
URLConnection 接続 = realUrl.openConnection();
// 実際の接続を開始します
接続.connect();
// URL の応答を読み取るために BufferedReader 入力ストリームを初期化します
in = new BufferedReader(new InputStreamReader(
connection.getInputStream(), "UTF-8"));
// キャプチャされた各行のデータを一時的に保存するために使用されます
文字列行;
while ((line = in.readLine()) != null) {
// キャプチャされた各行を走査し、結果に格納します
結果 += 行;
}
} catch (例外 e) {
System.out.println("GET リクエストの送信中に例外が発生しました!" + e);
e.printStackTrace();
}
// 入力ストリームを閉じるには、finally を使用します。
ついに {
試す {
if (in != null) {
in.close();
}
} キャッチ (例外 e2) {
e2.printStackTrace();
}
}
結果を返します。
}
static ArrayList<String> RegexString(String targetStr, String patternStr) {
// 結果を保存するための ArrayList を事前定義します
ArrayList<String> 結果 = new ArrayList<String>();
// 正規表現を使用してスタイル テンプレートを定義します。キャプチャされるコンテンツは括弧内にあります
パターン pattern = Pattern.compile(patternStr);
// マッチング用のマッチャーを定義する
マッチャー matcher = pattern.matcher(targetStr);
// 見つかった場合
ブール値 isFind = matcher.find();
// ループを使用して文内のすべてのケルビンを検索して置換し、その内容を sb に追加します
while (isFind) {
// 成功した一致結果を追加します
results.add(matcher.group(1));
// 次に一致するオブジェクトの検索を続けます
isFind = matcher.find();
}
結果を返します。
}
public static void main(String[] args) {
// アクセスするリンクを定義します
文字列 URL = "http://www.zhihu.com/explore/recommendations";
// リンクにアクセスしてページのコンテンツを取得します
文字列結果 = SendGet(url);
// 正規表現を使用して画像の src コンテンツと一致します
ArrayList<String> imgSrc = RegexString(result, "question_link.+?>(.+?)<");
// 結果を出力する
System.out.println(imgSrc);
}
}
これはすべての結果と一致します (ArrayList が直接出力されるため、角括弧とカンマがいくつかあります)。
OK、これが Zhihu クローラーの最初のステップです。
しかし、この方法ですべての質問と回答を取得する方法はないことがわかります。
キャプチャされたすべてのオブジェクトを保存するために Zhihu カプセル化クラスを設計する必要があります。
Zhihu.java ソース コード:
java.util.ArrayListをインポートします。
パブリッククラス Zhihu {
public String 質問 // 質問;
public String zhihuUrl;//Web ページのリンク
public ArrayList<String> 回答 // すべての回答を格納する配列。
// コンストラクターがデータを初期化します
public Zhihu() {
質問 = "";
zhihuUrl = "";
答え = 新しい ArrayList<String>();
}
@オーバーライド
public String toString() {
return "質問:" + 質問 + "/nLink:" + zhihuUrl + "/nAnswer:" + 回答 + "/n";
}
}
新しい Spider クラスを作成して、クローラーの一般的に使用される機能をいくつか保存します。
Spider.java ソース コード:
java.io.BufferedReaderをインポートします。
インポートjava.io.InputStreamReader;
java.net.URLをインポートします。
java.net.URLConnectionをインポートします。
java.util.ArrayListをインポートします。
java.util.regex.Matcherをインポートします。
java.util.regex.Patternをインポートします。
パブリッククラス Spider {
静的 String SendGet(String url) {
// Web ページのコンテンツを保存する文字列を定義します
文字列結果 = "";
//バッファリングされた文字入力ストリームを定義する
BufferedReader の = null;
試す {
//文字列をURLオブジェクトに変換
URL realUrl = 新しい URL(url);
// その URL へのリンクを初期化します
URLConnection 接続 = realUrl.openConnection();
// 実際の接続を開始します
接続.connect();
// URL の応答を読み取るために BufferedReader 入力ストリームを初期化します
in = new BufferedReader(new InputStreamReader(
connection.getInputStream(), "UTF-8"));
// キャプチャされた各行のデータを一時的に保存するために使用されます
文字列行;
while ((line = in.readLine()) != null) {
// キャプチャされた各行を走査し、結果に格納します
結果 += 行;
}
} catch (例外 e) {
System.out.println("GET リクエストの送信中に例外が発生しました!" + e);
e.printStackTrace();
}
// 入力ストリームを閉じるには、finally を使用します。
ついに {
試す {
if (in != null) {
in.close();
}
} キャッチ (例外 e2) {
e2.printStackTrace();
}
}
結果を返します。
}
static ArrayList<Zhihu> GetZhihu(String content) {
// 結果を保存するための ArrayList を事前定義します
ArrayList<Zhihu> 結果 = new ArrayList<Zhihu>();
// タイトルを一致させるために使用されます
パターン questionPattern = Pattern.compile("question_link.+?>(.+?)<");
マッチャー questionMatcher = questionPattern.matcher(content);
// 質問へのリンクである URL を照合するために使用されます
パターン urlPattern = Pattern.compile("question_link.+?href=/"(.+?)/"");
マッチャー urlMatcher = urlPattern.matcher(content);
// 質問とリンクの両方が一致する必要があります
boolean isFind = questionMatcher.find() && urlMatcher.find();
while (isFind) {
// キャプチャした情報を保存する Zhihu オブジェクトを定義します
zhihu zhuhuTemp = new Zhihu();
zhuhuTemp.question = questionMatcher.group(1);
zhuhuTemp.zhihuUrl = "http://www.zhihu.com" + urlMatcher.group(1);
// 成功した一致結果を追加します
results.add(zhuhuTemp);
// 次に一致するオブジェクトの検索を続けます
isFind = questionMatcher.find() && urlMatcher.find();
}
結果を返します。
}
}
最後の main メソッドは呼び出しを担当します。
java.util.ArrayListをインポートします。
パブリッククラス Main {
public static void main(String[] args) {
// アクセスするリンクを定義します
文字列 URL = "http://www.zhihu.com/explore/recommendations";
// リンクにアクセスしてページのコンテンツを取得します
文字列コンテンツ = Spider.SendGet(url);
// このページ上のすべての Zhihu オブジェクトを取得します
ArrayList<Zhihu> myZhihu = Spider.GetZhihu(content);
// 結果を出力する
System.out.println(myZhihu);
}
}
はい、以上です。実行して結果を確認します。
良い結果が得られました。
次のステップは、リンクにアクセスしてすべての答えを取得することです。
次回ご紹介させていただきます。
さて、上記は Zhihu 編集者が推奨する Java を使用してコンテンツをキャプチャする方法の全体的な手順を簡単に紹介したものです。必要な友人はそれを参照して自由に拡張できます。