设为首页 收藏本站
查看: 672|回复: 0

[经验分享] Python网页抓取程序(续)

[复制链接]

尚未签到

发表于 2015-4-27 11:45:33 | 显示全部楼层 |阅读模式
  继续上次的话题,这次抓取的网页是天涯论坛中,“地缘看世界”
  1、获取网址:通过正则表达式来获取各贴子网址
  link='http://www.tianya.cn/publicforum/content/worldlook/1/223829.shtml'     
    html=urllib2.urlopen(link).read()     
    m=re.search(r'name=\'idArticleslist\' value=\S*>',html)     
    IDs=re.findall(r'[0-9]+',m.group(0))
  for ID in IDs:   
        url="http://www.tianya.cn/publicforum/content/worldlook/1/%s.shtml"%ID
  2、 下载网页:以前是边下载边处理,这样处理时间长,有时还有下载不了的情况,改为下载到指定目录,并在下载前检查是否存在同名
  htmldir=r'.\html\\'
  filename=htmldir+url.split('/')[-1]   
    if (not os.path.exists(filename)) or os.path.getsize(filename)==0:     
        print 'downloading'+filename+'\n'     
        html=urlRead(url)     
        if len(html)>0:     
            f=open(filename,'w')     
            f.write(html)     
            f.close()
  3、下载后对网页内容进行分析,在分析前要对网页进行处理以去除htmlparser无法处理的部分,实质是对网页进行截取,并将无法处理字符串替换
  txts=re.split(r'',html)   
    txt=txts[0]     
    txt=re.sub('\xcb\xce\xcc\xe5','\'\xcb\xce\xcc\xe5\'', txt)
  4、提取贴子的正文,还是正规的htmlparser的方法,但这种方法速度很慢,也可采用正则表达式的方法,但这样适应性不强。文本中也以
  这个贴子中有大量的图片,在的形式保存
  class DocParser(HTMLParser.HTMLParser):   
    def __init__(self,pool):     
        self.pool=pool     
        self.startread=0     
        self.pre=0     
        HTMLParser.HTMLParser.__init__(self)     
        self.doc=''     
    def handle_starttag(self, tag, attrs):     
        if tag=='span':     
            for (name,value) in attrs:     
                if name=='value' and value=='10174465':     
                    self.pre=1     
        if tag=="div" and self.pre==1:     
            for (name,value) in attrs:     
                if name=='class' and value =='post':     
                    self.startread= 1     
        if tag=='img' and self.startread==1:     
            
            for (name,value) in attrs:     
                if name=='original':     
                    
                    imgname=value.split('/')[-4]+value.split('/')[-3]\     
                            +value.split('/')[-2]+value.split('/')[-1]     
                    self.doc+='\n'%imgname     
                    if not os.path.exists(htmldir+imgname):     
                        self.pool.add_task(getImg,value,htmldir)     
                        
    def handle_endtag(self, tag):     
        if tag == 'div' and self.startread==1:     
            self.doc+='\n\n\n'     
            self.pre=0     
            self.startread = 0     
    def handle_data(self,data):     
        if self.startread:     
            self.doc+=data     
            self.doc+='\n'
  5、破解防外链接:通过设置Referer实现
  preurl='http://www.tianya.cn/'
  req = urllib2.Request(url)
  req.add_header('Referer', preurl)
  6、提高urlopen工作健壮性,设置重试次数和超时等待
  改造后的urlopen如下:
  def urlRead(url):   
    fails = 0     
    rs=''     
    preurl='http://www.tianya.cn/'     
    while True:     
        try:     
  
            if fails >= 100:     
                print 'Failed to Read '+url     
                break     
            #设置Referer,避免防盗链     
            req = urllib2.Request(url)     
            req.add_header('Referer', preurl)     
            response=urllib2.urlopen(req,timeout=30)     
            length=response.info()['Content-Length']     
            rs=response.read()     
            if len(rs)==length:     
                continue     
                     
        except Exception:     
            fails += 1     
            time.sleep(10)     
        else:     
            break     
        
    return rs
  7、简易多线程下载:以前试用过stackless感觉没有效果,后来还是使用threadpool类,
  from Queue import Queue   
from threading import Thread
  class Worker(Thread):   
    """Thread executing tasks from a given tasks queue"""     
    def __init__(self, tasks):     
        Thread.__init__(self)     
        self.tasks = tasks     
        self.daemon = True     
        self.start()     
   
    def run(self):     
        while True:     
            func, args, kargs = self.tasks.get()     
            try: func(*args, **kargs)     
            except Exception, e: print e     
            self.tasks.task_done()
  class ThreadPool:   
    """Pool of threads consuming tasks from a queue"""     
    def __init__(self, num_threads):     
        self.tasks = Queue(num_threads)     
        for _ in range(num_threads): Worker(self.tasks)
  def add_task(self,  func, *args, **kargs):   
        """Add a task to the queue"""     
        self.tasks.put(( func, args, kargs))
  def wait_completion(self):   
        """Wait for completion of all the tasks in the queue"""     
        self.tasks.join()
  使用时:
  pool = ThreadPool(200)
  for ID in IDs:   
       url="http://www.tianya.cn/publicforum/content/worldlook/1/%s.shtml"%ID     
       pool.add_task(getHtml,url,htmldir)
  pool.wait_completion()
  8、输出到pdf,我使用了reportlab要注意的是:
  引用字体:
  reportlab.rl_config.warnOnMissingFontGlyphs = 0
  pdfmetrics.registerFont(TTFont('YaHei', 'msyh.ttf'))   
pdfmetrics.registerFont(TTFont('YaHeiBD', 'msyhbd.ttf'))     
fonts.addMapping('YaHei', 0, 0, 'YaHei')     
fonts.addMapping('YaHei', 0, 1, 'YaHei')     
fonts.addMapping('YaHeiBD', 1, 0, 'YaHeiBD')     
fonts.addMapping('YaHeiBD', 1, 1, 'YaHeiBD')     
stylesheet=getSampleStyleSheet()     
normalStyle = copy.deepcopy(stylesheet['Normal'])     
normalStyle.fontName ='YaHei'
  其次是中文换行:
  normalStyle.wordWrap = 'CJK'
  中文的左缩进有bug设置左缩进后,第一行全部向右移,并不是比其他的行前面少几个字
  最后是嵌入图片:取得图片的长和宽,然后设置缩放比,
  def get_image(path):   
    width=439     
    height=685     
    img = utils.ImageReader(path)     
    iw, ih = img.getSize()     
   
    if iw>width or ih>height:     
        rw=float(iw)/float(width)     
        rh=float(ih)/float(height)     
        if rw>rh:     
            return Image(path,width,round(ih/rw))     
        else:     
            return Image(path,round(iw/rh),height)     
    else:     
        return Image(path)
  结论:python是处理网页的利器,但我在编码上浪费了许多时间,在htmlparser和re中对中文的编码支持也不好,不知道各达人有没有什么好方法。
  python号称是“胶水语言”,但我始终对如何将其与其他诸如C#,java在一起使用感到困惑。
  多线程下载还是存在很多问题,各位在借鉴时一定要注意。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-61198-1-1.html 上篇帖子: Python3.3官方教程中文翻译2:使用Python解释器 下篇帖子: python中的继承和抽象类的实现
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表