• python爬虫之深度爬取实例


    写了一个之前没完成的项目,代码优化不够,速度有点慢,应该也有错误的地方,望大佬看了之后能给点建议。。。。。。。。。

    这是开始的url,先看一下它的网页结构:http://www.cymodel.net/deaafc/13143.html,可以观察到,整个网页大致分为六部分内容,中间的正文部分,右边的四部分新闻板块,还有最下面的一部分社会新闻。而每一个新闻链接点进去后又是一个相同模样的页面,爬取的目标是获取到所有的新闻title和对应的url。下面是代码,每部分链接的提取都差不多,利用find_all返回结果列表,然后再对列表进行遍历。

      1 import requests
      2 from bs4 import BeautifulSoup
      3 
      4 # response请求页面的响应,all_url_lis用于存放所有页面的utl,all_title_list用于存放所有页面的title,
      5 # i用来显示当前爬取到第几个页面
      6 
      7 
      8 def parse(response, all_url_list, all_title_list, i):
      9     html = response.content  # 先获取二进制形式的内容,下面再进行转换,否则会出现中文乱码
     10     html = str(html, encoding='utf-8')
     11     soup = BeautifulSoup(html, 'lxml')  # 利用Beautifulsoup解析库
     12     f = open('title_and_url.txt', 'a', encoding='utf-8')    # 打开文件,存储所有页面的title和url
     13 
     14     # 获取正文
     15     # content = soup.find(name='div', attrs={'class': 'main_article'})
     16     # p_list = content.find_all(name='p')
     17     # for p in p_list:
     18     #     print(p.string)
     19 
     20     flag = 0    # 用来标志当前页面的url有多少已经存储过了,后面可以作为结束循环的条件
     21 
     22     # 获取下方社会新闻
     23     Sociology_list = soup.find_all(name='div', attrs={'class': 'r'})
     24     sociology_a_list = Sociology_list[0].find_all(name='a')
     25     for a in sociology_a_list:
     26         sociology_title = a.string
     27         sociology_url = a.attrs.get('href')
     28         # print(sociology_title, sociology_url)
     29         # 判断列表中是否已经存在这个页面的url或title,实现去重
     30         if sociology_url not in all_url_list and sociology_title not in all_title_list:
     31             all_url_list.append(sociology_url)
     32             all_title_list.append(sociology_title)
     33             f.write(sociology_title + '   ' + sociology_url + '
    ')
     34         else:
     35             flag += 1
     36 
     37     # 获取排行榜
     38     Ranking_list = soup.find_all(name='ul', attrs={'class': 'tt', 'id': 'tt'})
     39     rank_a_list = Ranking_list[0].find_all(name='a')
     40     for a in rank_a_list:
     41         rank_title = a.string
     42         rank_url = a.attrs.get('href')
     43         # print(rank_title, rank_url)
     44         if rank_url not in all_url_list and rank_title not in all_title_list:
     45             all_url_list.append(rank_url)
     46             all_title_list.append(rank_title)
     47             f.write(rank_title + '   ' + rank_url + '
    ')
     48         else:
     49             flag += 1
     50 
     51     # 热点推荐
     52     hot_list = soup.find_all(name='ul', attrs={'class': 'ducheng_list'})
     53     hot_a_list = hot_list[0].find_all(name='a')
     54     for a in hot_a_list:
     55         hot_title = a.string
     56         hot_url = a.attrs.get('href')
     57         # print(hot_title, hot_url)
     58         if hot_url not in all_url_list and hot_title not in all_title_list:
     59             all_url_list.append(hot_url)
     60             all_title_list.append(hot_title)
     61             f.write(hot_title + '   ' + hot_url + '
    ')
     62         else:
     63             flag += 1
     64 
     65     # 热点视频
     66     video_list = soup.find_all(name='ul', attrs={'class': 'tuku_list'})
     67     video_a_list = video_list[0].find_all(name='a')
     68     for a in video_a_list:
     69         video_title = a.string
     70         video_url = a.attrs.get('href')
     71         # print(video_title, video_url)
     72         if video_url not in all_url_list and video_title not in all_title_list:
     73             all_url_list.append(video_url)
     74             all_title_list.append(video_title)
     75             f.write(video_title + '   ' + video_url + '
    ')
     76         else:
     77             flag += 1
     78 
     79     # 要闻
     80     yaowen_list = soup.find_all(name='ul', attrs={'class': 'yaowen_list'})
     81     yaowen_a_list = yaowen_list[0].find_all(name='a')
     82     for a in yaowen_a_list:
     83         yaowen_title = a.string
     84         yaowen_url = a.attrs.get('href')
     85         # print(yaowen_title, yaowen_url)
     86         if yaowen_url not in all_url_list and yaowen_title not in all_title_list:
     87             all_url_list.append(yaowen_url)
     88             all_title_list.append(yaowen_title)
     89             f.write(yaowen_title + '   ' + yaowen_url + '
    ')
     90         else:
     91             flag += 1
     92 
     93     f.close()
     94     print('第{0}个页面存储完成'.format(i), flag)
     95     # 一个页面中有44条新闻。如果改页面中的所有url都已经被存储过了,则可以大致认为已经获取到了所有的url
     96     # 实际少了十三条
     97     if flag == 44:
     98         return flag
     99     else:
    100         return
    101 
    102 
    103 if __name__ == '__main__':
    104     all_url_list = []
    105     all_title_list = []
    106     url = 'http://www.cymodel.net/deaafc/13143.html'
    107     all_url_list.append(url)
    108     i = 0
    109     while (True):
    110         # 如果想要把all_url_list里面的每个页面的url全部爬取一遍,则可以用这个条件作为循环结束
    111         # 把下面的内嵌if和函数里面的if else注释掉即可
    112         if( i < len(all_url_list) ):
    113             response = requests.get(url=all_url_list[i])
    114             flag = parse(response, all_url_list, all_title_list, i+1)
    115             i += 1
    116             if flag == 44:
    117                 print('已爬取大部分的url!!!!!')
    118                 break
    119         else:
    120             print('已爬取到所有的url!!!!!')
    121             break

     再写的时候,主要遇到了两个问题,一是如何实现去重,二是爬取到什么时候结束。

    第一个问题的解决办法是,先定义两个列表,用于存放每个页面的url和title,也就是all_url_liat和all_title_list,然后再每次存放url和title之前,先判断列表里面有没有这个url,如果没有,则进行存储,并添加到列表中。本来之定义了一个url的列表,但后来发现有的网页之间url不同,title相同,里面的内容也相同,所以又加了一个all_title_list。用这种方法实现去重的好处是比较简单,容易想到,但坏处是列表里面的元素过多,比较占内容,会有两个具有四百多个元素的列表,而且每次添加数据前,都要过一遍列表,判断要添加的url是否已经再列表中,这样就会导致程序运行较慢。

    第二个问题的解决办法一是根据每个页面未被存储的url数量判断,每个页面中共有44个新闻的链接,如果改页面中的44个链接都已经被存储过了,那么就认为已经获取到了大部分的url,第二种办法是把all_url_list中的每个url都爬取一下,这样能获取到所有的新闻链接,但耗时有点长,代码还需要优化。第一种办法的获取结果为416条,第二种办法获取到的是429条。

    *****************************不积跬步,无以至千里。 *****************************

  • 相关阅读:
    完全卸载mysql数据库图文教程
    软件测试 (一) 软件测试方法大汇总(转)
    html笔记之常用标签
    前端之HTML简介<一>
    java笔记之对象的克隆
    java笔记之网络知识--—TCP
    Vue组件通信中事件总线(eventBus)的使用
    React项目之antd-4.0中Form表单的数据获取
    React项目中使用antd遇坑——icon组件的使用
    常见面试题——['1','2','3'].map(parseInt)
  • 原文地址:https://www.cnblogs.com/liangshian/p/11309035.html
Copyright © 2020-2023  润新知