一、简单思路
下图新浪新闻中心的首页,也就是我们要爬取的第一页:新浪新闻中心的国际板块

此页下拉发现有五个小栏目:

每个小栏目下拉会继续加载页面,同时加载到最底下还会发现有翻页选项:

在Chrome中打开调试者工具(F12),进入Network选项,点击JS:

刷新页面,下拉加载新闻,观察调试者工具中的变化:

可以发现,每下拉加载一次或点击翻页就会请求一个新的网页,这个网页和前一页的区别就是在page的值上发生了变化,如图5Request URL处所示。理论上来说,根据这一规律可以将这一栏目的所有新闻全部爬取。
下面再看五个小栏目的区别:分别点开,观察调试者工具中的变化:
对于亚洲栏目:
http://api.roll.news.sina.com.cn/zt_list?channel=news&cat_1=gjxw&cat_3=gj-yz&level==1||=2&show_ext=1&show_all=1&show_num=22&tag=1&format=json&page=1&callback=newsloadercallback&_=1517556788882
对于欧洲栏目:
http://api.roll.news.sina.com.cn/zt_list?channel=news&cat_1=gjxw&cat_3=gj-oz&level==1||=2&show_ext=1&show_all=1&show_num=22&tag=1&format=json&page=3&callback=newsloadercallback&_=1517557031988
发现除page以外唯一的区别就是cat-3的值不同,结合前面提到的page变化,可以爬取五个栏目的不同页的新闻。同时也可以进入国内、社会、军事等其他具有类似结构的页面进行爬取。
思路:首先在parse中,设置两层循环,提取不同栏目下不同页面所有新闻的URL,同时返回这些URL的Request,并且通过item传递URL到parse_item回调函数。再用parse_item解析这些新闻页面,提取出标题和内容,将item传入Pipeline对爬取的数据进行存储。
二、部分代码
1、items

2、pipelines

3、settings




3、middlewares
可以保留默认的middlewares内容,如下为添加的,用于随机选择代理IP和代理浏览器(代理IP不一定可用,可以上网寻找可用的免费代理IP):
from scrapy import signals
import random
import base64
from SinaBot.settings import PROXIES
class RandomUserAgent(object):
"""Randomly rotate user agents based on a list of predefined ones"""
def __init__(self, agents):
self.agents = agents
@classmethod
def from_crawler(cls, crawler):
return cls(crawler.settings.getlist('USER_AGENTS'))
def process_request(self, request, spider):
print("**************************" + random.choice(self.agents))
request.headers.setdefault('User-Agent', random.choice(self.agents))
class ProxyMiddleware(object):
def process_request(self, request, spider):
proxy = random.choice(PROXIES)
if proxy['user_pass']is not None:
request.meta['proxy'] ="http://%s" % proxy['ip_port']
encoded_user_pass = base64.encodestring(proxy['user_pass'].encode("utf-8")).decode("utf-8")
request.headers['Proxy-Authorization'] ='Basic ' + encoded_user_pass
print("**************ProxyMiddleware have pass************" + proxy['ip_port'])
else:
print("**************ProxyMiddleware no pass************" + proxy['ip_port'])
request.meta['proxy'] ="http://%s" % proxy['ip_port']
pass
4、SinaSpider



三、爬取结果
上万条新闻,如果想爬取特定的页数,同样也可以对Spider中的min_page_num和max_page_num做限制。

问题:新老新闻的URL格式会发生变化,采用同样的正则表达式会出现老新闻不能提取的问题。
下一步关注点:如何做全站爬取,如何获取可靠的代理IP。
(1)关于全站爬取:推荐使用提取链接(LinkExtractor)的方法,不断提出对于新闻页的请求,将不是新闻页的链接筛掉。不断循环往复,构造多个爬虫,从同一网站的多个站点开始爬取,最终爬取全站内容。几乎可以爬取各类主要新闻网页的全站。
(2)关于代理IP:Crawlera或者Goagent, 也可以花钱购买服务,不过一般会有抓取次数限制,而且高质量的服务价格更昂贵。
网友评论