`
qepwqnp
  • 浏览: 115179 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

python文章采集例子(爬取http://infoq.com)

阅读更多
写了个采集http://infoq.com资源的小程序,原理:从infoq.com上读取提供的RESS资源。然后根据资源中相关链接下载相应文章
RESS地址:http://www.infoq.com/cn/rss/rss.action?token=v4OEYqEXG7ltwOPp5IpH34Ky6WdtpXqz
  <?xml version="1.0" encoding="UTF-8" ?> 
- <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/">
- <channel rdf:about="http://www.infoq.com/cn/">
  <title>未注册用户的 InfoQ 个性化 RSS Feed - 请注册后升级!</title> 
  <link>http://www.infoq.com/cn/</link> 
  <description>本 RSS Feed 是一个个性化定制的 Feed,对于您在 InfoQ.com 上的帐号(无论注册与否)都是唯一的。您可以从 InfoQ 网站左侧栏中的“您的社区”选项框内选择感兴趣的社区,此外您还可以通过关闭子话题和标签的方式过滤掉您不感兴趣的内容。您所做的选择将影响到本 RSS Feed 显示的新闻——新闻内容将和您在网站首页中央的新闻栏看见的内容保持一致。如果您的 RSS Feed 没有反映出这样的相关性,那么可能是因为您使用的 Feed 链接没有与您的 InfoQ 帐号相关联。为了确保您所使用的 Feed 的正确性,请先在 InfoQ 上注册,然后从网站左侧菜单中的“个性化 RSS”链接获取新的 RSS Feed URL。祝您使用愉快!</description> 
- <items>
- <rdf:Seq>
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/petapoco" /> 
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/Scale-ASPNet-Apps" /> 
  <rdf:li resource="http://www.infoq.com/cn/articles/ck-explore-test-mistakes" /> 
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/NativeDriver" /> 
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/Premailer" /> 
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/learning-from-history" /> 
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/github-mac" /> 
  <rdf:li resource="http://www.infoq.com/cn/articles/cf-java-object-serialization-rmi" /> 
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/Win8-Doubt" /> 
  <rdf:li resource="http://www.infoq.com/cn/presentations/lcm-javaee-7-reaching-cloud" /> 
  <rdf:li resource="http://www.infoq.com/cn/articles/raw-notes-redmond" /> 
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/collective-ownership-bad" /> 
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/swarchbooks2011" /> 
  <rdf:li resource="http://www.infoq.com/cn/news/2011/06/Micro-42-Beta" /> 
  <rdf:li resource="http://www.infoq.com/cn/articles/wl-silverlight-query" /> 
  </rdf:Seq>
  </items>
  </channel>
- <item rdf:about="http://www.infoq.com/cn/news/2011/06/petapoco">
  <title>PetaPoco:适用于.NET的微型ORM</title> 
  <link>http://www.infoq.com/cn/news/2011/06/petapoco</link> 
  <description>>PetaPoco是一款适用于.NET应用程序的对象关系映射器(ORM, Object Relational Mapper)。与那些功能完备的ORM(如NHibernate或Entity Framework)不同的是,PetaPoco更注重易用性和性能,而非丰富的功能。使用PetaPoco只需要引入一个C#文件,可以使用强类型的POCO,并支持
.........


得到一个RESS的标准XML文档,然后解析XML得相关文章信息,再进入解析,最后下载图片,保存文章信息到MYSQL数据库中

下面是代码:
#! /usr/bin/env python 
# -*- coding: utf-8 -*- 

import urllib
import re,sys
import string
from xml.dom.minidom import parseString
from sgmllib import SGMLParser  
import MySQLdb
reload(sys)
sys.setdefaultencoding('utf8')


class Constants():
    #站点
    HTML_SITE = "http://www.infoq.com";
    #聚体资源
    HTML_RESOURCE = HTML_SITE + "/cn/rss/rss.action?token=v4OEYqEXG7ltwOPp5IpH34Ky6WdtpXqz";  
    #数据库配置
    DB_HOST = "localhost"     
    #数据库用户名
    DB_USER = "root"
    #数据库密码
    DB_PASSWORD = "root"
    #数据库
    DB_DATABASE = "test"
    #数据库连接编码集
    CHARSET = "utf8"
    #代理服务器
    PROXY_ADRESS = ""
    #代理用户名
    PROXY_USERNAME = ""
    #代理用户密码
    PROXY_PASSWORD = ""
    #图片本地保存路径
    IMG_LOCALDSTDIR = "E:/image/"
    

    
class ListUrls(SGMLParser):  
    def reset(self):  
        self.imgs = []  
        SGMLParser.reset(self)  
    def start_img(self, attrs):  
        src = [v for k, v in attrs if k == 'src']  
        if src:  
            self.imgs.extend(src)
#数据库工具类
class DBUTIL():
    def  getConnectionDB(self):
        try:
            conn = MySQLdb.connect(host=Constants.DB_HOST, user=Constants.DB_USER, passwd=Constants.DB_PASSWORD, db=Constants.DB_DATABASE, charset=Constants.CHARSET)
            return conn
        except:
            print "EROOR: get ConnectionDB is FAIL"
        
#文章对象用于从网站中爬取然后存储在DB中
class  actrict():
    title = ''
    link = ''
    description = ''
    creator = ''
    createdate = ''
    identifier = ''
    content = ''
    
class webcrawlerhttpurl(): 
    #获取HTML内容   
    def getUrlInfo(self, weburl):
        try :
            #proxyConfig = 'http://%s:%s@%s' % (Constants.PROXY_USERNAME, Constants.PROXY_PASSWORD, Constants.PROXY_ADRESS)
            #inforMation = urllib.urlopen(weburl, proxies={'http':proxyConfig})
            inforMation = urllib.urlopen(weburl)
            #header = inforMation.info()            
            #contentType = header.getheader('Content-Type')           
            status = inforMation.getcode()           
            if status == 200:            
                html = inforMation.readlines()                        
                return html    
            else:
                return 'ERROR: get web %s% is fail and status=%s' % (weburl, status);
        except:
            print 'ERROR: get web %s% is fail' % (weburl);
        finally:
            inforMation.close()    
            
    #解析HTML
    def parseHtml(self, html, link):
        try:
            #body是一个list,需要转成string
            document = ""
            for line in html:
                if line.split():
                    document = document + line                
            #title
            title = document[re.search("title>", document).end():]   
            title = title[:re.search("title>", title).end() - 8]
              
            #content
            content = document[re.search("box-content-5", document).end():]
            content = content[:re.search("bottom-corners", content).end()]  
            content = document[re.search("<!-- AddThis Button END -->", document).end():]  
            content = content[:re.search("<script type='text/javascript'>", content).end() - 33] 
            content = content.replace("'", "\\'") 
      
        except:
            print 'ERROR:PARSEHTML IS FAIL %s' % (link)        
        return content
    #解析RESS然后访问其中每个具体资源
    def parseRessXml(self, xml_file):  
            #body是一个list,需要转成string
            document = ""
            for line in xml_file:
                document = document + line            
            doc = parseString(document)
            pkgs = doc.getElementsByTagName("item")            
            #遍历所有的资源地址
            i = 0;
            for pkg in pkgs:
                try:
                    i = i + 1
                    print '-------------------PARSE HTML (%s)-----------------' % (i)
                    title = pkg.getElementsByTagName("title")
                    title = self.getText(title[0].childNodes)
                    link = pkg.getElementsByTagName("link")
                    link = self.getText(link[0].childNodes)
                    description = pkg.getElementsByTagName("description")
                    description = self.getText(description[0].childNodes)
                    creator = pkg.getElementsByTagName("dc:creator")
                    creator = self.getText(creator[0].childNodes)
                    createdate = pkg.getElementsByTagName("dc:date")
                    createdate = self.getText(createdate[0].childNodes)
                    identifier = pkg.getElementsByTagName("dc:identifier")
                    identifier = self.getText(identifier[0].childNodes)

                    #判断文章是否已存在
                    conn = DBUTIL().getConnectionDB()
                    cur = conn.cursor()                       
                    SQL = "SELECT COUNT(1) FROM ARTICLES WHERE identifier='%s'"%(identifier)
                    cur.execute(SQL)
                    alldata = cur.fetchall()
                   
                    if alldata[0][0] != 0:
                        print "Warning: DB already exist for this article"
                        continue;
                    
                    #解析Html返回文章内容
                    content = self.parseHtml(self.getUrlInfo(link), link)
                    #存储图片文件到本地
                    lister = ListUrls()
                    lister.feed(content)
                    self.saveimg(lister.imgs)
                    
                    for img in lister.imgs:
                        content = content.replace(img,Constants.IMG_LOCALDSTDIR +"/" + img.split("/")[-1].split(";")[0])
                        
                    #封装成actrict类
                    actrict.title = title
                    actrict.link = link
                    actrict.identifier = identifier
                    actrict.description = description
                    actrict.createdate = createdate
                    actrict.creator = creator
                    actrict.content = content 
                    #进行存本地数据库
                    self.putDB(actrict)
                except :
                    print "ERROR: PARSE_XMLRESS IS FAIL%s" % (link)

    #解析XML取字符
    def getText(self, nodelist):
        rc = ""
        for node in nodelist:
            if node.nodeType == node.TEXT_NODE:
                rc = rc + node.data
        return rc
    #保存图片文件
    def saveimg(self, imgs):
        for img in imgs :
            try:
                if string.find(img, 'http') != 0:
                    img = Constants.HTML_SITE + img 
                DstDir = Constants.IMG_LOCALDSTDIR          
                imgPath = DstDir + img.split("/")[-1].split(";")[0]
                print imgPath 
                File = open(imgPath, "wb") 
                #proxyConfig = 'http://%s:%s@%s' % (Constants.PROXY_USERNAME, Constants.PROXY_PASSWORD, Constants.PROXY_ADRESS)
                #inforMation = urllib.urlopen(img, proxies={'http':proxyConfig})
                inforMation = urllib.urlopen(img)
                jpg = inforMation.read()
                File.write(jpg)
                print("INFO: SAVE IMG:" + imgPath)
            except :
                print "ERROR: SAVA IMG IS FAIL:%s" % (img)
            finally:
                inforMation.close()
                File.close()
  
    #存储DB
    def putDB(self, actrict):
        title = actrict.title
        link = actrict.link
        identifier = actrict.identifier
        description = actrict.description
        createdate = actrict.createdate
        creator = actrict.creator
        content = actrict.content
        print title
        try:    
            conn = DBUTIL().getConnectionDB()
            cur = conn.cursor()                       
            SQL = "INSERT INTO ARTICLES(title,link,identifier,description,createdate,creator,content)VALUES\
            ('%s','%s','%s','%s','%s','%s','%s')" % (title, link, identifier, description, createdate, creator, content)
            cur.execute(SQL)
            conn.commit()
            print "INFO: SAVE ACTRICT IS SUCCESSFUL"
        except :
                print "ERROR: SAVE ACTRICT IS FAIL"
        finally:     
            cur.close()      
            conn.close()
        


if __name__ == "__main__":
    webcrawler = webcrawlerhttpurl();
    xml_file = webcrawler.getUrlInfo(Constants.HTML_RESOURCE)    
    webcrawler.parseRessXml(xml_file)


'''
    CREATE TABLE `ARTICLES` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(500) DEFAULT NULL COMMENT '文章标题',
  `link` varchar(500) DEFAULT NULL COMMENT '文章完整链接',
  `description` varchar(5000) DEFAULT NULL COMMENT '描述信息',
  `creator` varchar(200) DEFAULT NULL COMMENT '作者',
  `createdate` varchar(200) DEFAULT NULL COMMENT '发布时间',
  `identifier` varchar(500) DEFAULT NULL COMMENT '关键字,用于区分文章是否已存在',
  `content` longtext COMMENT '内容',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
'''



------------------------------


提供源码下载:
  • 大小: 17.6 KB
1
0
分享到:
评论

相关推荐

    http://yourgame.javaeye.com/blog/252853

    描述中的链接则指向了InfoQ网站上的一篇博客,作者为yanxinfeng,但未给出具体的文章主题。 由于提供的信息有限,我将基于"CRM完整数据库脚本.sql"这个文件名来生成相关知识点。SQL脚本通常是用于创建、修改或操作...

    开源IaaS软件ZStack.zip

    [Infoq]私有云之殇:公有云这座大山(上)http://www.infoq.com/cn/articles/ZStack-PartI  [Infoq]为私有云结庐而做“隆中对”(下)http://www.infoq.com/cn/articles/ZStack-PartII  ...

    多变量时间序列异常样本的识别

    文章提出了一种基于局部稀疏系数(Local Sparsity Coefficient)的方法,并采用扩展的Frobenius范数来衡量两个MTS样本之间的相似性。此外,通过两阶段顺序查询来进行k-最近邻搜索(k-Nearest Neighbor, k-NN),从而...

    java开发者应该去的20个英文网站

    6. InfoQ (https://www.infoq.com/) InfoQ是一个全面的技术资讯平台,发布最新的技术趋势、实践和大会报道,包括Java领域。 7. Baeldung (https://www.baeldung.com/) Baeldung是一个深入的Java教程网站,涵盖了...

    nodejs.zip

    深入浅出Node.js(二):Node.js&NPM的安装与配置-http://www.infoq.com/cn/articles/nodejs-npm-install-config 2.NPM的命令: (1).unstall:npm unstall -g grunt-cli 3.环境变量: D:\Program Files\nodejs\; D:\...

    java版bs公交服务网源码-SYSADMIN-REFERENCES:系统管理员参考

    http://www.infoq.com/presentations/scaling-operations-facebook https://ops-school.readthedocs.org/en/latest/config_management.html http://www.damnsmalllinux.org/income-guide/intro.html ops ...

    infoq-downloader:从Infoq下载演讲以离线查看

    InfoQ下载器 从Infoq下载演讲,以离线查看。 先决条件 您将需要有上述或 。...casper ./lib/infoq-casper.js http://www.infoq.com/presentations/a-presentation-name 如果您更喜欢SlimerJS,请尝试以下方法: cas

    ARCore/ARKit学习资料-Swift开发

    ARCore / ARKit学习资料ARCore-ARKit技术ARCore / ARKit学习资料官方文档Google ARCore:https://www.infoq.cn/article/1jwL4NOhehcEJgvh-KDI Apple ARKit:https://developer.apple.com/augmented-reality /关于...

    郑华 - Hulu推荐系统构建经验谈

    本资源为文档PDF:郑华 - Hulu推荐系统构建经验谈 视频网址:http://www.infoq.com/cn/presentations/hulu-recommendation-system-construction-experiences/

    夜莺::light_bulb:分布式高性能监控系统。 下一代开放猎鹰

    国内用户可以访问gitee大规模仓库: ://gitee.com/cnperl/Nightingale,非实时同步,每天一次,不过速度很快。 夜莺简介 夜莺是一套分布式高可用的运维监控系统,...二次开发: ://xie.infoq.cn/article/30d37e98fbe5

    字体颜色: [color=red]文字[/color] 提示:您可以使用 color=#FF0000

    这个链接指向了InfoQ中国(iteye)上的一个博客文章,通常这里会包含有关IT技术、编程技巧或者某个特定话题的讨论,但由于无法直接访问这个链接,我们无法获取具体信息。 标签“源码”和“工具”暗示了可能涉及的...

    java网络资源介绍ppt

    除了上述网站,还有许多其他的学习资源,如Stack Overflow、GitHub、Oracle Developer Network (OTN)、JavaWorld、InfoQ等,它们都提供了大量的技术问答、源码示例、文章和讨论,可以帮助开发者解决问题,学习新的...

    nodejs-lessions:一个node学习记录仓库

    nodejs学习记录学习路径初级开发者要求:能基于koa/express 开发基本的web服务学习材料:【强烈推荐】博文共赏:Node.js 静态文件服务器实战 https://www.infoq.cn/article/2011/11/tyq-nodejs-static-file-server...

    C# 导出word例子for free,09年的东西,不知道还有多少意义

    http://www.cnblogs.com/WormCanFly/archive/2009/09/17/1568668.html#2045847 09年的刚刚工作时用到的技术,仅供大家参考。今天发现还有人来下载,特地改成免费的。 内容源码

    程序员成长学习要求

    2. **技术社区**:如[InfoQ](https://www.infoq.com/cn/)、[CSDN](https://www.csdn.net/)等,参与技术讨论,获取最新资讯。 3. **专业论坛**:如[IBM developerWorks](https://www.ibm.com/developerworks/)、...

    talkingdata-mobile-user-demographics.zip

    基于用户app的下载和使用情况预测用户的人口属性(性别和年龄) gender_age:训练和测试集 events, app_events: 当用户使用Taking...数据集介绍:https://www.infoq.cn/article/predict-mobile-users-Kaggle-contest

Global site tag (gtag.js) - Google Analytics