Поиск RSS новостных сайтов

от автора

Покопался я ещё в своих старых и не очень проектах и нашёл одну интересную программку. Она ищет RSS ссылки новостных сайтов. Задача которая стояла — это найти как можно больше новостных RSS лент и собрать их всех в одну базу.

Когда встал вопрос о том как искать новостные сайты, пришла мысль о использовании сервиса 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *