鱼C论坛

 找回密码
 立即注册
查看: 2325|回复: 4

[已解决]Web爬虫

[复制链接]
发表于 2017-1-18 10:33:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在书上看到一段代码,没看懂什么意思:
  1. parser=HTMLParser(formatter.AbstractFormatter(formatter.DumbWriter(cStringIO.StringIO())))
  2.         parser.feed(data)
  3.         parser.close()
  4.         return parser.anchorlist
复制代码

百度一下,说StringIO是为了从内存中读取数据,但是没太懂读的是什么数据?
                还有说DumbWriter是把事件流转换为文本文档。事件流的意思是什么呢?这里把什么改成了文本文档?

AbstractFormatter具体用法是什么也没太理解。。

各位大神答疑解惑,小女子感激不尽啊~~

附上整体程序:
  1. #!/user/bin/env python
  2. import cStringIO
  3. import formatter
  4. from htmllib import HTMLParser
  5. import httplib
  6. import sys
  7. import os
  8. import urllib
  9. import urlparse
  10. class Retriever(object):
  11.     __slots__=('url','file')
  12.     def __init__(self,url):
  13.         self.url,self.file=self.get_file(url)
  14.     def get_file(self,url,default='index.html'):
  15.         'Create usable local filename from URL'
  16.         parsed=urlparse.urlparse(url)
  17.         host=parsed.netloc.split('@')[-1].split(':')[0]
  18.         filepath='%s%s' % (host,parsed.path)

  19.         if not os.path.splitext(parsed.path)[1]:
  20.             filepath=os.path.join(filepath,default)
  21.         linkdir=os.path.dirname(filepath)
  22.         if not os.path.isdir(linkdir):
  23.             if os.path.exists(linkdir):
  24.                 os.unlink(linkdir)
  25.             os.makedirs(linkdir)
  26.         return url,filepath
  27.     def download(self):
  28.         'Downliad URL to specific named file'
  29.         try:
  30.             retval=urllib.urlretrieve(self.url,self.file)
  31.         except (IOError,httplib.InvalidURL) as e:
  32.             retval=(('*** ERROR :bad URL:"%s":%s' % (self.url,e)),)
  33.         return retval
  34.     def parse_links(self):
  35.         'Parse out the links found in download HTML file'
  36.         f=open(self.file,'r')
  37.         data=f.read()
  38.         f.close()
  39.         parser=HTMLParser(formatter.AbstractFormatter(formatter.DumbWriter(cStringIO.StringIO())))
  40.         parser.feed(data)
  41.         parser.close()
  42.         return parser.anchorlist

  43. class Crawler(object):
  44.     count=0
  45.     def __init__(self,url):
  46.         self.q=[url]
  47.         self.seen=set()
  48.         parsed=urlparse.urlparse(url)
  49.         host = parsed.netloc.split('@')[-1].split(':')[0]
  50.         self.dom = '.'.join(host.split('.')[-2:])
  51.     def get_page(self,url,media=False):
  52.         'Download page & parse links,add to queue if nec'
  53.         r=Retriever(url)
  54.         fname=r.download()[0]
  55.         if fname[0]=='*':
  56.             print fname,'...skipping parse'
  57.             return
  58.         Crawler.count+=1
  59.         print '\n(',Crawler.count,')'
  60.         print 'URL:',url
  61.         print 'FILE:',fname
  62.         self.seen.add(url)
  63.         ftype=os.path.splitext(fname)[1]
  64.         if ftype not in ('.htm','.html'):
  65.             return
  66.         for link in r.parse_links():
  67.             if link.startswith('mailto:'):
  68.                 print '...discarded,mailto link'
  69.                 continue
  70.             if not media:
  71.                 ftype=os.path.splitext(link)[1]
  72.                 if ftype in ('.mp3','.mp4','.m4v','.wav'):
  73.                     print '...discarded ,media file'
  74.                     continue
  75.             if not link.startswith('http://'):
  76.                 link=urlparse.urljoin(url,link)
  77.             print '*',link,
  78.             if link not in self.seen:
  79.                 if self.dom not in link:
  80.                     print '...discarded,not in domain'
  81.                 else:
  82.                     if link not in link:
  83.                         self.q.append(link)
  84.                         print '...new,added to Q'
  85.                     else:
  86.                         print '...discarded,already in Q'
  87.             else:
  88.                 print '...discarded,already processed'
  89.     def go(self,media=False):
  90.         'Process next page in queue (if any)'
  91.         while self.q:
  92.             url=self.q.pop()
  93.             self.get_page(url,media)

  94. def main():
  95.     if len(sys.argv)>1:
  96.         url=sys.argv[1]
  97.     else:
  98.         try:
  99.             url=raw_input('Enter starting URl:')
  100.         except (KeyboardInterrupt,EOFError):
  101.             url=''
  102.     if not url:
  103.         return
  104.     if not url.startswith('http://') and not url.startswith('ftp://'):
  105.         url='http://%s/' % url
  106.     robot=Crawler(url)
  107.     robot.go()

  108. if __name__=='__main__':
  109.     main()
复制代码
最佳答案
2017-1-18 11:58:00
这个应该还是用python2写的,用的库也是python自带的urllib的标准库
如果你用python3+requests库写就不需要这么麻烦了
response.content 直接就是字节流
response.text 就是解码好的字符串
非常方便,不再需要用到StringIO 转换byte和str了
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2017-1-18 11:58:00 | 显示全部楼层    本楼为最佳答案   
这个应该还是用python2写的,用的库也是python自带的urllib的标准库
如果你用python3+requests库写就不需要这么麻烦了
response.content 直接就是字节流
response.text 就是解码好的字符串
非常方便,不再需要用到StringIO 转换byte和str了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-1-18 13:12:34 | 显示全部楼层
jerryxjr1220 发表于 2017-1-18 11:58
这个应该还是用python2写的,用的库也是python自带的urllib的标准库
如果你用python3+requests库写就不需 ...

这个字节流的含义能否理解为当前网页的内容?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-1-18 13:13:47 | 显示全部楼层
追加一个问题 。

在这个程序里,可以识别当前页的其他链接。这个具体怎么实现的?没怎么理解。。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-1-18 14:55:55 | 显示全部楼层
定~~~~
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-2-25 02:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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