Когда встал вопрос о том как искать новостные сайты, пришла мысль о использовании сервиса new.google.com. От туда можно выдёргивать ссылки на новостные сайты, к тому же они постоянно добавляются и отсортированы по регионам, темам и т.д. Осталось пройтись по всем разделам news.google.com, выдернуть ссылки новостных сайтов, а затем найти все RSS каждого из них.
Сначала код. Он состоит из следующих файлов: main.cpp LinksReader.cpp LinksReader.h LinksReader.pro Sources.txt и файл который создастся автоматически и в котором сохранится результат RssLinks.txt. Вся логика содержится в файлах LinksReader.h и LinksReader.cpp, остальные файлы вспомогательные, для использования класса и компилирования проекта. Компилировал проект в с помощью компилятора g++, среда Qt creator, версия библиотек 5.1
LinksReader.h
#ifndef LINKSREADER_H #define LINKSREADER_H #include <QStringList> #include <QFile> #include <QNetworkReply> #include <QEventLoop> #include <QDebug> class LinksReader: public QObject { Q_OBJECT private: void loadSources(); void loadRssLinks(); void readPage(QString url); void takeLinks(); void takeRssLinks(); void saveRssLinks(); QNetworkAccessManager mNAManager; QString mPage; QString mPageUrl; QStringList mSources; QStringList mLinks; QStringList mRssLinks; private slots: void onReplyFinished(QNetworkReply *pReply); public: LinksReader(QObject *pParent = 0); void run(); }; #endif
LinksReader.cpp
#include "LinksReader.h" void LinksReader::loadSources() { QString fileName = "Sources.txt"; QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "File " << fileName << " not found"; return; } QTextStream in(&file); while(!in.atEnd()) mSources.push_back(in.readLine()); file.close(); qDebug() << mSources.size() << " sources loaded"; return; } void LinksReader::loadRssLinks() { QString fileName = "RssLinks.txt"; QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QTextStream in(&file); while(!in.atEnd()) mRssLinks.push_back(in.readLine()); file.close(); qDebug() << mRssLinks.size() << " rss links loaded"; return; } void LinksReader::readPage(QString url) { mPage = ""; mPageUrl = url; mNAManager.get(QNetworkRequest(QUrl(url))); QEventLoop loop; QObject::connect(&mNAManager, SIGNAL(finished(QNetworkReply *)), &loop, SLOT(quit())); loop.exec(); } void LinksReader::takeLinks() { QStringList fullLinks; QString links = ""; QString beginTN = "<link>"; QString endTN = "</link>"; QString tagContent = ""; int beginTP = 0; int endTP = 0; while(1) { beginTP = mPage.indexOf(beginTN); endTP = mPage.indexOf(endTN); if (beginTP == -1 || endTP == -1) break; tagContent = mPage.mid(beginTP + beginTN.length(), endTP - beginTP - endTN.length() + 1); links += tagContent; mPage.remove(0, endTP + endTN.length()); } fullLinks = links.split("http://"); fullLinks.removeFirst(); for(int i = 0; i < fullLinks.size(); i++) { fullLinks[i].remove(fullLinks[i].indexOf("/"), fullLinks[i].length()); mLinks.push_back(fullLinks[i]); } } void LinksReader::takeRssLinks() { QString beginTN = "<link"; QString endTN = ">"; QString tagContent = ""; QString beginRssString = "href=\""; QString endRssString = " "; int beginTP = 0; int endTP = 0; while(1) { beginTP = mPage.indexOf(beginTN); endTP = mPage.indexOf(endTN, beginTP); if (beginTP == -1 || endTP == -1) break; beginTP += beginTN.length(); tagContent = mPage.mid(beginTP, endTP - beginTP); if (tagContent.indexOf("type=\"application/rss+xml\"") != -1) { int beginRssPos = tagContent.indexOf(beginRssString); int endRssPos = tagContent.indexOf(endRssString, beginRssPos); beginRssPos += beginRssString.size(); QString rssString = tagContent.mid(beginRssPos, endRssPos - beginRssPos).remove("\""); if (rssString.size() > 0 && rssString[rssString.size() - 1] == '/') rssString.remove(rssString.size() - 1, 1); if (rssString.indexOf("http://") == -1) rssString.push_front(mPageUrl); qDebug() << rssString; mRssLinks.push_back(rssString); } mPage.remove(0, endTP + endTN.length()); } } void LinksReader::saveRssLinks() { QFile file("RssLinks.txt"); file.open(QFile::ReadWrite); QTextStream in(&file); for(int i = 0; i < mRssLinks.size(); i++) in << mRssLinks[i] << "\n"; file.close(); } void LinksReader::onReplyFinished(QNetworkReply *reply) { mPage += reply->readAll(); } LinksReader::LinksReader(QObject *pParent): QObject(pParent) { QObject::connect(&mNAManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(onReplyFinished(QNetworkReply *))); } void LinksReader::run() { loadSources (); loadRssLinks(); qDebug() << "Please wait..."; for(int i = 0; i < mSources.size(); i++) { readPage(mSources[i]); takeLinks(); } mLinks.removeDuplicates(); for(int i = 0; i < mLinks.size(); i++) { readPage("http://" + mLinks[i]); takeRssLinks(); } mRssLinks.removeDuplicates(); saveRssLinks(); qDebug() << "Finish"; }
main.cpp
#include <QCoreApplication> #include "LinksReader.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); LinksReader linksReader; linksReader.run(); return a.exec(); }
LinksReader.pro
QT += core QT += network QT -= gui TARGET = LinksReader CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp \ LinksReader.cpp HEADERS += \ LinksReader.h
Sources.txt
http://news.google.com/news?ned=au&output=rss http://news.google.com/news?ned=in&output=rss http://news.google.com/news?ned=en_il&output=rss http://news.google.com/news?ned=en_my&output=rss http://news.google.com/news?ned=nz&output=rss http://news.google.com/news?ned=en_pk&output=rss http://news.google.com/news?ned=en_ph&output=rss http://news.google.com/news?ned=en_sg&output=rss http://news.google.com/news?ned=ar_me&output=rss http://news.google.com/news?ned=ar_ae&output=rss http://news.google.com/news?ned=ar_lb&output=rss http://news.google.com/news?ned=ar_sa&output=rss http://news.google.com/news?ned=cn&output=rss http://news.google.com/news?ned=hk&output=rss http://news.google.com/news?ned=hi_in&output=rss http://news.google.com/news?ned=ta_in&output=rss http://news.google.com/news?ned=ml_in&output=rss http://news.google.com/news?ned=te_in&output=rss http://news.google.com/news?ned=iw_il&output=rss http://news.google.com/news?ned=jp&output=rss http://news.google.com/news?ned=kr&output=rss http://news.google.com/news?ned=tw&output=rss http://news.google.com/news?ned=vi_vn&output=rss http://news.google.com/news?ned=nl_be&output=rss http://news.google.com/news?ned=fr_be&output=rss http://news.google.com/news?ned=en_bw&output=rss http://www.google.com/news?ned=cs_cz&output=rss http://news.google.com/news?ned=de&output=rss http://news.google.com/news?ned=es&output=rss http://news.google.com/news?ned=en_et&output=rss http://news.google.com/news?ned=fr&output=rss http://news.google.com/news?ned=en_gh&output=rss http://news.google.com/news?ned=en_ie&output=rss http://news.google.com/news?ned=it&output=rss http://news.google.com/news?ned=en_ke&output=rss http://news.google.com/news?ned=hu_hu&output=rss http://news.google.com/news?ned=fr_ma&output=rss http://news.google.com/news?ned=en_na&output=rss http://news.google.com/news?ned=nl_nl&output=rss http://news.google.com/news?ned=en_ng&output=rss http://news.google.com/news?ned=no_no&output=rss http://news.google.com/news?ned=de_at&output=rss http://news.google.com/news?ned=pl_pl&output=rss http://news.google.com/news?ned=pt-PT_pt&output=rss http://news.google.com/news?ned=de_ch&output=rss http://news.google.com/news?ned=fr_sn&output=rss http://news.google.com/news?ned=en_za&output=rss http://news.google.com/news?ned=fr_ch&output=rss http://news.google.com/news?ned=sv_se&output=rss http://news.google.com/news?ned=en_tz&output=rss http://news.google.com/news?ned=tr_tr&output=rss http://news.google.com/news?ned=en_ug&output=rss http://news.google.com/news?ned=uk&output=rss http://news.google.com/news?ned=en_zw&output=rss http://news.google.com/news?ned=ar_eg&output=rss http://news.google.com/news?ned=el_gr&output=rss http://news.google.com/news?ned=ru_ru&output=rss http://news.google.com/news?ned=sr_rs&output=rss http://news.google.com/news?ned=ru_ua&output=rss http://news.google.com/news?ned=uk_ua&output=rss http://news.google.com/news?ned=es_ar&output=rss http://news.google.com/news?ned=pt-BR_br&output=rss http://news.google.com/news?ned=ca&output=rss http://news.google.com/news?ned=fr_ca&output=rss http://news.google.com/news?ned=es_cl&output=rss http://news.google.com/news?ned=es_co&output=rss http://news.google.com/news?ned=es_cu&output=rss http://news.google.com/news?ned=es_us&output=rss http://news.google.com/news?ned=es_mx&output=rss http://news.google.com/news?ned=es_pe&output=rss http://news.google.com/news?ned=us&output=rss http://news.google.com/news?ned=es_ve&output=rss
После запуска программы, создания объекта класса LinksReader и вызова его метода run происходит следующее:
1. Загружаются источники.
2. Загружаются все найденные за прошлые разы RSS ссылки (чтобы не искать каждый раз по новой, а пополнять уже имеющуюся базу RSS).
3. Проходим по всем источником, читаем разметку и выдёргиваем все ссылки которые в разметке помечены тегом <link></link>
.
4. Удаляем все повторяющиеся ссылки.
5. Проходим по всем найденным новостным сайтам, читаем разметку каждого из них и выдёргиваем значения всех RSS тегов этого сайта.
6. Удаляем все повторяющиеся RSS ссылки.
7. И наконец сохраняем результат в файл.
По стандарту все RSS ссылки сайта, должны быть помечены тегом <link rel="alternate" type="application/rss+xml" title="Моя RSS-лента" href="index.xml" />
, что намного облегчает поиск RSS.
Как видно программа достаточно проста, но хорошо делает своё дело. За один запуск находит 600-700 RSS лент. Повторные запуски увеличивают это количество, так-как в news.google.com постоянно добавляются ссылки на новые новостные сайты.
Не хотел подробно рассматривать каждую строку кода, думаю что он и так хорошо читается, даже не знающим Qt. Но, если есть непонятные места — спрашивайте и я с радостью помогу разобраться. Если есть замечания, критика — пишите.
ссылка на оригинал статьи http://habrahabr.ru/post/203210/
Добавить комментарий