Html 试图通过抓取来查找超链接

Html 试图通过抓取来查找超链接,html,r,web-scraping,Html,R,Web Scraping,所以我对网络垃圾这一话题还相当陌生。我正在尝试查找以下页面的html代码包含的所有超链接: 这就是我所尝试的: url <- "https://www.exito.com/mercado/lacteos-huevos-y-refrigerados/leches" webpage <- read_html(url) html_attr(html_nodes(webpage, "a"), "href") url您将无法获取所需的a标记,因为html/xml解析器无法看到网站的该部分。

所以我对网络垃圾这一话题还相当陌生。我正在尝试查找以下页面的html代码包含的所有超链接:

这就是我所尝试的:

url <- "https://www.exito.com/mercado/lacteos-huevos-y-refrigerados/leches"
webpage <- read_html(url)
html_attr(html_nodes(webpage, "a"), "href")

url您将无法获取所需的
a
标记,因为html/xml解析器无法看到网站的该部分。这是因为它是网站的一个动态部分,如果你选择网站的另一部分,它会发生变化;网站唯一的“静态”部分是顶部标题,这就是为什么你只得到6个
a
标签:标题中的6个
a
标签

为此,我们需要模仿浏览器(firefox、chrome等)的行为,进入网站(请注意,我们不是以html/xml解析器的身份进入网站,而是通过浏览器以“用户”的身份进入网站),并从中读取html/xml源代码

为此,我们需要R包
RSelenium
。请确保将其正确地与一起使用,因为没有它,下面的任何代码都无法工作

在您安装了
RSelenium
docker
之后,从您的终端运行
docker-run-d-p 4445:4444 selenium/standalone firefox:2.53.1
(如果在Linux上,您可以在终端上运行它;如果在Windows上,您必须下载docker终端,请在那里运行它)。之后,您就可以复制下面的代码了

为什么你的方法不起作用 我们需要从下图访问第5个
div
标签:

正如你所看到的,这个第五个
div
标签里面有三个点(
),表示里面有代码:这正是网站底部所有的位置(包括你要找的
a
标签)。如果我们尝试使用
rvest
xml2
访问此第5个标记,我们将找不到任何内容:

