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

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

 import requests
from bs4 import BeautifulSoup # response请求页面的响应,all_url_lis用于存放所有页面的utl,all_title_list用于存放所有页面的title,
# i用来显示当前爬取到第几个页面 def parse(response, all_url_list, all_title_list, i):
html = response.content # 先获取二进制形式的内容,下面再进行转换,否则会出现中文乱码
html = str(html, encoding='utf-8')
soup = BeautifulSoup(html, 'lxml') # 利用Beautifulsoup解析库
f = open('title_and_url.txt', 'a', encoding='utf-8') # 打开文件,存储所有页面的title和url # 获取正文
# content = soup.find(name='div', attrs={'class': 'main_article'})
# p_list = content.find_all(name='p')
# for p in p_list:
# print(p.string) flag = 0 # 用来标志当前页面的url有多少已经存储过了,后面可以作为结束循环的条件 # 获取下方社会新闻
Sociology_list = soup.find_all(name='div', attrs={'class': 'r'})
sociology_a_list = Sociology_list[0].find_all(name='a')
for a in sociology_a_list:
sociology_title = a.string
sociology_url = a.attrs.get('href')
# print(sociology_title, sociology_url)
# 判断列表中是否已经存在这个页面的url或title,实现去重
if sociology_url not in all_url_list and sociology_title not in all_title_list:
all_url_list.append(sociology_url)
all_title_list.append(sociology_title)
f.write(sociology_title + ' ' + sociology_url + '\n')
else:
flag += 1 # 获取排行榜
Ranking_list = soup.find_all(name='ul', attrs={'class': 'tt', 'id': 'tt'})
rank_a_list = Ranking_list[0].find_all(name='a')
for a in rank_a_list:
rank_title = a.string
rank_url = a.attrs.get('href')
# print(rank_title, rank_url)
if rank_url not in all_url_list and rank_title not in all_title_list:
all_url_list.append(rank_url)
all_title_list.append(rank_title)
f.write(rank_title + ' ' + rank_url + '\n')
else:
flag += 1 # 热点推荐
hot_list = soup.find_all(name='ul', attrs={'class': 'ducheng_list'})
hot_a_list = hot_list[0].find_all(name='a')
for a in hot_a_list:
hot_title = a.string
hot_url = a.attrs.get('href')
# print(hot_title, hot_url)
if hot_url not in all_url_list and hot_title not in all_title_list:
all_url_list.append(hot_url)
all_title_list.append(hot_title)
f.write(hot_title + ' ' + hot_url + '\n')
else:
flag += 1 # 热点视频
video_list = soup.find_all(name='ul', attrs={'class': 'tuku_list'})
video_a_list = video_list[0].find_all(name='a')
for a in video_a_list:
video_title = a.string
video_url = a.attrs.get('href')
# print(video_title, video_url)
if video_url not in all_url_list and video_title not in all_title_list:
all_url_list.append(video_url)
all_title_list.append(video_title)
f.write(video_title + ' ' + video_url + '\n')
else:
flag += 1 # 要闻
yaowen_list = soup.find_all(name='ul', attrs={'class': 'yaowen_list'})
yaowen_a_list = yaowen_list[0].find_all(name='a')
for a in yaowen_a_list:
yaowen_title = a.string
yaowen_url = a.attrs.get('href')
# print(yaowen_title, yaowen_url)
if yaowen_url not in all_url_list and yaowen_title not in all_title_list:
all_url_list.append(yaowen_url)
all_title_list.append(yaowen_title)
f.write(yaowen_title + ' ' + yaowen_url + '\n')
else:
flag += 1 f.close()
print('第{0}个页面存储完成'.format(i), flag)
# 一个页面中有44条新闻。如果改页面中的所有url都已经被存储过了,则可以大致认为已经获取到了所有的url
# 实际少了十三条
if flag == 44:
return flag
else:
return if __name__ == '__main__':
all_url_list = []
all_title_list = []
url = 'http://www.cymodel.net/deaafc/13143.html'
all_url_list.append(url)
i = 0
while (True):
# 如果想要把all_url_list里面的每个页面的url全部爬取一遍,则可以用这个条件作为循环结束
# 把下面的内嵌if和函数里面的if else注释掉即可
if( i < len(all_url_list) ):
response = requests.get(url=all_url_list[i])
flag = parse(response, all_url_list, all_title_list, i+1)
i += 1
if flag == 44:
print('已爬取大部分的url!!!!!')
break
else:
print('已爬取到所有的url!!!!!')
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条。

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

