写了一个之前没完成的项目,代码优化不够,速度有点慢,应该也有错误的地方,望大佬看了之后能给点建议。。。。。。。。。
这是开始的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条。
*****************************不积跬步,无以至千里。 *****************************