库(xml2)
图书馆(dplyr)
#> 
#>正在附加包:“dplyr”
#>以下对象已从“package:stats”屏蔽:
#> 
#>滤波器,滞后
#>以下对象已从“package:base”屏蔽:
#> 
#>相交、setdiff、setequal、并集
lnk%
读取html()%>%
xml_find_all(//div[@class='flex-grow-1w-100flex-column'])%>%
xml_children()
#>{xml_nodeset(6)}
#>[1]\n
#>[2]\n
#>[3]\n
#>[4]\n
#>[5]\n
#> [6] 
请注意,第5个
div
标记内没有任何代码。一个简单的html/xml解析器无法捕获它

它是如何工作的 我们需要使用
RSelenium
。在您正确安装所有内容后,我们需要设置“远程驱动程序”,打开它并导航到网站。所有这些步骤都只是为了确保我们以“普通”用户的身份从浏览器进入网站。这将确保我们可以访问在进入网站时实际看到的呈现代码。下面是进入网站和构建链接的详细步骤


#确保正确安装docker:https://docs.ropensci.org/RSelenium/articles/docker.html
图书馆(资源库)
#在安装docker之后和运行代码之前,请确保运行
#rselenium docker镜像:docker run-d-p 4445:4444 selenium/standalone firefox:2.53.1
#现在,设置远程驱动程序
remDr%
#查找具有特定类的所有标记
#我在网站代码上手动搜索了这个标签,发现所有的产品
#具有共享同一类的a标记
xml_find_all(//a[@class='vtex-product-summary-2-x-clearLink h-100 flex-column']”)%>%
#提取href属性
xml_attr(“href”)%%>%
粘贴0(“https://www.exito.com", .)
产品链接
#>  [1] "https://www.exito.com/leche-semidescremada-deslactosada-en-bolsa-x-900-ml-145711/p"
#>  [2] "https://www.exito.com/leche-entera-en-bolsa-x-900-ml-145704/p"                     
#>  [3] "https://www.exito.com/leche-entera-sixpack-x-1300-ml-cu-987433/p"                  
#>  [4] "https://www.exito.com/leche-deslactosada-en-caja-x-1-litro-878473/p"               
#>  [5] "https://www.exito.com/leche-polvo-deslactos-semidesc-764522/p"                     
#>  [6] "https://www.exito.com/leche-slight-sixpack-en-caja-x-1050-ml-cu-663528/p"          
#>  [7] "https://www.exito.com/leche-semidescremada-sixpack-en-caja-x-1050-ml-cu-663526/p"  
#>  [8] "https://www.exito.com/leche-descremada-sixpack-x-1300-ml-cu-563046/p"              
#>  [9] "https://www.exito.com/of-leche-deslact-pag-5-lleve-6-439057/p"                     
#> [10] "https://www.exito.com/sixpack-de-leche-descremada-x-1100-ml-cu-414454/p"           
#> [11] "https://www.exito.com/leche-en-polvo-klim-fortificada-360g-239085/p"               
#> [12] "https://www.exito.com/leche-deslactosada-descremada-en-caja-x-1-litro-238291/p"    
#> [13] "https://www.exito.com/leche-deslactosada-en-caja-x-1-litro-157334/p"               
#> [14] "https://www.exito.com/leche-entera-larga-vida-en-caja-x-1-litro-157332/p"          
#> [15] "https://www.exito.com/leche-en-polvo-klim-fortificada-780g-138121/p"               
#> [16] "https://www.exito.com/leche-entera-en-bolsa-x-1-litro-125079/p"                    
#> [17] "https://www.exito.com/leche-entera-en-bolsa-sixpack-x-11-litros-cu-59651/p"        
#> [18] "https://www.exito.com/leche-deslactosada-descremada-sixpack-x-11-litros-cu-22049/p"
#> [19] "https://www.exito.com/leche-entera-en-polvo-instantanea-x-760-gr-835923/p"         
#> [20] "https://www.exito.com/of-alpin-cja-cho-pag9-llev12/p"

希望这能回答您的问题

您将无法获得所需的
a
标记,因为html/xml解析器无法看到网站的这一部分。这是因为它是网站的一个动态部分,如果你选择网站的另一部分,它会发生变化;网站唯一的“静态”部分是顶部标题,这就是为什么你只得到6个
a
标签:标题中的6个
a
标签

为此,我们需要模仿浏览器的行为(firefox、chrome等),进入网站(n
library(purrr)
library(stringr)
library(caTools)
library(httr)

get_links <- function(sha, start, end){
  string = paste0('{"withFacets":false,"hideUnavailableItems":false,"skusFilter":"ALL_AVAILABLE","query":"148","map":"productClusterIds","orderBy":"OrderByTopSaleDESC","from":' , start , ',"to":' , end , '}')
  base64encoded <- caTools::base64encode(string)
  params = list(
    'extensions' = paste0('{"persistedQuery":{"version":1,"sha256Hash":"' , sha , '","sender":"vtex.store-resources@0.x","provider":"vtex.search-graphql@0.x"},"variables":"' , base64encoded , '"}')
  )

  product_info <- content(httr::GET(url = 'https://www.exito.com/_v/segment/graphql/v1', query = params))$data$products
  links <- map(product_info, ~{
     .x %>% .$link
  })
  return(links)
}


start <- '0'
end <- '19'     
sha <- httr::GET('https://exitocol.vtexassets.com/_v/public/assets/v1/published/bundle/public/react/asset.min.js?v=1&files=vtex.store-resources@0.38.0,OrderFormContext,Mutations,Queries,PWAContext&files=exitocol.store-components@0.0.2,common,11,3,SearchBar&files=vtex.responsive-values@0.2.0,common,useResponsiveValues&files=vtex.slider@0.7.3,common,0,Dots,Slide,Slider,SliderContainer&files=exito.components@4.0.7,common,0,1,3,4&workspace=master') %>%
  content(., as = "text")%>% str_match(.,'query\\s+productSearch.*?hash:\\s+"(.*?)"')%>% .[[2]] 
links <- get_links(sha, start, end)
print(links)
import requests, base64, re, json

def get_sha():
    r = requests.get('https://exitocol.vtexassets.com/_v/public/assets/v1/published/bundle/public/react/asset.min.js?v=1&files=vtex.store-resources@0.38.0,OrderFormContext,Mutations,Queries,PWAContext&files=exitocol.store-components@0.0.2,common,11,3,SearchBar&files=vtex.responsive-values@0.2.0,common,useResponsiveValues&files=vtex.slider@0.7.3,common,0,Dots,Slide,Slider,SliderContainer&files=exito.components@4.0.7,common,0,1,3,4&workspace=master')
    p = re.compile(r'query\s+productSearch.*?hash:\s+"(.*?)"') #https://regex101.com/r/VdC27H/5
    sha = p.findall(r.text)[0]
    return sha

def get_json(sha, start, end):
    #these 'from' and 'to' values correspond with page # as pages cover batches of 20 e.g. start 20 end 39

    string = '{"withFacets":false,"hideUnavailableItems":false,"skusFilter":"ALL_AVAILABLE","query":"148","map":"productClusterIds","orderBy":"OrderByTopSaleDESC","from":' + start + ',"to":' + end + '}' 
    base64encoded = base64.b64encode(string.encode('utf-8')).decode()
    params = (('extensions', '{"persistedQuery":{"sha256Hash":"' + sha + '","sender":"vtex.store-resources@0.x","provider":"vtex.search-graphql@0.x"},"variables":"' + base64encoded  + '"}'),)
    r = requests.get('https://www.exito.com/_v/segment/graphql/v1',params=params)
    return r.json()

def get_links(sha, start, end):
    result = get_json(sha, start, end)
    links = [i['link'] for i in result['data']['products']]
    return links

sha = get_sha()
links = get_links(sha, '0', '19')
#print(len(links))
print(links)