上一章咱们使用Python实现了一个简单的HTTP请求,瞧着简单,爬虫就是模拟人打开一个个URL浏览一个个网页来爬取数据的,一个成功的HTTP请求,就是一个爬虫的基础。
接下来,咱们以一个实际的例子:爬取百度新闻,来介绍使用BeautifulSoup对HTML进行解析处理。
爬取腾讯新闻
1、寻找数据特征
腾讯新闻的网址URL为:http://news.qq.com/
我们打开网页看看:
我们需要爬取这个页面每一条新闻的标题,鼠标右击一条新闻的标题,选择“审查元素”,出现下图的窗口:
图片中红框的位置就是那一条新闻标题在HTML中的结构、位置和表现形式:
<a target="_blank" class="linkto" href="http://news.qq.com/a/20170104/001280.htm">北京2016年39天重污染 PM2.5仍超国标一倍</a>
它上一级元素为:<em class=”f14 l24″>,再上一级元素为:<div class=”text”>
我们再看另一条新闻的标题,发现它的结构和之前我们分析的新闻标题的结构是一样的:
<div class="text"> <em class="f14 l24"> <a target="_blank" class="linkto" href="http://news.qq.com/a/20170104/000968.htm">台拟将蔡英文贺岁春联“自自冉冉”一词列入辞典 </a> </em> </div>
通过这些信息,我们就可以确定新闻标题在HTML文档中的位置。
接下来,我们开始使用Python对腾讯新闻标题进行爬取
** 2、编写爬取代码
首先上完整的代码
# coding:utf-8 # 引入相关模块 import requests from bs4 import BeautifulSoup url = "http://news.qq.com/" # 请求腾讯新闻的URL,获取其text文本 wbdata = requests.get(url).text # 对获取到的文本进行解析 soup = BeautifulSoup(wbdata,\'lxml\') # 从解析文件中通过select选择器定位指定的元素,返回一个列表 news_titles = soup.select("div.text > em.f14 > a.linkto") # 对返回的列表进行遍历 for n in news_titles: # 提取出标题和链接信息 title = n.get_text() link = n.get("href") data = { \'标题\':title, \'链接\':link } print(data)
运行程序,获取到的部分结果为如下所示:
C:\Python34\python.exe H:/python/scrap/scrap_tech_book/scrap_tennetNews.py {\'标题\': \'2017年首个断崖降级官员曝光 他犯了什么事?\', \'链接\': \'http://news.qq.com/a/20170104/002209.htm\'} {\'标题\': \'湄公河武装执法纪实:队员吃饭都要死死盯着前方\', \'链接\': \'http://news.qq.com/a/20170104/007148.htm\'} {\'标题\': \'河南台前县出台彩礼“指导标准”:总数不得高于6万\', \'链接\': \'http://news.qq.com/a/20170104/001693.htm\'} {\'标题\': \'摆射击摊获刑老太谈上诉原因:怕预订的咸菜浪费了\', \'链接\': \'http://news.qq.com/a/20170104/013261.htm\'} {\'标题\': \'美国联军承认在叙伊有“误伤”:打死*二百*民\', \'链接\': \'http://news.qq.com/a/20170104/005283.htm\'} {\'标题\': \'辽宁黑山企业人员退休先缴四百元:未经省级审批\', \'链接\': \'http://news.qq.com/a/20170104/006323.htm\'} {\'标题\': \'罗布泊遇难者李中华的骨灰回家:身份仍有3大谜团\', \'链接\': \'http://news.qq.com/a/20170104/003139.htm\'} {\'标题\': \'嫌楼上邻居吵,这家人买“震楼神器”反击\', \'链接\': \'http://news.qq.com/a/20170104/001582.htm\'} {\'标题\': \'12岁女孩疑似被弃 因妈妈买不起她的火车票?\', \'链接\': \'http://news.qq.com/a/20170104/004622.htm\'} {\'标题\': \'向美国商务部说“NO” 这家中国民企打赢美国官司\', \'链接\': \'http://news.qq.com/a/20170104/000322.htm\'} {\'标题\': \'台拟将蔡英文贺岁春联“自自冉冉”一词列入辞典\', \'链接\': \'http://news.qq.com/a/20170104/000968.htm\'} {\'标题\': \'新华社:姚明资历经验尚浅 任篮协主席尚有障碍\', \'链接\': \'http://news.qq.com/a/20170104/000330.htm\'} {\'标题\': \'新京报:法院拍卖BB弹玩具枪,自己人也糊涂?\', \'链接\': \'http://news.qq.com/a/20170104/001344.htm\'}
这正是我们所需要的。
虽然代码很简单,但还是做一点点讲解,方便刚刚接触的同学。
3、代码解析
# coding:utf-8
首先,我们定义了文件的编码形式为UTF-8,以避免一些编码错误导致中文乱码。
import requests from bs4 import BeautifulSoup
然后,我们引入了相关的模块,requests用于HTTP请求,BeautifulSoup用于解析HTML响应。
url = "http://news.qq.com/"
设置一个变量url,值为腾讯新闻的URL
wbdata = requests.get(url).text
使用requests.get()对URL发起GET方式的HTTP请求,并使用text()方法获取响应的文本内容,最后将其赋值给变量wbdata。
soup = BeautifulSoup(wbdata,\'lxml\')
使用BeautifulSoup对响应文本wbdata进行解析处理,这里使用的是lxml库,如何没有安装,可以使用Python自带的html.parser,效果也是一样的。
news_titles = soup.select("div.text > em.f14 > a.linkto")
在解析后的文本中,使用select选择器,在文本中选择指定的元素,通常我们还会使用find()和findall()方法来进行元素选择。
这一步返回的为一个列表,列表内的元素为匹配的元素的HTML源码。
for n in news_titles: # 提取出标题和链接信息 title = n.get_text() link = n.get("href") data = {\'标题\':title,\'链接\':link} print(data)
对结果列表进行遍历,再从遍历的元素中提取出数据,get(“href”)表示获取属性名为“href”的属性值,get_text()表示获取标签的文本信息。
这样,一个简单的腾讯新闻爬虫就完成了,如果对requests模块和BeautifulSoup模块有更加深的学习欲望,可以查看它们的官方文档:
requests官方文档(中文): http://docs.python-requests.org/zh_CN/latest/
BeautifulSoup文档(中文):
https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html
原文件的例子现在已提取不出来,现增加一个例子:
#coding:utf-8
# 引入相关模块
import requests
from bs4 import BeautifulSoup
url = "http://blog.sina.com.cn/s/articlelist_1097984013_0_1.html"
# 请求URL,获取其text文本
r= requests.get(url)
r.encoding=\'utf-8\'
wbdata =r.text
# 对获取到的文本进行解析
soup = BeautifulSoup(wbdata,\'lxml\')
# 从解析文件中通过select选择器定位指定的元素,返回一个列表
news_titles = soup.select("div.articleCell >p.atc_main > span.atc_title>a")
print(news_titles)
# 对返回的列表进行遍历
for n in news_titles:
# 提取出标题和链接信息
title = n.get_text()
link = n.get("href")
data = {
\'标题\':title,
\'链接\':link
}
print(data)