python网络爬虫举例

实现一个类,抓取一个网站所有页面
实现思路:一边添加url,一边抓取,一直进行下去就可以了,直到列表遍历完成,说明没有新的url可供抓取,即抓取完成。
实际上是图的广度优先遍历。

import urllib.request
import re
from bs4 import BeautifulSoup

class get_all_page_of_site():
    '''
    参数url是要抓取的网页
    '''
    def __init__(self,url):
        self.__url_list=[]
        self.__url_list.append(url)
        self.__save_page_number=0

    '''
    函数功能:根据url获取页面内容,存储位置是loc_dir
    返回值:包含页面内容的BeautifulSoup对象
    '''
    def __get_page(self,url,loc_dir):
        try:
            #这里使用urllib.urlretrieve(url,file)来也不能简化代码,虽然用它可能不需要关注网页的编码方式,
            #保存方便,但是但是它没有返回文件对象,只知道filename,所以还需要打开文件让BeautifulSoup读入
            req = urllib.request.Request(url)
            f=urllib.request.urlopen(req)
            data=f.read()
            #使用BeautifulSoup解析html文档时,程序员不用告诉它文档的编码格式
            soup=BeautifulSoup(data,"html.parser")
            self.__save_page_number+=1
            #soup.original_encoding是网页的编码方式,sina新闻大部分是UTF-8,少部分是GBK
            file1=open(loc_dir+str(self.__save_page_number)+".html",'w',encoding=soup.original_encoding)
            file1.write(str(data.decode(soup.original_encoding)))
            file1.close()
            #这样不行,因为HTTPResponse只能read()一次,read()之后缓存就清空了。
            #return BeautifulSoup(f.read(),"html.parser")
            return soup
        #下面的异常可以根据需要自行处理
        #仍然解析不了的就不解析了
        except UnicodeDecodeError:
            return None
        #如果根据URL,打不开页面,就不再尝试
        except urllib.error.URLError:
            return None
        except TimeoutError:
            return None
        #如果url语法错误,就不尝试获取页面了,遇到过ValueError: unknown url type
        except ValueError:
            return None
        #这是偷懒的做法
        except:
            return None 
    '''
    函数功能:找出BeautifulSoup对象里的页面中,匹配 re_str的URL,放入self.__url_list中。
    '''   
    def __add_page_url(self,soup,re_str):
        #get_page()可能返回None
        if soup is None:
            return 
        for link in soup.find_all('a'):
            if re.search(re_str,str(link.get('href'))):
                if not (str(link.get('href')) in self.__url_list):
                    self.__url_list.append(str(link.get('href')))
    
    '''
    函数功能:获取所有网页
    参数说明:
    re_str:是一个正则表达式,用来匹配要爬取的url
    loc_dir:指明网页的本地存储位置
    max_page:最多抓取多少个网页,-1表示没有限制
    '''    
    def get_all(self,re_str,loc_dir,max_page=100):
        #一边向列表尾部添加元素,一边从头开始遍历,不需要维护当前遍历位置
        #列表为空了,页面就抓完了。
        #列表为空说明最后一个url的页面都抓取了,但是没有新的url产生
        for url in self.__url_list:
            soup=self.__get_page(url,loc_dir)
            print("URL: ",url)
            self.__add_page_url(soup,re_str)
            print("URL list length:",len(self.__url_list))
            print("URL index is:",self.__url_list.index(url))
            print("Saved page number:",self.__save_page_number)
            if not (max_page==-1 or self.__save_page_number<max_page):
                break

'''
使用举例
'''
if __name__=='__main__':
    #进行url过滤的正则表达式
    #这里抓取url中包含“news.sina.com.cn”并且以“html”结尾的网页
    re_str=r".*news\.sina\.com\.cn.*html$"
    #抓取到的内容的本地存储位置
    loc_dir="sina6/"
    #请在这里填写你需要抓取的网站
    url='http://news.sina.com.cn/'
    site=get_all_page_of_site(url)
    site.get_all(re_str,loc_dir)

运行打印:

URL:  http://news.sina.com.cn/
URL list length: 240
URL index is: 0
Saved page number: 1
URL:  http://slide.news.sina.com.cn/w/slide_1_86523_304209.html
URL list length: 241
URL index is: 1
Saved page number: 2
URL:  http://slide.news.sina.com.cn/z/slide_1_64237_303947.html
URL list length: 245
URL index is: 2
Saved page number: 3

保存的文件:

猜你喜欢

转载自blog.csdn.net/jxzdsw/article/details/81221337