[近期新闻] 原谅我蹭个热度,获取近期新浪新闻中关于王石的内容,Python实现

2020-01-14 10:44:55 业务范围 3735
[近期新闻] 原谅我蹭个热度,获取近期新浪新闻中关于王石的内容,Python实现
果博一站讯:

话说大老王的妻子田朴珺否认与王石婚姻危机,且怒怼网友:吃饱了撑的。

之后,大老王就成了热搜名人。

很多网友表示,怎么能这么说话呢?好歹你也是个“贵族”……

今天,我们不讨论这个。我们专题讲解使用Python如何在浩如烟海的新浪新闻中获取我们想要知道的人物的新闻,我们以获取大老王的新闻为例。本文只是探讨技术问题,如果你对于批量获取新浪新闻内容感兴趣,建议你坚持往下看,获取通过本文,你可以得到一个不错的工具。

前情概要

对于这个课题,我试了N多种方法,如果你只是爬取新闻,比如首页内展示的新闻,新浪没有进行反爬措施,或者说反爬措施相对容易破解。但是,如果你使用搜索功能的话,想要爬取搜索出来的内容,还是有一定难度的……

今天,我们手把手教你降低这一难度。

简单方法

刚开始的时候,我的思路是这样的,先进入新闻搜索页面,然后搜索“王石”,出现了下面的内容。

可以看到,总共7页内容,有点少哦,刚开始页面才4篇新闻,之后的就是每页20篇新闻。(不好意思,发现一个bug,截止发文,文章总数并不是看到的132篇,其实只有116篇内容,大家自己验证吧)

思路

分析网址信息

当我使用requests库时,获取第一页的信息正常,而第二页就没法获取了。其实页面是通过js代码控制的,每次点击页码后会出现相应的内容,如果使用修改网址传参的话从第二页开始一般都是得不到内容的。

因此,分析网页网址信息和内容应该是解决这类问题的重中之重。

那怎么办?

我们知道对于这类js加载页面的问题,有两个办法:一是利用Python中相关模块去执行js代码,这个网上很多教程,感兴趣的小伙伴可以参考学习下;再一个就是使用selenium或者PhantomJS等自动化模块模拟人打开一个网页,然后获取网页源代码(此时获取到的就是执行js后的代码),然后分析其中的内容。

思路

今天,我们着重使用第二个方法来将新浪新闻中关于王石的新闻做一整理。我们的思路是这样的,直接打开这个搜索页面,首先获取第一页内容并从中提取我们需要的信息;然后每次使用selenium单击下一页内容,获取下一页面的源代码及提取需要的信息。最终,将每一页面我们需要的信息通过一个列表返回。

准备环境

Python3.7 安装selenium、requests、bs4库

具体实现步骤

【获取单页面内容】

首先,设置UA代理

header = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' }

这里的UA代理是爬虫的基础,大家可以自己构建一个UA代理池,这里不再赘述。

然后获取单页面内容,由于搜索网址的url是经过编码处理的,所以此处应该定一个网址处理函数

def parse_key(key):

return parse.quote(key, encoding='gb2312')

然后使用该函数即可获取到某一单页内容。

def get_text(key='王石'):

req = requests.get(url.format(parse_key(key)), headers=header).text

return req

这里没有进行异常处理,貌似也不需要了,大家可以自行加上去。

【使用selenium自动化处理】

定义一个函数,使用webdriver打开网址并返回webdriver对象,便于我们后续操作

def in_url(url):

wb = webdriver.Ie()

wb.get(url)

return wb

然后,我们单击一个页码时,将每一页的新闻内容展示并获取源代码。

def click_element(wb, el_no, total_no):

if el_no == 1:

e = wb.find_element_by_xpath('//*[@id="_function_code_page"]/a[1]')

e.click()

elif 1 < el_no and el_no < total_no:

e = wb.find_element_by_xpath('//*[@id="_function_code_page"]/a[{}]'.format(

el_no + 2))

e.click()

return wb.page_source

上面两步是重点,通过分析,我们知道,每次单击“下一页”时,xpath变化范围是页码+2(因为网页中加了“上一页”和“下一页”选项),el_no为1时,实际是我们单击获得第二页的内容。理解了上面的内容就好办了。

【使用BeautifulSoup库获取有效信息】

下面是我们定义的获取信息的函数,它可以从单页内容中搜索所有"h2"标签内容(里面含有新闻标题、作者、发文日期、新闻链接等内容),我们逐一从标签中将重点内容获取出来。

def find_info_bs4(html):

r_lst = []

soup = BeautifulSoup(html, 'html.parser')

for item in soup.find_all('h2'):

tmp_dict = {}

tmp_dict['title'] = item.find('a').text

print(tmp_dict['title'])

tmp_dict['author'] = item.find('span').text.split(' ')[0]

print(tmp_dict['author'])

tmp_dict['time'] = " ".join(item.find('span').text.split(' ')[1:])

print(tmp_dict['time'])

tmp_dict['url'] = item.find('a').get('href')

print(tmp_dict['url'])

r_lst.append(tmp_dict)

return r_lst

【整合流程】

# 利用selenium进入网址

wb = in_url(url.format(parse_key('王石')))

# 最终结果

result_lst = []

print('第一页')

# 先将第一页新闻筛选添加到result_lst中

result_lst.extend(find_info_bs4(wb.page_source))

print('{}'.format(len(find_info_bs4(wb.page_source))))

# 获取总页面,多少个分页元素就有多少页

n = len(wb.find_elements_by_xpath('//*[@id="_function_code_page"]/a'))

# 循环遍历每一页面

for i in range(1, n):

print('第{}页'.format(i + 1))

# 单击后获取源代码

html = click_element(wb, i, n)

# 提取有效信息并将字典添加到result_lst中

result_lst.extend(find_info_bs4(html))

print('添加记录{}条'.format(len(find_info_bs4(html))))

# 打印最终新闻条数

print(len(result_lst))

执行结果展示

最终,获取到下面内容

好了,今天的内容就到这里了。怎么样?是不是很酷?感兴趣的小朋友可以试试看,如果将关键字修改后,可以检索别的新闻内容。其实,可以将result_lst改为set数据类型。当然,你也可以将这些函数封装成一个类使用。可做更多的扩展,由你决定。

欢迎大家关注我,后续会推出更有意思的内容。

转载请注明出处,百家号:Python高手养成

声明:果博一站登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不构成投资建议。投资者据此操作,风险自担。