如何用Mathematica寫一個爬蟲?

想用Mathematica分析知乎的社交網路結構,爬一個子主題的點贊關係,爬成一個有向圖.

大概用來分析,該主題的活躍度和同質性,給定用戶的影響力和權威性.

效果大概如圖:


挺有意思的問題,我來拋磚引玉一發。

先上代碼,寫得略丑且沒加註釋,勿怪。。。。

questionID = 27834147;
questionAddress =
"https://www.zhihu.com/question/" &<&> ToString[questionID] &<&> "/";
xml = Import[questionAddress,
"Text"]; aidAndatokenList = (StringTrim[StringSplit[#, "="],
"""] /@ StringSplit[#][[1 ;; 2]])[[All, 2]] /@
StringSplit[xml,
"itemscope itemtype="http://schema.org/Answer"
"][[2 ;; -1]];
numOfAnonymous = 0;
getVote[{aid_, atoken_}] :=
Module[{author, tmpxml, votersProfileAdress, votersProfile, total,
voters},
tmpxml = Import[questionAddress &<&> "answer/" &<&> atoken, "XMLObject"];
votersProfileAdress =
"https://www.zhihu.com/answer/" &<&> aid &<&>
"/voters_profile?offset=";
SetSharedVariable[votersProfileAdress];
author =
Cases[tmpxml, {__, "title" -&> user_, __, "href" -&> url_} :&> {user,
url}, Infinity];
author =
If[author == {}, {"匿名用戶" &<&> ToString[++numOfAnonymous],
ToString[numOfAnonymous]}, author[[1]]];
votersProfile =
ImportString[URLFetch[votersProfileAdress &<&> "0"], "JSON"];
total = "total" /. votersProfile[[2, 2]];
voters =
StringCases[#, {"&
username,
"
href="" ~~ Shortest[url__] ~~ "">
" :&> url}] /@
votersProfile[[3, 2]];
voters = {{voters}, ParallelTable[
StringCases[#, {"& username,
"
href="" ~~ Shortest[url__] ~~ "">
" :&> url}] /@
ImportString[URLFetch[votersProfileAdress &<&> ToString[i]],
"JSON"][[3, 2]]
, {i, 10, total - 1, 10}]} // Flatten[#, 2] //
DeleteCases[#, {}] ;
{author, voters}
];
relationship = getVote /@ aidAndatokenList; // AbsoluteTiming

大概說明一下吧:選取Mathematica 到底有多厲害? - Wolfram Mathematica這個問題為例,抓取其中的所有回答,然後逐個回答抓取作者和點贊者

運行結果如下

然後試著畫個圖(因為有重名用戶存在所以這裡用的是用戶的url)

然後說一下現在的幾個問題:

  1. 不知道怎麼用MMA登錄知乎,導致抓取的點贊者不全。比如這個問題里AlephAlpha的回答有2305個贊,我的程序只抓取到了1700多個,剩下的全是空列表被刪掉了;
  2. 題主問的是子主題的點贊關係,我這個只是一個問題的。怎樣獲得子主題的問題列表還沒研究出來。
  3. 圖畫出來以後並不直觀,需要進一步的分析才能得到結果。我對社交網路分析這塊完全不熟。。。
  4. 效率問題。這是只有十幾個回答的問題,程序都跑了半分鐘才出結果(這還是用了並行),如果真要抓取子主題不知得跑多久了。

參考鏈接:

  1. 抓取豆瓣相冊圖片——Mathematica版,關於用MMA做爬蟲的大部分知識都是從這裡學來的
  2. 如何寫個爬蟲程序扒下知乎某個回答所有點贊用戶名單? - 洛克的回答,關於知乎網頁的各種關鍵詞都是從這個回答學的

磚已拋完,坐等引玉~


先佔個坑...

Clear["`*"];
topicID = 19554091;
maxPage = 50;
topicAddress[i_] :=
"www.zhihu.com/topic/" &<&> ToString[topicID] &<&>
"/top-answers?page=" &<&> ToString[i] &<&> "/";
xml[i_] := topicAddress[i] // URLFetch;
questions[i_] :=
StringCases[xml[i], "href="/question/" ~~ DigitCharacter .. ~~ "">"]
questionList =
Table[StringCases[questions[i_], DigitCharacter ..], {i, 1,
maxPage}] // Flatten;
questionAddress[x_] :=
"https://www.zhihu.com/question/" &<&> ToString[x] &<&> "/" // URLFetch;
aidAndatokenList[
x_] := (StringTrim[StringSplit[#, "="], """] /@
StringSplit[#][[1 ;; 2]])[[All, 2]] /@
StringSplit[questionAddress[x],
"itemscope itemtype="http://schema.org/Answer"
"][[2 ;; -1]];

讓我想想那個data-aid和data-atoken怎麼用.

貌似寫不下去了...模擬登陸什麼鬼.....

然後寫了個和題目無關緊要的東西

Clear["`*"];
topicID = 19571350;
maxPage = 33;
topicAddress[i_] :=
"www.zhihu.com/topic/" &<&> ToString[topicID] &<&>
"/top-answers?page=" &<&> ToString[i] &<&> "/";
xml[i_] := topicAddress[i] // URLFetch;
questions[i_] :=
StringCases[xml[i], "href="/question/" ~~ DigitCharacter .. ~~ "">"]
questionList =
Table[StringCases[questions[i_], DigitCharacter ..], {i, 1,
maxPage}] // Flatten;
questionAddress[x_] :=
"https://www.zhihu.com/question/" &<&> ToString[x] &<&> "/";
answer[x_] :=
StringCases[questionAddress[x] // URLFetch,
"&

"]
zanList[x_] := StringCases[answer[x], DigitCharacter ..] // Flatten;
zanData = zanList /@ questionList // ToExpression

可以分析某話題下的問題的點贊排序:

縱坐標取10的對數

上面是按自然排序,可以看出知乎的排名演算法還是很有意思的

靠前贊不一定多,特別是排第二的贊數普遍特低.看綠線,排19名還有300贊.

下面的圖是排序後的,可以發現是近似指數增長,而且關鍵是這是取10對數後的指數增長

統計結果顯示二八法則完全適用,12%的答案佔了88%贊…


可以使用cookie,增強一些頁面的下載,比如淘寶搜索頁面等,知乎沒試過。

可以curl下看下

佔個坑,刷下存在感,歡迎大家回答我的問題。

有空我發幾個case

如果熟悉了的話,字元串模式寫得比較順,個人工作中解析網頁,分析臨時日誌等使用較多,用得較爽。

從我的使用經驗來講,我也主要使用了3種較簡單的方式

1種是Curl,因為可以集成到RunProcess中,然後有個外部的東西更新cookie文件或手動更新。。。然後用mma解析等

2是只用URLFeatch/Save等,同時也涉及到cookie的問題

3是有些網站有API可以登錄,比如wikipedia的書籤


推薦閱讀:

Mathematica中下標不能用區分變數嗎?
在mathematica中怎麼限定一個變數的類型,比如整數,正數,實數,複數等?
為什麼wolfram做了mathworld卻沒有physicsworld?
如何用計算機生成一段隨機的音樂?

TAG:WolframMathematica |