分享

利用Python编写网络爬虫下载文章

 toppoo 2014-05-11

利用Python编写网络爬虫下载文章

今天来讲如何利用Python爬虫下载文章,拿韩寒的博客为例来一步一步进行详细探讨。。。

韩寒的博客地址是:http://na.com.cn/s/articlelist_1191258123_0_1.html

可以看出左边是文章列表,而且不止一页,我们先从最简单的开始,先对一篇文章进行下载,再研究对一页所有的文

章进行下载,最后再研究对所有的文章下载。

第一步:对一篇文章下载

     我们打开韩寒的博客,然后查看源码,可以看出每一篇文章的列表源码为:

    <span class="atc_title"><a title="东望洋" target="_blank"  

    href=" http://na.com.cn/s/blog_4701280b0102eck1.html ">东望洋</a></span>

    我们主要是想提取出中间绿色部分的URL,然后找到这篇文章的正文进行分析,然后提取进行下载。首先,假

    设已经得到这个字符串,然后研究如何提取这个URL,观察发现,对于所有的这类字符串,都有一个共同点,那

    就是都含有子 串'<a title=','href='和'.html' ,那么我们可以用最笨的方式---查找子串 进行定界。

    在Python中有一个方法叫做find(),是用来查找子串的,返回子串出现的位置,那么,可以用如下代码来提

    取URL,并读取文件和下载文件。

#encoding:utf-8
import urllib2

def getURL(str):
  start = str.find(r'href=')
  start += 6
  end   = str.find(r'.html')
  end   += 5
  url = str[start : end]
  return url

def getContext(url):
  text =urllib2.urlopen(url).read()
  return text

def StoreContext(url):
  content  = getContext(url)
  filename = url[-20:]
  open(filename, 'w').write(content)

if __name__ == '__main__':
  str = '<span class="atc_title"><a title="东望洋" target="_blank" href="http://na.com.cn/s/blog_4701280b0102eck1.html">东望洋</a></span>'   
  url = getURL(str)
  StoreContext(url)

第二,三步:下载所有的文章

   

     在这一步中,我们要提取第一页所有的文章的URL和标题,不再采用上面第一步的find()函数,毕竟这个函数

    缺乏灵活性,那么采用正则表达式最好。

    首先采集数据,观察发现,所有文章的URL都符合

    <a title="..." target="_blank" href=" http://na.com.cn....html ">

    这一规则,所以我们可以设置正则表达式

    r'<a title=".+" target="_blank" href="( '" rel="nofollow,noindex">http://na\.com.\cn.+.\html )">'

       这样就容易了,下面是爬取韩寒所有文章,并在本地保存为.html文件。

代码:

#coding:utf-8
import re
import urllib2

def getPageURLs(url):
  text = urllib2.urlopen(url).read()
  pattern = r'<a title=".+" target="_blank" href="(http://na\.com.\cn.+.\html)">'
  regex = re.compile(pattern)
  urlList = re.findall(regex,text)
  return urlList

def getStore(cnt,url):
  text = urllib2.urlopen(url)
  context = text.read();
  text.close()
  filename = 'HanhanArticle/'+str(cnt) + '.html'
  f = open(filename,'w')
  f.write(context)
  f.close()
  
def getAllURLs():
  urls = []
  cnt = 0
  for i in xrange(1,8):
    urls.append('http://na.com.cn/s/articlelist_1191258123_0_'+str(i)+'.html')
  for url in urls:
    tmp = getPageURLs(url)
    for i in tmp:
      cnt += 1
      getStore(cnt,i)
  
if __name__ == '__main__':
  getAllURLs()

由于我把文章的标题用一个数字来命名,似乎不是很完美,还有两个问题没有解决,怎么提取文章的标题?,这是涉

及到中文提取,怎么把文章的内容提取出来保存为txt格式的文件?

如果能解决上面的两个问题,那么才算是真正地用网络爬虫技术实现了对韩寒博客的下载。

(1)提取文章的标题

   为了方便操作,我们用BeautifulSoup来分析网页,对html文本我们提取title之间的内容为

    <title> 东望洋_韩寒_新浪博客 </title>

   对这个强制转化为字符串,然后进行切片操作,大致取string[7 : -28],得到了文章的标题。

from bs4 import BeautifulSoup
import re

for i in xrange(1,317):
  filename = 'HanhanArticle/' + str(i) + '.html'
  html = open(filename,'r')
  soup = BeautifulSoup(html)
  html.close()
  title = soup.find('title')
  string = str(title)
  article = string[7 : -28].decode('utf-8')
  if article[0] != '.':
    print article

但是有些标题直接的内容还需要处理,比如 <<ONE IS ALL>>, 本来应该解释为《ONE IS ALL》

还有比如 中央电视台很*很**, 这里的**在文件中不能作为名称字符。

#coding:utf-8
import re
import urllib2
from bs4 import BeautifulSoup

def getPageURLs(url):
  text = urllib2.urlopen(url).read()
  pattern = r'<a title=".+" target="_blank" href="(http://na\.com\.cn.+\.html)">'
  regex = re.compile(pattern)
  urlList = re.findall(regex,text)
  return urlList

def getStore(title,url):
  text = urllib2.urlopen(url)
  context = text.read();
  text.close()
  filename = 'HanhanArticle/'+ title + '.html'
  f = open(filename,'w')
  f.write(context)
  f.close()

def getTitle(url):
  html = urllib2.urlopen(url).read()
  soup = BeautifulSoup(html)
  title = soup.find('title')
  string = str(title)
  return string[7 : -28]

def Judge(title):
  lens = len(title)
  for i in xrange(0,lens):
    if title[i] == '*':
      return False
  return True
  
def getAllURLs():
  urls = []
  for i in xrange(1,8):
    urls.append('http://na.com.cn/s/articlelist_1191258123_0_'+str(i)+'.html')
  for url in urls:
    tmp = getPageURLs(url)
    for i in tmp:
      title = getTitle(i).decode('utf-8')
      print title
      if title[0] != '.' and Judge(title):
        getStore(title,i)
  
if __name__ == '__main__':
  getAllURLs()

提取正文部分后续再处理。。。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多