▉一文带你入门爬虫——爬取百度风云榜实时新闻

当我在想,第一期推文出什么的时候,各种想法在我脑子里闪过,后来我发现很多微信群会有早报推送而且每当我用百度的时候右侧会有一个实时新闻热度的排行。于是这个爬虫就诞生了,并且根据这个实战可以很好的入门python爬虫。

先看下这个项目的成果

百度风云榜的实时热点是根据每时每刻新闻的热度排名在不断变化的,而在百度风云榜的实时热点页面上提供的超链接是百度搜索该词条的结果,需要得到报道这个新闻的页面需要从第一个界面跳转两次。

先附上源代码再从中进行讲解。

importrequests
frombs4importBeautifulSoup
importtime
importcsv
importdatetime
#得到当前的时间
nowTime=datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S')
#创建列表储存新闻标题
new_title = []
#创建列表储存新闻跳转的百度界面
urls = []
#创建csv文件 操作方式为写入, 文件名为时间
csv_file = open(nowTime+".csv","w")
# 创建writer对象,指定文件与分隔符
csv_writer = csv.writer(csv_file,delimiter=',')
#s = requests.Session()
#百度风云榜的url
url = "http://top.baidu.com/buzz?b=1&fr=tph_right"
#设置请求头
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}
#通过一个get请求获取网页信息
req = requests.get(url,headers=headers)
#处理乱码问题
req.encoding=('gb2312')
#用Beautiful soup 解析网页
soup = BeautifulSoup(req.text,"html.parser")
#用select选择出所有新闻的超链接,储存在url列表中
all_url = soup.select('a.list-title')
print(nowTime)
foriinall_url:
url = i["href"]
urls.append(url)
#获取新闻题目
new_title.append(i.string)
# print(str(a)+i.string)
foriinrange(len(urls)):
# print(urls[i])
req = requests.get(urls[i],headers= headers)
soup = BeautifulSoup(req.text,"html.parser")
reall_all_url = soup.select('div > a')
#[24]---[37]为有效url
# for j in range(len(reall_all_url)):
# try:
# print(j)
# print(reall_all_url[j]["href"])
# except:
# continue
#for i in range(len(reall_all_url)):
forminrange(24,200):
try:
if'http://www.baidu.com/link?url='inreall_all_url[m]["href"] :
print(m)
print(i + 1, new_title[i], reall_all_url[m+6]["href"])
csv_writer.writerow([i + 1, new_title[i], reall_all_url[m+6]["href"]])
break
except:
continue
time.sleep(1)
csv_file.close()

在此主要介绍一个爬虫的简单思路,实现过程,此项目中出现的问题。

首先我们需要确定我们需要的得到的内容是,实时新闻热点,包括时间,标题,内容(在这里,内容映射为该新闻在某新闻网站的链接)

然后大致思路是通过解析百度风云热点的网页,获取对于的百度搜索该词条的链接,再从这些链接中获取报道其具体内容的链接

明确第一个目标,获取热点新闻标题和百度搜索该词条的超链接。我们用Beautiful库中的select方法来提取出我们需要的内容。在此之前我们用requests库中get方法得到

#通过一个get请求获取网页信息
req = requests.get(url,headers=headers)
#处理乱码问题
req.encoding=('gb2312')
#用Beautiful soup 解析网页
soup = BeautifulSoup(req.text,"html.parser")
#用select选择出所有新闻的超链接,储存在url列表中
all_url = soup.select('a.list-title')

上述代码做了一件事,选择了网页中('a.list-title')便签下的内容,在上述代码中需要注意的是,求情头(headers)一定要设置,虽然有时候不设置也可以,但是IP也可能某个时候就被封了。

重点讲下req.encoding=('gb2312'),python3默认编码是"utf-8’的编码,但是我们需要爬取信息的网页的编码的"gb2312’编码方式的(通过查看网页源代码中"charset=’),所以需要转换成"gb2312’格式的,否则会出现乱码!

再看看代码中('a.list-title')的由来,鼠标指向需要的数据右击之后点击检查

在弹出的界面再按下图操作,直接copy粘贴在select方法中,作为参数传递即可,但是只需要保留一个运算符即可。

此时我们如果打印all_url,得到的是一个列表,此列表储存了该界面下热点排行榜上所有新闻的标题和对应的百度搜索该词条的链接,并且可以看出链接是储存在href属性中,我们通过for语句将我们所需要的信息储存起来。

所以我们需要创建两个列表new_title,和urls来储存新闻名和百度的搜索链接foriinall_url: 中是把 i 作为 all_url 这个变量的别名,通过对 i 的操作实现对 all_url的操作,i.string 返回 i 中的字符串内容。注释部分的代码是为了方便观察调试。

foriinall_url:
url = i["href"]
#获取词条百度搜索的结果
urls.append(url)
# a += 1
#获取新闻题目
new_title.append(i.string)
# print(str(a)+i.string)

接下来我们需要对所得到的链接的网页经行解析,从中提取出我们需要的,报道该新闻的链接。我们通过同样的方法,select出我们需要的网页链接。copy下来。在第一次写的时候需要通过for语句打印,以此来获取我们需要的链接在列表中的所对应的下标,我们通过下列代码实现目标。

foriinrange(len(urls)):
# print(urls[i])
req = requests.get(urls[i],headers= headers)
soup = BeautifulSoup(req.text,"html.parser")
reall_all_url = soup.select('div > a')
forjinrange(len(reall_all_url)):
try:
print(j)
#打印reall_all_url[j]元素中的"href"属性 print(reall_all_url[j]["href"])
except:
continue

-----------------一个有脾气的分割线------------------

通过观察(大量的)打印结果可以发现,从下标等于24开始到38中"href"属性中包含了大量具体报道的链接,但是还有少部分分布在下标为50到140+的"href"属性中。

在失败了好几次之后,发现并且还有少量个例在满足前两个条件但是跳转的却是时事热点的界面,即第一个我们爬取的url。但是出现这个连接之后证明我们离我们需要的链接所对应的下标不到个位数的距离了所以我选择在爬取到满足上述条件的网页后最终选择相隔五个元素之后的链接。

具体实现代码如下:

/****注意:以上代码嵌套在上一个遍历百度搜索网页的循环中***/

运行之后就可以打印出实时热点的新闻排行和相应报道的连接了。但是在我提供的源代码中有几个小细节说明一下:

1:

s = requests.Session()这句我在代码中注释掉了,它的用法是代替requests函数即后面的requests.get 请求 可以替换成s.get。他的作用使我们所有的请求都是同一个cookies,也就是说所有的操作是同一用户进行的。他的意义在某些需要登陆的情况比较重要

2:

#创建csv文件 操作方式为写入, 文件名为时间
csv_file = open(nowTime+".csv","w")
# 创建writer对象,指定文件与分隔符
csv_writer = csv.writer(csv_file,delimiter=',')
csv_writer.writerow([i + 1, new_title[i], reall_all_url[m+6]["href"]])
#关闭文件
csv_file.close()

上面几句已经基本说明python对csv文件的写入

3:

importdatetime

#得到当前的时间nowTime=datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S')

这两句就可以获取当前的时间储存到nowTime变量中,当前格式为:年-月-日 时-分-秒