web爬虫讲解—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息
该系统采用自动化爬虫技术从百度新闻网站中提取实时更新的信息源,并精准抓取其首页的指定链接规则(如新闻rul地址)。
有很多网站,在浏览器访问时会显示一些信息;然而,在HTML源文件中却无法直接获取这些信息;这些信息通常会通过滚动区域滚动到相应位置后才显示出来;因此,这种现象通常是JavaScript的Ajax动态请求所导致的。
我们以百度新闻为列:
1、分析网站
首先我们浏览器打开百度新闻,在网页中间部分找一条新闻信息

然后对源码进行核查,在源文件中并未发现该条新闻的存在情况

我们需要进行数据包解析工作。在启动相关抓取工具之前,请确保已使用抓包浏览器完成初始设置。此时,在解析过程中我们注意到一条信息是基于Ajax动态构建的JSON格式数据。具体而言,在HTML页面完成加载后才会生成该数据结构。因此,在原始文件中此数据并未直接存在,并且常规方法也无法获取该数据

首先访问该JSON数据的官方网址,在浏览器中进行查看,并确认所需的数据是否完全包含在内。此次请求返回了17条相关信息,请注意所需的信息并未完全包含在内,并需继续探索其他JS包以获取完整的数据集。

我们将抓包浏览器的滚动条滑动至底部以引发所有JavaScript请求接着,在继续寻找JavaScript包的过程中我们最终检查了所有的JavaScript包并未发现任何与新闻信息相关的数据

那么该信息不再包含在js包中。我们转而查看其他类型的请求。此时我们发现许多get请求均响应所需的新闻资讯。这表明仅当第一次发起Ajax请求时才会返回包含JSON格式的数据。而后续的所有Ajax请求均返回以html形式呈现的字符串内容。

对于每次Ajax请求返回的结果而言,在JSON响应中获取URL地址与在HTML响应中获取内容之间是否存在某种规律进行比较分析。
我们能够观察到,在JSON信息中包含的网址与HTML属性所指定的字符串数据属于同一个请求地址的一部分
仅仅在请求时发送的不同参数即可限定处理方式;由此可见,在同一个请求地址上进行数据处理时,并不会因为传入的不同参数而产生不同的数据格式;相反地,则会根据不同的传入参数返回对应的数据格式。
http://news.baidu.com/widget?id=LocalNews&ajax=json&t=1501348444467 JSON数据的网址
http://news.baidu.com/widget?id=civilnews&t=1501348728134 html类型的字符串数据网址
http://news.baidu.com/widget?id=InternationalNews&t=1501348728196 html类型的字符串数据网址
为了实现将HTML类型的字符串数据URL与添加JSON数据URL参数的技术效果如何?
http://news.baidu.com/widget?id=civilnews&ajax=json 将html类型的字符串数据网址加上JSON数据的网址参数
http://news.baidu.com/widget?id=InternationalNews&ajax=json 将html类型的字符串数据网址加上JSON数据的网址参数

这次就容易处理了。首先找出所有包含HTML类型的字符串数据地址;接着通过前面所述的方法将这些HTML 类型的数据转换为 JSON 格式的地址;最后再循环遍历这些转换后的JSON 格式地址就可以获取到所有的新闻链接了。
crapy实现
在学习过程中有什么不懂得可以加我的
python学习交流扣扣qun,784758214
群里有不错的学习视频教程、开发工具与电子书籍。
与你分享python企业当下人才需求及怎么从零基础学习好python,和学习什么内容
# -*- coding: utf-8 -*-
import scrapy
from scrapy.http import Request,FormRequest
import re
import json
from adc.items import AdcItem
from scrapy.selector import Selector
class PachSpider(scrapy.Spider): #定义爬虫类,必须继承scrapy.Spider
name = 'pach' #设置爬虫名称
allowed_domains = ['news.baidu.com'] #爬取域名
start_urls = ['http://news.baidu.com/widget?id=civilnews&ajax=json']
qishiurl = [ #的到所有页面id
'InternationalNews',
'FinanceNews',
'EnterNews',
'SportNews',
'AutoNews',
'HouseNews',
'InternetNews',
'InternetPlusNews',
'TechNews',
'EduNews',
'GameNews',
'DiscoveryNews',
'HealthNews',
'LadyNews',
'SocialNews',
'MilitaryNews',
'PicWall'
]
urllieb = []
for i in range(0,len(qishiurl)): #构造出所有idURL
kaishi_url = 'http://news.baidu.com/widget?id=' + qishiurl[i] + '&ajax=json'
urllieb.append(kaishi_url)
# print(urllieb)
def parse(self, response): #选项所有连接
for j in range(0, len(self.urllieb)):
a = '正在处理第%s个栏目:url地址是:%s' % (j, self.urllieb[j])
yield scrapy.Request(url=self.urllieb[j], callback=self.enxt) #每次循环到的url 添加爬虫
def enxt(self, response):
neir = response.body.decode("utf-8")
pat2 = '"m_url":"(.*?)"'
url = re.compile(pat2, re.S).findall(neir) #通过正则获取爬取页面 的URL
for k in range(0,len(url)):
zf_url = url[k]
url_zf = re.sub("\ \/", "/", zf_url)
pduan = url_zf.find('http://')
if pduan == 0:
print(url_zf) #输出获取到的所有url
