系列文章:
爬虫初探:一次爬虫的编写尝试
一 概述
在上一篇拉取到各新闻的概况信息之后(发布日期,标题,链接,来源),发现有些地方还可以继续挖掘。例如在搜索结果页,新闻的发布时间只有日期,没有精确的时分信息,而原始来源是可能细化到时分,甚至到秒的。另外,如果想要获取更详细的信息,也需要获取文章的内容。这就需要做进一步的 spider 动作。
二 执行中遇到的关键问题
2.1 链接重定向
从页面上获取的链接,并非直接是原文的真实地址,而是一个需要重定向的链接,以检索词:福建 疫情 防控 的搜索结果中,下面这条新闻的内容为例:
对应的文章链接是:
http://www.baidu.com/link?url=NKkcMXU9fX7L3fd4mA4k-Yx_trx5NOX0Kwfu6rP9n-aqDDRSQaCjpRi02OGm7E3W6hg1mawKzUmaS5atOUL3S9UnwtdPzocIJGVu3rDy4Xu
复制代码
而在浏览器中输入上述 url 或 在搜索结果中直接打开,真实的链接是:
https://m.thepaper.cn/baijiahao_13725847
复制代码
所以,不能简单地通过诸如 python 的 urllib2.urlopen()来直接获取 url 内容,而是必须先获取跳转真实链接。
2.2 内容模板
进入新闻详情页面,就需要针对不同的页面进行内容解析了,一般来说,每个来源的页面需要配置一个模板,来做对应的解析工作,这里没有什么取巧的办法,只能先分析页面内容,然后再去进行配置。可以考虑的是不自己硬编码,而是利用一些抓取工具来实现,可以简化工作。
三 问题解决
3.1 重定向问题解决
3.1.1 python
基于 python 语言,是参考了这篇文章:https://blog.csdn.net/weixin_35552251/article/details/113477811,通过 urllib 的方法获取重定向后的 url 地址:
from urllib import request
url = "https://www.baidu.com/link?url=IscBx0u8h9q4Uq3ihTs_PqnoNWe7slVWAd2dowQKrnqJedvthb3zrh9JqcMJu3ZqFrbW_DKVuTnTypDbMkZx_hwCQIGFPRVWGyxRXA-65jK&wd=&eqid=f7aeecba00092ed7000000065ec62596"
print(request.urlopen(url).geturl())
复制代码
3.1.2 Java
相比之下,java 会更容易一些,当然是指从安装依赖包的角度来看。由于我的开发环境的 python 版本和环境问题,导致安装 request 的 python 包遇到些波折,所以采用了 Java 的中转方案,获取真实的 url 地址。仅供参考。原理上,就是通过 HeaderField 中的"Location"内容获取。
/**
* 获取重定向地址
* @param path
* @return
* @throws Exception
*/
public static String getRedirectUrl(String path) throws Exception {
HttpURLConnection conn = (HttpURLConnection) new URL(path)
.openConnection();
conn.setInstanceFollowRedirects(false);
conn.setConnectTimeout(5000);
return conn.getHeaderField("Location");
}
复制代码
3.2 页面模板分析
3.2.1 示例 1
通过 3.1,我们可以得到示例新闻的真实 url 为: https://m.thepaper.cn/baijiahao_13725847
接下来就是分析页面结构,根据需要获取确切的发布时间、摘要等信息了。
以时间为例,所属的页面元素源码为:
<span data-href="https://m.thepaper.cn">
政务:福建交警 2021-07-24 09:58</span>
复制代码
继续使用正则表达式,取<span data-href="https://m.thepaper.cn"> 和 </span>之间的字符串,然后再进行 分割,取数组中的元素[1]即可。
3.2.2 示例 2
百家号的内容,格式化程度更高一些,对应的元素解析代码如下:
itemList = content.split('newTimeFactor_before_abs c-color-gray2')
i = 0
for link in itemList:
if i == 0:
i=i+1
continue;
if link.find('general_image_pic')>=0:
# print link
news_date = re.findall(r" m\">(.+) </span>", link)
source = re.findall(r".jpeg\"><\/div>(.+)<\/span><\/a><div ", link)
if len(source) <= 0:
source = re.findall(r"<span class=\"nor-src-icon-v vicon-2\"><\/span>(.+)<\/span><\/a><div", link)
title = re.findall(r"\"title\":\"(.+)\",\"url", link)
url = re.findall(r"url\":\"(.+)\"}\'>", link)
if len(source) > 0:
cars = [title[0], news_date[0], source[0], url[0]]
newsList.append(cars)
print title[0]
writer.writerow(cars)
i=i+1
复制代码
四 总结
至此,一个简单的抓取示例初步完成。大家如果看过其他的介绍爬虫的相关文章,一般都还会有入库操作、种子的去重、抓取时为了避免被封设置虚拟 ip 和 user agent 的设置。这些也都是编写 spider 代码的重要环节。后续有需要我们再做讨论。
评论