• Python爬虫之利用BeautifulSoup爬取豆瓣小说(一)——设置代理IP


    自己写了一个爬虫爬取豆瓣小说,后来为了应对请求不到数据,增加了请求的头部信息headers,为了应对豆瓣服务器的反爬虫机制:防止请求频率过快而造成“403 forbidden”,乃至封禁本机ip的情况,而设置了代理ip,详细请见代码和注释。

    爬取豆瓣小说的链接:https://www.douban.com/tag/%E5%B0%8F%E8%AF%B4/book?start=0

    获取免费代理ip的网站:http://www.xicidaili.com/

      1 #-*-coding:utf-8-*-
      2 import urllib2
      3 from bs4 import BeautifulSoup
      4 import time
      5 import random
      6 
      7 class dbxs:
      8 
      9     def __init__(self):
     10         self.pageIndex = 0
     11         self.enable = True
     12         
     13         
     14     #获取html页面的内容
     15     def getPage(self, pageIndex):
     16         try:
     17             #设置代理ip
     18             enable_proxy = True
     19             #Openers使用处理器Handlers,所有的“繁重”工作由Handlers处理,每个handlers知道如何通过特定协议打开URLs,或者如何处理URL打开时的各个方面
     20             #在你使用代理上网或其他的情况就需要自己创建一个opener,可以实例化一个OpenerDirector,然后调用.add_handler(some_handler_instance)
     21             #也可使用build_opener,这是一个更加方便的函数,用来创建opener对象,它只需要一次函数调用
     22             proxy_handler = urllib2.ProxyHandler({'Http': '113.118.170.230:808'})
     23             null_proxy_handler = urllib2.ProxyHandler({})
     24             if enable_proxy:
     25             #当你获取一个URL你要使用一个opener,默认情况下opener是urlopen,但urllib2.urlopen()不支持验证、cookie或者其他Http高级功能
     26             #要支持这些功能,必须使用build_opener()创建自定义opener对象,build_opener([handler1 [handler2,...]]),参数handler是Handlers的实例,常用的有HTTPBasicAuthHandler、HTTPCookieProcessor、ProxyHandler
     27                 opener = urllib2.build_opener(proxy_handler)
     28             else:
     29                 opener = urllib2.build_opener(null_proxy_handler)
     30             urllib2.install_opener(opener)   #install_opener用来创建(全局)默认opener,这个表示调用urlopen将使用你安装的opener
     31             #获得页面响应的内容
     32             url = 'https://www.douban.com/tag/%E5%B0%8F%E8%AF%B4/book' + "?start=" + str(pageIndex)
     33             #设置请求头部信息,模拟浏览器的行为
     34             my_headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:55.0)'}
     35             request =   urllib2.Request(url, headers = my_headers)
     36             response = urllib2.urlopen(request)
     37             return response.read()
     38 
     39             #另外一种随机设置请求头部信息的方法
     40             #my_headers =['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:55.0)', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)', 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)']
     41             #header = random.choice(my_headers)    #random.choice()可以从任何序列,比如list列表中,选取一个随机的元素返回,可以用于字符串、列表、元组
     42             #request = urllib2.Request(url, headers = {'User-Agent': header})
     43         except urllib2.URLError, e:
     44             if hasattr(e, "code"):
     45                 print e.code
     46             if hasattr(e, "reason"):
     47                 print e.reason
     48                 return None
     49 
     50     #过滤查找这一页的小说名字,信息和评分
     51     def getContent(self, pageIndex):
     52         pageCode = self.getPage(pageIndex)
     53         soup = BeautifulSoup(pageCode, 'html.parser')
     54         #在获得相应的内容中找出所有标签为<dd>的内容(里面包含了我们需要的小说信息)
     55         contents = soup.find_all('dd')
     56         #如果contents为真,能够获取到包含<dd>标签的内容,什么情况获取不到?我们发现豆瓣小说21页之后的所有页面里都不包含<dd>标签,我们应该停止打印
     57         if contents:
     58         #item为包含小说信息的每一页的内容
     59             for item in contents:
     60                 title = item.find(class_ = 'title').string
     61                 info = item.find(class_ = 'desc').string.strip()
     62                 rate = item.find(class_ = 'rating_nums')
     63                 #通过试验,我们发现某一页可能存在小说没有评分,如果我们不判断rate,那么可能就出现报错
     64                 if rate:
     65                     rates = rate.string
     66                     print u"%s
    %s
    评分:%s
    " %(title, info, rates)
     67                 #对于小说没有评分的内容,我们只打印小说名字,信息
     68                 else:
     69                     print u"%s
    %s
    " %(title, info)
     70         #如果页面不包含<dd>标签,我们应该停止
     71         else:
     72             print u"所有页面已加载完"
     73             self.enable = False
     74                     
     75         return contents
     76 
     77 
     78     #创建一个开始方法
     79     def start(self):
     80         #打印第一页,此时self.pageIndex = 0,初始化时设置了
     81         #设置页码x = 1
     82         x = 1
     83         #我们观察发现,第二页的pageIndex - 第一页的 = 第一页的小说的个数
     84         #我们执行self.getContent的同时,获取了第一页的小说的个数
     85         page_num = len(self.getContent(self.pageIndex))
     86         print u"第%s页" %x
     87 
     88         #利用self.enable控制下一页的打印
     89         while self.enable == True:
     90             #设置下一页的pageIndex
     91             self.pageIndex += page_num
     92             #页码+1
     93             x += 1
     94             #time.sleep(1)    #可以利用time模块来设置sleep时间
     95             #再次调用self.getContent的同时,获取当前页的小说的个数
     96             page_num = len(self.getContent(self.pageIndex))
     97             #在self.getContent中,如果不能获取到<dd>的内容,self.enable将会改为False,如果我们不加self.enable判断,仍会打印不存在小说信息的页码 
              if self.enable == True:
    99
      print u"第%s页" %x 100 101 102 DBXS = dbxs() 103 DBXS.start()
  • 相关阅读:
    改善用户体念:jsp+Ajax实现实时上传,删除,导入Excel进度条
    hibernate+proxool的数据库连接池配置方法
    Js事件对象
    关于java数组拷贝的性能
    resin连接池配置
    java 动态编译源代码
    Java中对字符串进行加密和解密
    内存数据库H2 Mixed Mode布署
    ActiveX控件的另类免费签名法
    对PreparedStatement、Statement的一点总结
  • 原文地址:https://www.cnblogs.com/my_captain/p/7446201.html
Copyright © 2020-2023  润新知