php抓取网页不全 js(数据加载是一种异步加载方式,原始的页面最初不会)

优采云 发布时间: 2022-02-13 07:09

  php抓取网页不全 js(数据加载是一种异步加载方式,原始的页面最初不会)

  数据加载是一种异步加载方式。原创页面起初不收录一些数据。原创页面加载完成后,会请求一个接口从服务器获取数据,然后对数据进行处理并呈现在网页上。只需发送一个 Ajax 请求。如果遇到这样的页面,直接使用requests之类的库爬取原创页面是无法获取到有效数据的。这时候就需要分析网页后端向接口发送的Ajax请求了。如果可以使用requests来模拟Ajax请求,那么就可以成功获取。

  Ajax,全称是Asynchronous JavaScript and XML,即异步JavaScript和XML。这不是编程

  语言,但使用JavaScript与服务器交换数据并更新,同时保证页面不刷新,页面链接不改变

  网页技术的一部分。对于传统的网页,如果要更新其内容,则必须刷新整个页面,但使用 Ajax,您可以在不完全刷新页面的情况下更新其内容。在这个过程中,页面实际上是在后台与服务器交互的。获取到数据后,使用 JavaScript 改变网页,从而更新网页的内容。

  以微博为例

  以微博为例,切换到微博页面,一直往下滚动,可以发现往下滑动几条微博后就没有再往下,而是出现加载*敏*感*词*,过一会又会出现新的微博继续出现在下方。博客内容,这个过程真的是Ajax加载的过程。注意页面并没有完全刷新,也就是说页面的链接没有变化,但是页面中有新的内容,也就是后面刷新的新微博。这就是通过 Ajax 获取和呈现新数据的方式。

  Ajax 实际上有一个特殊的请求类型叫做 xhr。可以找到一个名称以getIndex开头的请求,其Type为xhr,即Ajax请求。用鼠标点击请求,查看请求的详细信息。请求标头中的信息之一是 X-Requested-With:XMLHttpRequest,它将请求标记为 Ajax 请求。然后点击预览查看响应的内容,是 JSON 格式的。

  

  

  

  这是一个 GET 类型的请求,请求链接是 . 请求有 4 个参数: type , value ,

  containerid 和页面。可以发现,它们的type、value和containerid总是一样的。type总是uid,value的值是页面链接中的数字,其实就是用户的id。另外,还有containerid。可以查到是107603加上用户id。改变的值为page,显然这个参数是用来控制分页的,page=l代表第一页,page=2代表第二页,以此类推。

  返回的json数据中最关键的两条信息分别是cardlistinfo和cards:前者收录了比较重要的信息总数,观察后发现其实是微博总数,我们可以估算出页数根据这个数字;另一个是一个列表,里面有10个元素,展开一个看看。

  

  可以发现这个元素有一个比较重要的字段mblog。展开它,可以发现它收录了微博的一些信息,例如态度count(点赞数)、comments_count(评论数)、reposts_count(转发数)、created at(发帖时间)、text(微博的文字) ) 等,都是格式化的内容。

  

  

  原则

  向网页更新发送Ajax请求的过程可以简单分为以下三个步骤:发送请求;解析内容;呈现网页。

  发送请求:JavaScript可以实现页面的各种交互功能,Ajax也不例外,JavaScript也能实现。这是由 JavaScript 实现的 Ajax 的最低级别。其实就是新建一个XMLHttpRequest对象,然后调用onreadystatechange属性设置*敏*感*词*,然后调用open和send方法向一个链接(也就是服务器)发送消息。

  发送了请求。由于设置了*敏*感*词*器,当服务器返回响应时,会触发onreadystatechange对应的方法,然后可以在该方法中解析响应内容。

  

  

  解析内容:得到响应后会触发onreadystatechange属性对应的方法,可以通过xmlhttp的responseText属性获取响应内容。返回的内容可能是HTML,也可能是JSON,然后只需要在方法中用JavaScript进一步处理即可。例如,如果是 JSON,则可以对其进行解析和转换。

  呈现网页:JavaScript 具有更改网页内容的能力。解析响应内容后,可以调用 JavaScript 对网页进行解析处理。例如,通过document.getElementByid().innerHTML的操作,可以改变一个元素中的源代码,从而改变网页上显示的内容。这种操作也称为DOM操作,即对Document网页的操作。文档操作,如更改、删除等。上例中为 document 。getElementByid("myDiv ”) .innerHTML=xmlhttp.responseText 会将ID为myDiv的节点内部的HTML代码更改为服务器返回的内容,这样服务器返回的新数据就会显示在myDiv元素内部。页面似乎已更新。

  代码示例

  爬取所有微博的前10页,首先定义一个方法来获取每个请求的结果。在请求时,page 是一个可变参数,所以将它作为方法参数传入。

  

  这里定义 base_url 来表示请求 URL 的前半部分。接下来构造参数字典,其中type、value、containerid为固定参数,page为可变参数。接下来调用urlencode方法将参数转换为-URL GET请求参数,类似于type=ui d&value=2830678474&containerid=78474&page=2。然后,base_url 与参数组合形成一个新的 URL。接下来,我们通过请求请求链接,添加 headers 参数。然后判断响应的状态码,如果是200,直接调用json方法将内容解析成json返回,否则不返回信息。如果发生异常,捕获并输出其异常信息。

  以今日头条为例

  在抓取之前,先分析一下抓取的逻辑。打开今日头条首页,右上角有一个搜索入口,这里我们尝试捕捉街拍的美图,所以输入“街拍”二字进行搜索。

  

  然后打开开发者工具,查看所有网络请求。首先打开第一个网络请求,这个请求的URL就是当前的link=street shoot。切换到 XHR Filtering 选项卡并查看是否有任何 Ajax 请求。点击数据栏展开,发现有很多条数据。点击第一项展开,可以发现有一个title字段,它的值就是页面中第一条数据的标题。再次查看其他数据,正好是一一对应的。

  

  为了捕捉漂亮的图片,这里的一组图片对应上一个数据字段中的一条数据。每条数据还有一个 image_detail 字段,它是一个列表的形式,其中收录了该组中所有图像的列表。您需要做的就是提出问题并下载它们。一组图片会发布到一个文件夹中,文件夹的名字就是组图的标题。

  切换回 Headers 选项卡并观察其请求 URL 和 Headers 信息。您可以看到这是一个 GET 请求。请求 URL 的参数有 offset、format、keyword、autoload、count 和 curtab。

  

  唯一变化的参数是offset,其他参数都没有变化,而且第二次请求的offset值是20,第三次是40,第四次是60,所以可以找到规律,这个offset值是偏移值,然后可以推断出count参数是一次获取的数据条数。因此,我们可以使用offset参数来控制数据分页。

  代码示例

  实现方法 get_page 以加载单个 Ajax 请求的结果。唯一改变的参数是偏移量,所以我们将它作为参数传递

  import requests

from urllib.parse import urlencode

def get_page(offset):

params = {

'offset':offset,

'format':'json',

'keyword':'街拍',

'autoload':'true',

'count':'20',

'cur_tab':'1'

}

url = 'http://www.toutiao.com/search_content/?'+urlencode(params)

try:

response = requests.get(url)

print(response)

if response.status_code == 200:

return response.json()

except requests.ConnectionError:

return None

get_page(1)

  

  实现另一种解析方法:提取每条数据的image_detail字段中的每条图片链接,返回图片链接和图片所属的标题。这时候就可以构造一个*敏*感*词*了

  def get_images(json):

if json.get('data'):

for item in json.get('data'):

title = item.get('title')

images = item.get('image_detail')

for image in images:

yield {

'image':image.get('url'),

'title':title

}

  

  这里的数据没有任何价值,说明有防采摘措施。

  后面会分析

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线