python爬虫之深度爬取实例的更多相关文章

  1. Python爬虫教程-17-ajax爬取实例(豆瓣电影)

    Python爬虫教程-17-ajax爬取实例(豆瓣电影) ajax: 简单的说,就是一段js代码,通过这段代码,可以让页面发送异步的请求,或者向服务器发送一个东西,即和服务器进行交互 对于ajax: ...

  2. 【转载】教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神

    原文:教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神 本博文将带领你从入门到精通爬虫框架Scrapy,最终具备爬取任何网页的数据的能力.本文以校花网为例进行爬取,校花网:http:/ ...

  3. python爬虫-基础入门-爬取整个网站《3》

    python爬虫-基础入门-爬取整个网站<3> 描述: 前两章粗略的讲述了python2.python3爬取整个网站,这章节简单的记录一下python2.python3的区别 python ...

  4. python爬虫-基础入门-爬取整个网站《2》

    python爬虫-基础入门-爬取整个网站<2> 描述: 开场白已在<python爬虫-基础入门-爬取整个网站<1>>中描述过了,这里不在描述,只附上 python3 ...

  5. python爬虫-基础入门-爬取整个网站《1》

    python爬虫-基础入门-爬取整个网站<1> 描述: 使用环境:python2.7.15 ,开发工具:pycharm,现爬取一个网站页面(http://www.baidu.com)所有数 ...

  6. Python 爬虫入门之爬取妹子图

    Python 爬虫入门之爬取妹子图 来源:李英杰  链接: https://segmentfault.com/a/1190000015798452 听说你写代码没动力?本文就给你动力,爬取妹子图.如果 ...

  7. Python爬虫实战之爬取百度贴吧帖子

    大家好,上次我们实验了爬取了糗事百科的段子,那么这次我们来尝试一下爬取百度贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作. 本篇目标 对百度贴吧的任意帖子进行抓取 指定是否只抓取楼主发帖 ...

  8. python 爬虫 requests+BeautifulSoup 爬取巨潮资讯公司概况代码实例

    第一次写一个算是比较完整的爬虫,自我感觉极差啊,代码low,效率差,也没有保存到本地文件或者数据库,强行使用了一波多线程导致数据顺序发生了变化... 贴在这里,引以为戒吧. # -*- coding: ...

  9. 教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神

    本博文将带领你从入门到精通爬虫框架Scrapy,最终具备爬取任何网页的数据的能力.本文以校花网为例进行爬取,校花网:http://www.xiaohuar.com/,让你体验爬取校花的成就感. Scr ...

随机推荐

  1. LInux:服务的管理-systemctl

    使用systemctl管理服务 服务的启动与停止 服务的启动与停止 命令格式:systemctl 选项 服务名 选项说明: start:启动;stop:停止:restart:重启:status:服务状 ...

  2. Java使用JDBC连接SQL Server数据库

    Java使用JDBC连接SQL Server数据库 1.下载驱动 1.下载Microsoft SQL Server JDBC 驱动程序 https://docs.microsoft.com/zh-cn ...

  3. Java Web 学习(9) —— EL 与 JSTL

    EL 与 JSTL EL与JSTL的作用是为了减少JSP页面中的代码. EL EL(Expression Language):表达式语言 常用于取值 语法 EL 表达式以${开头,以}结束. 多个表达 ...

  4. Java中的集合-您必须知道的13件事

    Java Collections Framework是Java编程语言的核心部分之一.集合几乎用于任何编程语言中.大多数编程语言都支持各种类型的集合,例如List, Set, Queue, Stack ...

  5. Linux进程和计划任务实践

    1.显示统计占用系统内存最多的进程,并排序. 方法一 [root@test ~]#ps aux --sort=%mem USER PID %CPU %MEM VSZ RSS TTY STAT STAR ...

  6. MySQL数据库查询所有表名

    查找指定库中所有表名 select table_name from information_schema.tables where table_schema='db_name'; 注:替换db_nam ...

  7. pandas.read_sql_query()读取数据库数据用chunksize的坑

    最近一项工作需要读取数据库中1500万条数据,考虑到数据量太大,不方便直接一次性读取,不然会内存爆炸.想到用pandas.read_sql_query()里有一个chunksize可以分批返回chun ...

  8. 在wcharczuk/go-chart图表上打印文字

    先看效果: 源码 package main import (    "bytes"    "fmt"    "io/ioutil"    & ...

  9. Linux vi文档操作

    使用操作 a 在光标后插入    A 插入行末   i 在光标前插入   I 插入行首 o 向下切换一行 O 向上开一行 dd 删除一整行 x 删除光标后一个字符   X 删除光标前一个字符 shif ...

  10. Redis for OPS 07:Redis 补充说明

    写在前面的话 redis 的各种架构搭建暂时就到这里,本文主要用于补充说明 Redis 的一些概念以及配置文件的相关信息. 常用词汇 缓存穿透: 类似热点数据存储 Redis 一样,对于非热点数据存储 ...