Baru -baru ini, saya perlu merangkak informasi artikel dari akun resmi WeChat. Saya mencari secara online dan menemukan bahwa kesulitan merangkak akun publik WeChat adalah bahwa tautan ke artikel akun resmi tidak dapat dibuka di sisi PC. Kita harus menggunakan browser WeChat sendiri (Anda hanya dapat membukanya di platform lain setelah Anda mendapatkan parameter yang ditambah oleh klien WeChat). Ini menyebabkan masalah besar pada program crawler. Kemudian, saya melihat program perayapan resmi WeChat yang ditulis oleh seorang pria besar di Zhihu, dan langsung mengikuti ide bos dan mengubahnya menjadi Java. Saya mengalami banyak masalah terperinci selama transformasi, jadi saya akan membagikannya.
Gagasan dasar sistem ini adalah menjalankan WeChat pada emulator android, mengatur proxy untuk emulator, mencegat data weChat melalui server proxy, dan mengirim data yang diperoleh ke program Anda sendiri untuk diproses.
Lingkungan yang perlu disiapkan: NodeJs, anyproxy proxy, dan android emulator
Alamat unduhan nodejs: http://nodejs.cn/download/. Saya mengunduh versi Windows, cukup instal secara langsung. Setelah instalasi, menjalankan file C:/Program/NodeJS/NPM.CMD akan secara otomatis mengonfigurasi lingkungan.
Instalasi anyproxy: Setelah menginstal nodeJs sesuai dengan langkah sebelumnya, jalankan instalasi npm -g anyproxy langsung di cmd dan instal
Pergi saja ke Android Emulator online, banyak dari mereka.
Pertama, instal sertifikat untuk server proxy. AnyProxy tidak menyelesaikan tautan HTTPS secara default. Setelah menginstal sertifikat, itu dapat diselesaikan. Jalankan anyproxy --root di CMD untuk menginstal sertifikat. Setelah itu, Anda harus mengunduh sertifikat ini di emulator.
Kemudian masukkan perintah apa saja -i untuk membuka layanan proxy. (Ingatlah untuk menambahkan parameter!)
Ingat IP dan port ini, dan kemudian agen emulator Android akan menggunakannya. Sekarang gunakan browser Anda untuk membuka halaman web: http: // localhost: 8002/Ini adalah antarmuka web apa pun, yang digunakan untuk menampilkan data transmisi http.
Klik pada menu di kotak merah di atas dan kode QR akan dirilis. Gunakan emulator Android untuk memindai kode untuk mengidentifikasinya. Emulator (ponsel) akan mengunduh sertifikat dan hanya menginstalnya.
Sekarang Anda siap mengatur proxy untuk emulator. Metode proxy diatur ke manual. IP proxy adalah IP yang menjalankan mesin apa pun, dan port adalah 8001
Pekerjaan persiapan pada dasarnya selesai di sini. Buka WeChat pada emulator dan buka artikel di akun publik, dan Anda dapat melihat data yang ditangkap oleh apa pun dari antarmuka web yang baru saja Anda buka:
Tautan ke artikel WeChat ada di kotak merah di atas. Klik untuk melihat data spesifik. Jika tidak ada di badan respons, ada masalah dengan instalasi sertifikat.
Jika semua hal di atas selesai, Anda dapat terus berjalan ke bawah.
Di sini kami mengandalkan layanan proxy untuk menangkap data WeChat, tetapi kami tidak dapat mengambil sepotong data dan mengoperasikan WeChat sendiri. Lebih baik menyalinnya secara manual. Jadi kita membutuhkan klien WeChat untuk melompat ke halaman dengan sendirinya. Pada saat ini, Anda dapat menggunakan apa pun untuk mencegat data yang dikembalikan oleh server WeChat, menyuntikkan kode lompatan halaman ke dalamnya, dan kemudian mengembalikan data yang diproses ke simulator untuk mencapai lompatan otomatis klien WeChat.
Buka file JS yang disebut aturan_default.js di anyproxy. File di bawah Windows adalah: c:/user/administrator/appData/roaming/npm/node_modules/anyproxy/lib
Ada metode yang disebut ReplacesEverResDataAsync: Function (Req, Res, ServerresData, Callback) dalam file. Metode ini bertanggung jawab untuk melakukan berbagai operasi pada data yang diperoleh oleh anyproxy. Pada awalnya, hanya ada Callback (ServerresData); Pernyataan ini berarti mengembalikan data respons server secara langsung ke klien. Hapus pernyataan ini secara langsung dan ganti dengan kode berikut yang ditulis oleh Daniu. Saya belum membuat perubahan pada kode di sini, dan komentar di dalamnya dijelaskan dengan sangat jelas. Baca saja mereka langsung menurut logika, dan tidak ada masalah besar.
REPLACESERVERRESDATAASYNC: FUNGSI (REQ, RES, ServerResData, Callback) {if (/mp//GetMassendMSG/i.test (req.url)) {// Ketika alamat tautan adalah halaman Historis Akun Resmi (Formulir Halaman Pertama) //console.log("start halaman pertama CRUWLE CRUWWACK (Formulir Halaman) //console.log(" if (serverresdata.toString ()! == "") {6 coba {// mencegah kesalahan keluar dari program var reg =/msglist = (.*?);/; // Tentukan pesan historis aturan pencocokan reguler var ret = reg.exec (serverresdata.toString ()); // Convert ke string (servererresdata.toString ()); // Convert ke string (serverResData.ToString ()); // Convert ke string (servererresdata.toString ()); // Convert ke string (serverResData.ToString ()); // Convert ke string (servererresdata.toString ());//Convert variabel ke string (serverResData.ToString ()); // Convert to String Httppost (ret [1], req.url, "/internetspider/getData/showbiz"); // fungsi ini didefinisikan nanti, mengirimkan pesan historis yang cocok JSON ke servernya sendiri var http = membutuhkan ('http'); http.get ('http: // xxx/getwxhis', function (res) {// alamat ini adalah program di servernya sendiri. Tujuannya adalah untuk mendapatkan alamat tautan berikutnya, tempatkan alamat dalam skrip JS, dan secara otomatis melompat ke halaman berikutnya. Prinsip GetWxHis.php akan diperkenalkan nanti. callback (chunk+serverResData); // masukkan kode yang dikembalikan ke halaman pesan historis dan kembali untuk menampilkannya})}); } catch (e) {// Jika reguler di atas tidak cocok, maka konten halaman ini mungkin halaman kedua dari halaman pesan historis akun resmi yang ditolak, karena halaman pertama dari pesan historis dalam format HTML, dan halaman kedua dalam format JSON. //console.log("start halaman pertama merangkak ke bawah bentuk "); coba {var json = json.parse (serverresdata.toString ()); if (json.general_msg_list! = []) {httppost (json.general_msg_list, req.url, "/xxx/showbiz"); // fungsi ini didefinisikan nanti seperti di atas, mengirimkan json dari halaman kedua pesan historis ke server Anda sendiri}} catch (e) {console. Callback (ServerResData); // Kembalikan langsung ke konten JSON halaman kedua}} //console.log("Start halaman crawl halaman pertama "); } lain jika (/mp//profile_ext/?action=home/i.test (req.url)) {// Ketika alamat tautannya adalah halaman pesan historis akun resmi (formulir halaman kedua) coba {var reg =/var msglist = /'(.* ?) Reg.exec (ServerResData.ToString ()); // Konversi variabel menjadi string httppost (ret [1], req.url, "/xxx/showbiz"); // fungsi ini didefinisikan nanti, kirim pesan historis yang cocok ke servernya sendiri var http = memerlukan ('http'); http.get ('xxx/getwxhis', function (res) {// Alamat ini adalah program di server Anda. Tujuannya adalah untuk mendapatkan alamat tautan berikutnya, tempatkan alamat dalam skrip JS, dan secara otomatis melompat ke halaman berikutnya. Prinsip/Chunk. ke halaman pesan historis dan kembali untuk menampilkannya})}); } catch (e) {//console.log(e); Callback (ServerresData); }} lain jika (/mp//profile_ext/?action=GetMSg/i.test (req.url)) {// ekspresi halaman kedua json coba {var json = json.parse (serverresdata.toString ()); if (json.general_msg_list! = []) {httppost (json.general_msg_list, req.url, "/xxx/showbiz"); // fungsi ini didefinisikan nanti seperti di atas, mengirimkan JSON dari pesan historis halaman kedua ke servernya sendiri}}} catch (e) {console. } callback (serverresdata); } lain jika (/mp//getAppMSgext/i.test (req.url)) {// Ketika alamat tautannya adalah jumlah pandangan dan suka untuk artikel akun resmi, coba {httpppost (serverresdata for poist, "/xxx/getMsgext"); fungsinya yang ditentukan, "/xxx/getsgext"); // fungsinya ditentukan, "/xxx/getMsgext"); // Fungsi -fungsinya ditentukan, dan fungsi ke kemudian, dan fungsi ini adalah function, dan xxx/getsgext "); server} catch (e) {} callback (serverResData); } lain jika (/s/? __ biz/i.test (req.url) || /mp//rumor/i.test(req.url)) {//khen alamat tautannya adalah artikel akun resmi (alamat rumor adalah artikel resmi, ditolak) coba {var http = membutuhkan ('http'); http.get ('http: // xxx/getwxpost', function (res) {// alamat ini adalah program lain di server Anda. Tujuannya adalah untuk mendapatkan alamat tautan berikutnya, tempatkan alamat dalam skrip JS, dan secara otomatis melompat ke halaman berikutnya. Prinsip GetWxPost.php akan diperkenalkan nanti. })}); } catch (e) {callback (serverresdata); }} else {callback (serverResData); } // Callback (ServerResData); },Izinkan saya menjelaskan secara singkat di sini bahwa ada dua bentuk tautan ke halaman pesan historis akun resmi WeChat: satu dimulai dengan mp.weixin.qq.com/mp/getmassendmsg, dan yang lainnya dimulai dengan mp.weixin.qq.com/mp/profile_ext. Halaman riwayat dapat dibalik. Jika terbalik, itu akan memicu acara JS untuk mengirim permintaan untuk mendapatkan data JSON (konten halaman berikutnya). Ada juga tautan artikel akun resmi, serta tautan ke jumlah artikel yang dibaca dan disukai (mengembalikan data JSON). Bentuk -bentuk tautan ini diperbaiki dan dapat dibedakan dengan penilaian logis. Ada pertanyaan di sini: bagaimana melakukan jika semua halaman sejarah perlu dirangkak. Ide saya adalah mensimulasikan mouse yang meluncur ke bawah melalui JS, sehingga memicu permintaan untuk mengirimkan permintaan untuk memuat bagian selanjutnya dari daftar. Atau secara langsung menggunakan anyproxy untuk menganalisis permintaan pemuatan geser dan secara langsung menghasilkan permintaan ini ke server WeChat. Tetapi ada masalah dengan bagaimana menilai bahwa tidak ada data yang tersisa. Saya merangkak data terbaru, dan saya tidak memiliki persyaratan ini untuk saat ini, dan saya mungkin menginginkannya di masa depan. Jika Anda membutuhkannya, Anda dapat mencobanya.
Gambar berikut adalah konten metode httpppost di atas.
fungsi httppost (str, url, path) {// kirim json ke server, str adalah konten json, url adalah alamat pesan pesan historis, jalur adalah jalur dan nama file dari program penerima
Console.log ("Mulai Penerusan");
mencoba{
var http = membutuhkan ('http');
var data = {
str: encodeuricomponent (str),
URL: Encodeuricomponent (URL)
};
data = membutuhkan ('queryString'). Stringify (data);
var options = {
Metode: "Posting",
Host: "xxx", // Perhatikan bahwa tidak ada http: //, ini adalah nama domain server.
Port: xxx,
Path: Path, // Jalur dan nama file dari program penerima
header: {
'Tipe konten': 'Aplikasi/X-WWW-Form-Urlencoded; Charset = UTF-8 ',
"Panjang konten": data.length
}
};
var req = http.Request (option, function (res) {
res.setencoding ('UTF8');
res.on ('data', function (chunk) {
console.log ('body:' + chunk);
});
});
req.on ('error', function (e) {
console.log ('Masalah dengan permintaan:' + e.message);
});
req.write (data);
req.end ();
} catch (e) {
console.log ("Pesan kesalahan:"+e);
}
Console.log ("Operasi Penerusan Berakhir");
}Setelah melakukan pekerjaan di atas, langkah selanjutnya adalah menyelesaikan kode server sesuai dengan bisnis Anda sendiri. Layanan kami digunakan untuk menerima data yang dikirim oleh server proxy untuk diproses, melakukan operasi persisten, dan pada saat yang sama mengirim kode JS yang perlu disuntikkan ke WeChat ke server proxy. Untuk data yang dikirim dari beberapa tautan berbeda yang dicegat oleh server proxy, kita perlu merancang metode yang sesuai untuk memproses data ini. Dari metode JS apa pun untuk memproses data WeChat REPLACESRESRESDATAASYNC: FUNGSI (Req, Res, ServerresData, Callback), kita dapat tahu bahwa setidaknya tiga metode diperlukan untuk merancang data halaman sejarah akun resmi, data halaman akun resmi, artikel akun resmi, dan membaca data. Pada saat yang sama, kita juga perlu merancang metode untuk menghasilkan tugas merangkak dan menyelesaikan perjalanan pulang pergi akun resmi. Jika Anda perlu merangkak lebih banyak data, Anda dapat menganalisis lebih banyak data yang dibutuhkan dari tautan yang ditangkap oleh apa pun, dan kemudian menambahkan penilaian ke ReplacesEverResDataAsync: Function (Req, Res, ServerRresdata, Callback), mencegat data yang diperlukan dan mengirimkannya ke server Anda sendiri, dan menambahkan metode yang sesuai untuk memproses jenis data ini pada server.
Saya menulis kode server di Java.
Metode untuk Memproses Data Halaman Riwayat Akun Resmi:
public void getMsgjson (string str, string URL) melempar UnsportedEncodingException {// TODO Metode yang dihasilkan secara otomatis string string biz = ""; Peta <String, String> querystrs = httpurlparser.parseurl (url); if (querystrs! = null) {biz = querystrs.get ("__ biz"); biz = biz + "=="; } /*** Kueri dari database apakah Biz sudah ada, dan masukkan jika tidak ada. * Ini berarti bahwa kami telah menambahkan akun resmi baru untuk target koleksi. */ Daftar <Weixin> hasil = weixInmapper.selectByBiz (biz); if (result == null || results.size () == 0) {weixin weixin = new weixin (); weixin.setbiz (biz); weixin.setCollect (System.currentTimemillis ()); weixinmapper.insert (weixin); } //System.out.println(str); // Parse str variable list <baption> daftar = jsonpath.read (str, "['list']"); untuk (daftar objek: daftar) {objek json = daftar; int type = jsonpath.read (json, "['comm_msg_info'] ['type']"); if (type == 49) {// type = 49 berarti itu adalah pesan teks string content_url = jsonpath.read (json, "$ .app_msg_ext_info.content_url"); content_url = content_url.replace ("//", "") .replaceall ("amp;", ""); // Dapatkan alamat tautan dari pesan teks int is_multi = jsonpath.read (json, "$ .app_msg_ext_info.is_multi"; // // det-grape = kutu MULTIEC_GREC APRETICE = IS ITIFICE = IS ITICE = Jsonpath.read (json, "$ .comm_msg_info.dateTime"); // Kirim waktu pesan gambar dan teks/*** Di sini gambar dan alamat tautan pesan teks dimasukkan ke dalam Perpustakaan Antrian Perpustakaan Lain yang akan diperkenalkan. antrian) */ coba {if (content_url! = null &&! " tmplist.setContentUrl (content_url); tmplistmapper.insertselective (tmplist); }} catch (Exception e) {System.out.println ("Antrian sudah ada, tidak dimasukkan!"); } / *** Di sini kami menilai apakah itu diulang dari posting database berdasarkan $ content_url* / daftar <ost> postlist = postmapper.selectbycontentUrl (content_url); boolean contenturlexist = false; if (postlist! = null && postlist.size ()! = 0) {contenturlexist = true; } if (! ContentUrlexist) {// 'yang sama $ content_url ada dalam posting database' integer fileid = jsonpath.read (json, "$ .app_msg_ext_info.fileid"); // judul weChat ID = jsonpath.Read (json, "$ .apping quechat; = Urlencoder.encode (judul, "UTF-8"); String Digest = jsonPath.read (json, "$ .app_msg_ext_info.digest"); // artikel ringkasan string_url = jsonpath.read (json, "$ .app_msg_ext_info.source_url");//baca tautan teks asli Source_url = Source_urce_urce_url ");//Baca Teks Asli Source_url = Source_Urfo.Source_URL");/Baca Teks Asli Source_url = Source_Urfo.Source_URL ");/Baca Teks Asli Source_url = Source_URLE. Cover string = jsonpath.read (json, "$ .app_msg_ext_info.cover"); // penutup gambar cover = cover.replace ("//", ""); /*** Simpan ke database* /// System.out.println ("title:"+title); // System.out.println ("WeChat ID:"+FileID); // System.out.println ("Ringkasan Artikel:"+Digest); // System.out.println ("Baca Tautan Asli:" Alamat: "+penutup); POST POST = posting baru (); Post.SetBiz (Biz); post.settitle (judul); Post.settitleencode (title_encode); Post.SetFieldId (FileID); Post.setDigest (Digest); POST.SETSOURCEURL (SOURCE_URL); post.setCover (sampul); POST.Setistop (1); // Tandai sebagai headline Content Post.setismulti (is_multi); Post.setDateTime (datetime); Post.SetContentUrl (content_url); postmapper.insert (post); } if (is_multi == 1) {// Jika itu adalah daftar pesan multi-grafik <bestigasi> multilists = jsonpath.read (json, "['app_msg_ext_info'] ['multi_app_msg_item_list']"); untuk (objek multilist: multilists) {objek multijson = multilist; content_url = jsonpath.read (multijson, "['content_url']"). ToString (). REPLACE ("//", "") .replaceall ("amp;", ""); // alamat tautan grafis/** di sini kita akan menilai apakah database diulangi berdasarkan $ content_url/surrorl; Daftar <ost> Posts = PostMapper.SelectByContentUrl (content_url); if (post! = null && posts.size ()! = 0) {contentUrlexist = true; } if (! ContentUrlexist) {// 'Sama $ content_url tidak ada dalam database'/** * di sini, masukkan alamat tautan grafik dan teks ke dalam perpustakaan antrian akuisisi * (Perpustakaan Antrian akan dimasukkan (KONTENSI PENGATURAN UNTUK PROFOMED HANYA UNTUK PENGADILAN PERJALANAN UNTUK PERJANJIAN BATCHERUE UNTUK PERJANJIAN BATCHERUSE, PENGATURAN UNTUK PERJANJIAN BERIKUTNYA, * Program lain akan mengatur KONTENSI PROPENSI PERUSAHAAN SETIAP PRIFICE (PENGADILAN LAIN. null &&! "". Equals (content_url)) {tmplist tmplistt = tmplist baru (); tmplistt.setContentUrl (content_url); tmplistmapper.insertselective (tmplistt); } String title = jsonpath.read (multijson, "$ .title"); String title_encode = urlencoder.encode (judul, "UTF-8"); Integer fileid = jsonpath.read (multijson, "$ .fileId"); String digest = jsonpath.read (multijson, "$ .digest"); String source_url = jsonpath.read (multijson, "$ .source_url"); source_url = source_url.replace ("//", ""); Tutupan string = jsonpath.read (multijson, "$ .cover"); cover = cover.replace ("//", ""); // System.out.println("Title:"+title);// System.out.println("WeChat ID:"+fileid);// System.out.println("Article summary:"+digest);// System.out.println("Read original link:"+source_url);// System.out.println("Cover image address:"+cover); POST POST = posting baru (); Post.SetBiz (Biz); post.settitle (judul); Post.settitleencode (title_encode); Post.SetFieldId (FileID); Post.setDigest (Digest); POST.SETSOURCEURL (SOURCE_URL); post.setCover (sampul); Post.setistop (0); // Tag Ini bukan headline konten Post.setismulti (is_multi); Post.setDateTime (datetime); Post.SetContentUrl (content_url); postmapper.insert (post); }}}}}}}}}Bagaimana menangani halaman artikel akun resmi:
string publik getWxPost () {// TODO Metode yang dihasilkan otomatis Stub / *** Ketika halaman saat ini adalah halaman artikel akun resmi, baca program ini* Hapus pertama load = 1 dalam daftar antrian koleksi* Kemudian pilih beberapa baris menurut "Pesanan oleh ID ASC" dari daftar antrian (perhatikan bahwa baris ini berbeda dari program di atas)* / tmplistm. Daftar <TMPlist> Queues = tMplistMapper.Selectmany (5); String url = ""; if (queue! = null && queues.size ()! = 0 && queue.size ()> 1) {tMplist antrian = queue.get (0); url = queue.getContentUrl (); Queue.setisload (1); int result = tmplistMapper.updatebyprimarykey (antrian); System.out.println ("Hasil Perbarui:"+Hasil); } else {System.out.println ("GetPost Queue adalah null?"+Queue == null? null: queues.size ()); Weixin weixin = weixinmapper.selectone (); String biz = weixin.getBiz (); if ((math.random ()> 0.5? 1: 0) == 1) {url = "http://mp.weixin.qq.com/mp/getMasssendmsg?__biz=" + biz + "wechat_webview_type = 1 & wechat_redirect";/{wechat_webview_type = 1 & wechat_redirect ";/{wechat_webview_type = 1 & wechat_redirect";/{wechat_webview_type = 1 & wechat_redirect ";/{wechat_webview_type = 1 & wechat_redirect";/split {weChat_webiew_type = 1 & wechat_redirect ";/{weChat_webiew_ "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=" + biz + "#wechat_redirect"; // pisahkan alamat URL dari akun historis resmi +}} url = "https://mp.weixin.qq.pq. + "#wechat_redirect"; // Pisahkan alamat URL dari Pesan Historis Akun Resmi (formulir halaman kedua) // Perbarui Bidang Waktu Pengumpulan Waktu di Tabel Akun Resmi yang disebutkan sekarang untuk Cap Waktu saat ini. weixin.setCollect (System.currentTimemillis ()); int result = weixInmapper.updatebyprimarykey (weixin); System.out.println ("GetPost Weixin Updateresult:"+hasil); } int randomtime = random baru (). NextInt (3) + 3; String jscode = "<script> setTimeout (function () {window.location.href = '"+url+"';},"+acak*1000+"); </script>"; mengembalikan jscode; }Cara menangani jumlah suka dan bacaan akun resmi:
public void getMSGEXT (string str, string URL) {// TODO Metode yang dihasilkan secara otomatis string string biz = ""; String sn = ""; Peta <String, String> querystrs = httpurlparser.parseurl (url); if (querystrs! = null) {biz = querystrs.get ("__ biz"); biz = biz + "=="; sn = querystrs.get ("sn"); sn = "%" + sn + "%"; } /** * $ sql = "SELECT * Dari` tabel artikel` di mana `biz` = '". $ biz. "' * dan` content_url` like '%". $ sn."%' "limit 0,1; * Temukan artikel yang sesuai berdasarkan biz dan sn*/ post post = postmapper.selectbybizandsn (biz, sn); if (post == null) {System.out.println ("biz:"+biz); System.out.println ("Sn:"+Sn); tmplistmapper.deletebyload (1); kembali; } // System.out.println ("Data JSON:"+str); Integer read_num; Integer like_num; Coba {read_num = jsonpath.read (str, "['appmsgstat'] ['read_num']"); // baca volume like_num = jsonpath.read (str, "['appmsgstat'] ['like_num']"); // like volume} catch (pengecualian e) {like_num = 123; System.out.println ("read_num:"+read_num); System.out.println ("like_num:"+like_num); System.out.println (e.getMessage ()); } /*** Di sini, artikel yang sesuai juga dihapus dalam daftar antrian koleksi berdasarkan SN, yang berarti bahwa artikel ini dapat dihapus dari antrian koleksi. * $ sql = "hapus dari` daftar tim` di mana `content_url` like '%". $ sn. "%'" */ tMplistMapper.deletebysn (sn); // Kemudian perbarui jumlah tampilan dan suka dengan tabel artikel. Post.setreadnum (read_num); Post.setlikenum (like_num); postmapper.updatebyprimarykey (post); }Cara menangani lompatan ke wechat injection js:
string publik getWxHis () {string url = ""; // TODO Metode yang dihasilkan otomatis Stub /*** Ketika halaman saat ini adalah pesan historis akun publik, baca program ini* Ada bidang pemuatan dalam daftar antrian koleksi. Ketika nilainya sama dengan 1, itu berarti sedang dibaca* pertama hapus load line = 1 dalam daftar antrian koleksi* Kemudian pilih baris apa pun dari daftar tim*/ tmplistmapper.deletebyload (1); Tmplist antrian = tmplistmapper.selectrandomone (); System.out.println ("Antrian is Null?"+Antrian); if (antrian == null) {// Daftar antrian kosong/*** Jika daftar antrian kosong, dapatkan biz dari meja yang menyimpan biz akun resmi. * Di sini saya mengatur bidang waktu waktu pengumpulan di tabel akun resmi. Setelah mengurutkannya dalam urutan positif, * Dapatkan catatan akun resmi dengan cap waktu terkecil dan dapatkan biz */ weixin weixin = weixinmapper.selectone (); String biz = weixin.getBiz (); url = "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=" + biz + "#wechat_redirect"; // Pisahkan akun historis akun resmi saat ini (formulir halaman kedua) // Perbarui bidang waktu pengumpulan waktu dalam tabel akun resmi yang disebutkan sekarang untuk saat ini (Formulir Halaman Kedua). weixin.setCollect (System.currentTimemillis ()); int result = weixInmapper.updatebyprimarykey (weixin); System.out.println ("Gethis Weixin Updateresult:"+hasil); } else {// Dapatkan bidang content_url dari url baris saat ini = queue.getContentUrl (); // perbarui bidang muat ke 1 tmplistmapper.updateByContentUrl (url); } // Ubah URL $ berikutnya yang akan dialihkan ke dalam skrip JS dan menyuntikkannya ke halaman WeChat oleh AnyProxy. // echo "<script> setTimeout (function () {window.location.href = '". $ url. "';}, 2000); </script>"; int randomtime = random baru (). NextInt (3) + 3; String jscode = "<script> setTimeout (function () {window.location.href = '"+url+"';},"+acak*1000+"); </script>"; mengembalikan jscode; }Di atas adalah program yang memproses data yang dicegat oleh server proxy. Ada masalah yang perlu diperhatikan di sini. Program ini akan melakukan akses round-robin ke setiap akun resmi yang termasuk dalam database, dan bahkan artikel yang disimpan akan diakses lagi. Tujuannya adalah untuk terus memperbarui jumlah tampilan dan suka artikel ini. Jika Anda perlu merangkak sejumlah besar akun publik, disarankan untuk memodifikasi kode untuk menambahkan antrian tugas dan menambahkan batasan bersyarat. Jika tidak, akun resmi akan merangkak data duplikat dalam beberapa putaran dan siklus akan sangat mempengaruhi efisiensi.
Pada titik ini, semua tautan artikel dari akun resmi WeChat dirangkak, dan tautan ini valid secara permanen dan dapat dibuka di browser. Selanjutnya, tulis program crawler untuk merangkak konten artikel dan informasi lainnya dari database.
Saya crawler yang ditulis dalam webmagic, ringan dan mudah digunakan.
Kelas Publik Spidermodel mengimplementasikan Pageprocessor {Private Static Postmapper Postmapper; Daftar Statis Pribadi <Post> Posting; // Konfigurasi yang relevan dari situs web perayapan, termasuk pengkodean, interval perayapan, retry kali, dll. Situs situs pribadi = situs.me (). SetRetryTimes (3) .setsleeptime (100); situs publik getSite () {// TODO Metode yang dihasilkan otomatis rintik-rintik this.site; } Proses public void (halaman halaman) {// TODO Metode yang dihasilkan otomatis Stub post post = posts.remove (0); String content = page.getHtml (). Xpath ("// div [@id = 'js_content']"). Get (); // Artikel Harry ditentukan di sini. Jika ada catatan hapus langsung atau atur bit representasi untuk menunjukkan bahwa artikel tersebut harmonis jika (content == null) {System.out.println ("Artikelnya harmonis!"); //postmapper.deletebyprimarykey (post.getId ()); kembali; } String contentSnap = content.replaceall ("data-src", "src"). Replaceall ("preview.html", "player.html"); // snapshot string contenttxt = htmltoword.striphtml (content); // contentstxtable contentsable moRacont =stripHtml (content);//contentsable contentsable moRacont contentsable =stripHtml (content);//Text ContentSable moRACONTONEBLETEBLE MORACONT = page.getHtml (). xpath ("// div [@id = 'meta_content']"); String pubtime = null; String wxname = null; String penulis = null; if (metacontent! = null) {pubtime = metaContent.xpath ("// em [@id = 'post-date']"). get (); if (pubtime! = null) {pubtime = htmltoword.striphtml (pubtime); // artikel penerbitan waktu} wxname = metaContent.xpath ("// a [@id = 'post-user']"). get (); if (wxname! = null) {wxname = htmltoword.striphtml (wxname); // nama akun publik} penulis = MetAcontent.xpath ("// em [ @class = 'Rich_Media_Meta Rich_Media_Meta_Text' dan @id! = 'Post-DEREA_META.) if (author! = null) {author = htmltoword.striphtml (penulis); // Artikel penulis}} // System.out.println ("Publikasikan waktu:"+pubtime); // System.out.println ("Nama Akun Publik:"+WXName); // System.out.println ("Account:"+WXName); // System.out.println ("Account:"+WXName); // System.out.println ("Account:"+WXNAME); // System.out.println ("Account:"+WXNAME); // System.out.println (""+WXName); // System.out.out.println (""+WXNAME); String title = post.getTitle().replaceAll("", "");//Article title String digest = post.getDigest();//Article summary int likeNum = post.getLikenum();//Article likes int readNum = post.getReadnum();//Article readings String contentUrl = post.getContentUrl();//Article link WechatInfoBean wechatBean = wechatinfobean baru (); wechatbean.settitle (judul); wechatbean.setContent (contentTxt); // konten teks biasa wechatbean.setsourcecode (contentSnap); // snapshot wechatbean.setlikeCount (likeenum); wechatbean.setViewCount (readnum); wechatbean.setabstracttext (digest); // abstrak wechatbean.setUrl (contentUrl); wechatbean.setpublishtime (pubtime); wechatbean.setsitename (wxname); // nama situs nama akun publik wechatbean.setauthor (penulis); wechatbean.setMediatype ("akun resmi weChat"); // sumber jenis media wechatstorage.savewechatinfo (wechatbean); // Tag artikel ini telah dirangkak pos.setisspider (1); postmapper.updatebyprimarykey (post); } public static void startSpider (daftar <ost> inposts, postmapper mypostmapper, string ... urls) {long starttime, endtime; startTime = system.currentTimeMillis (); postmapper = mypostmapper; Posts = inposts; HttpClientDownloader httpclientdownloader = httpclientDownloader baru (); Spidermodel spidermodel = spidermodel baru (); Spider myspider = spider.create (spidermodel) .addurl (URLS); myspider.setDownloader (httpclientdownloader); coba {spidermonitor.instance (). Daftar (myspider); myspider.thread (1) .run (); } catch (jMException e) {e.printstacktrace (); } endtime = System.currentTimeMillis (); System.out.println ("Crawl Time" + ((Endtime-StartTime) / 1000) + "detik--"); }}Saya tidak akan memposting kode penyimpanan logika yang tidak relevan lainnya. Di sini saya meletakkan data yang ditangkap oleh server proxy di MySQL dan menyimpan data yang dirangkak oleh program crawler saya di MongoDB.
Di bawah ini adalah informasi tentang nomor rekening resmi yang Anda rangkak: