本篇文章要实现给定若干url,抓取某新闻网站文章的标题和正文。这个和上面一篇相比复杂了不少,需要研究被抓页面的html结构。这里需要用到的工具是谷歌浏览器。
先在谷歌浏览器中打开要抓取的url,右键单击标题,选择检查。如下图:
可以看到标题和正文在下面的标签下
标题:
正文:
解析xml就可以获取里面的内容。解析方法很多:
(1)直接对xml文本操作,找到这两个标签,提取内容。
(2)写一个算法,解析成树,然后查找需要的内容。
(3)使用别人写好的库,解析这个页面
这里选择(3),比较方便。(1)实现起来很简单,可能会存在问题,(2)实现起来会稍微的复杂一些,费时费力。
使用(3)就不得不提一下xpath了。这里盗用w3school给出的xpath的定义:XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。详细语法不细讲,去w3school学习,很容易。地址是:http://www.w3school.com.cn/xpath/index.asp
注意:代码中用到了lxml,如果报错,需要使用pip3安装lxml包
代码修改上一篇文章中的代码,详情见注释。
from urllib import request
from lxml import etree
header_dict = {
"Accept":"application/json, text/javascript, */*; q=0.01",
"Accept-Language":"zh-CN,zh;q=0.9",
"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36",
}
def get_http(load_url,header):
res=""
try:
req = request.Request(url=load_url,headers=header)#创建请求对象
coonect = request.urlopen(req)#打开该请求
byte_res = coonect.read()#读取所有数据,很暴力
try:
res=byte_res.decode(encoding='utf-8')
except:
res=byte_res.decode(encoding='gbk')
except Exception as e:
print(e)
return res
url_list=[
"http://news.sina.com.cn/c/2018-09-08/doc-ihivtsyi6434298.shtml",
"http://finance.sina.com.cn/stock/usstock/c/2018-09-08/doc-ihivtsyi7277192.shtml",
"http://sports.sina.com.cn/china/national/2018-09-08/doc-ihivtsyi6890841.shtml",
"http://k.sina.com.cn/article_5919806896_160d915b000100bi6d.html?from=auto&subch=nauto",
"http://k.sina.com.cn/article_5919806896_160d915b000100bi6d.html?from=auto&subch=nauto"
]
for i in range(len(url_list)):
f=open("./a"+str(i)+".txt","w",encoding="utf-8")
page=get_http(url_list[i], header_dict)
tree=etree.HTML(page)
dir(tree)
title=tree.xpath("//h1[@id='main-title']/text()")#取根下所有id属性是main-title的h1标签中的文本,可能有多个这样的标签,结果是数组
#很多网站页面还是比较整齐的,爬取比较省心。不巧的是,我们要爬取的这个网站,页面杂乱,可能会有几十种不同xpath路径,要有耐心。
if len(title)==0:
title=tree.xpath('//h1/text()')#有些网站页面杂乱,要多分析些页面,把规则加入这里
content=tree.xpath("//div[@id='article']//p/text()")#取根下所有id属性是article的div标签下的所有p标签中的文本,可能有多个这样的标签,结果是数组
#这里也应该多分析几个页面,找出规则
if len(title)*len(content)>0:
title=title[0]
content=" ".join(content)
f.write(title+"\n"+content+"\n")
else:
f.write("解析错误")
f.close()
下一篇文章我们实现对整个网站的爬取,继续在本篇文章代码基础上修改。下一篇今天不写了。写了这几篇,项为之僵。才第三篇,大概需要写20篇,慢慢来。