网络抓取困难,URL 在搜索时没有改变,保持不变并且对于搜索的每个项目都没有 url 页面,保持不变

Dificulties webscraping, URL doesnt change on search, remain the same and for every item searched there is no url page, remain the same

我一直在考虑从理论上抓取此页面的方法

https://www.mercadopublico.cl/Home 是智利政府开放的企业,您可以申请向该州提供一些服务。

Mercadopublico

所以我搜索 Camas(西班牙语中“床”的意思) bed search

所以我发现的第一个障碍是 URL 在我的搜索中根本没有改变:https://www.mercadopublico.cl/Home/BusquedaLicitacion 在任何搜索中都是一样的

url don't change

第二道关卡,翻到下一页也不会变。所以我不能像我想的那样在数组上编写 URL 更改类型。

第三关是我最想要的信息

在主弹出窗口 window 的另一个弹出窗口中

pop up window

可以下载 CSV 格式的信息或 JSON 或从弹出窗口中抓取信息 window。

但是到目前为止,当我更改搜索或页面时,url 不会更改的部分我无法获得解决方案。所以到目前为止我无法思考,因为我无法完成第一部分。

我认为 webscrape 弹出窗口会更容易,因为那时我已经有了一个 URL。(弹出窗口 window 确实有一个不同的 URL!)

如果你知道如何或者我是否需要另一种方法来做到这一点(因为我知道我一直只使用 BS4 来做到这一点)请告诉我我应该朝哪个方向走。

这是我的第一个错误,我不知道如何用通常的代码解决,如果你帮我解决这个问题我就无法更进一步,那就是更改 URL 以获得矩阵 url,因为我不能使用范围方法

 # -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""

import requests
from bs4 import BeautifulSoup as bs

url = 'https://www.mercadopublico.cl/Home/BusquedaLicitacion'

#problem here because i cant navigate beacuse ajax doesnt let me
params = {
    'page': 0,
    'page1': 40,
}

results = []

for offset in range(0, 121, 40):  #  this method doesnt work on ajax page

    params['start'] = offset

    response = requests.get(url, params=params)
    print('url:', response.url)
    #print('status:', response.status_code)
                    
    soup = bs(response.text, "html.parser")

    all_products = soup.find_all('div', {'class': 'product-tile'})

    for product in all_products:
        itemid = product.get('data-itemid') 
        print('itemid:', itemid)

        data = product.get('data-product') 
        print('data:', data)
        
        name = product.find('span', {'itemprop': 'name'}).text
        print('name:', name)
        
        all_prices = product.find_all('div', {'class': 'price__text'})
        print('len(all_prices):', len(all_prices))
        
        price = all_prices[0].get('aria-label')
        print('price:', price)
        
        results.append( (itemid, name, price, data) )
        print('results')

# ---

# ... here you can save all `results` in file ...
import pandas as pd
df = pd.DataFrame(data = results[1:],columns = results[0])
df.to_excel('results.xlsx', index=False,header = False)#Writing to Excel file

所以,我现在正尝试通过此代码修改获得 urls

import requests
from bs4 import BeautifulSoup as bs    
from selenium import webdriver

#set chromodriver.exe path
driver = webdriver.Chrome(executable_path="C:\chromedriver.exe")
#implicit wait
driver.implicitly_wait(0.5)
#maximize browser
driver.maximize_window()
#launch URL
driver.get('https://www.mercadopublico.cl/Home/BusquedaLicitacion')
#identify element
l =driver.find_element_by_xpath("//button[text()='Check it Now']")
#perform click
driver.execute_script("arguments[0].click();", l);

    
url = 'https://www.mercadopublico.cl/Home/BusquedaLicitacion'
    
response = requests.get(url)
print('url:', response.url)
#print('status:', response.status_code)
                        
soup = bs(response.text, "html.parser")
    
all_products = soup.find_all('a', {'href': '#'})
    
for product in all_products:
    itemurl = product.get('onclick') 
    print('itemurl:', itemurl)# hasta aca

#close browser
driver.quit()

但没有得到任何打印,不确定是什么失败了。

非常感谢。

URL 没有改变,因为它正在使用搜索查询发出 post 请求。

POST https://www.mercadopublico.cl/BuscarLicitacion/Home/Buscar

请求数据为:

{
  "textoBusqueda":"camas",
  "idEstado":"5",
  "codigoRegion":"-1",
  "idTipoLicitacion":"-1",
  "fechaInicio":null,
  "fechaFin":null,
  "registrosPorPagina":"10",
  "idTipoFecha":[],
  "idOrden":"1",
  "compradores":[],
  "garantias":null,
  "rubros":[],
  "proveedores":[],
  "montoEstimadoTipo":[0],
  "esPublicoMontoEstimado":null,
  "pagina":0
}

可能还需要一个 cookie __RequestVerificationToken_L0hvbWU1

然后就可以得到link到HTML中的pop-up了。它位于 link.

的 onclick 属性 内

如果您需要更多帮助,请在评论部分提问。

Python 示例: 我目前已经让它工作到最后一步。当我查看 csv 和 json 文件时,我意识到它们都是无效的。该站点似乎在两者的底部附加了一些 html。 我建议只从最后一页抓取数据,而不是下载 csv/json.

import requests
from bs4 import BeautifulSoup


def get_headers(session):
    res = session.get("https://www.mercadopublico.cl/Home")
    if res.status_code == 200:
        print("Got headers")
        # return res.text
    else:
        print("Failed to get headers")



def search(session):
    data = {
        "textoBusqueda": "Camas",
        "idEstado": "5",
        "codigoRegion": "-1",
        "idTipoLicitacion": "-1",
        "fechaInicio": None,
        "fechaFin": None,
        "registrosPorPagina": "10",
        "idTipoFecha": [],
        "idOrden": "1",
        "compradores": [],
        "garantias": None,
        "rubros": [],
        "proveedores": [],
        "montoEstimadoTipo": [0],
        "esPublicoMontoEstimado": None,
        "pagina": 0
    }
    res = session.post(
        "https://www.mercadopublico.cl/BuscarLicitacion/Home/Buscar",
        data=data)
    if res.status_code == 200:
        print("Search succeeded")
        return res.text
    else:
        print("Search failed with error:", res.reason)



def get_popup_link(html):
    soup = BeautifulSoup(html, "html.parser")
    dirty_links = [link["onclick"] for link in soup.select(".lic-block-body a")]
    # clean onclick links
    clean_links = [link.replace("$.Busqueda.verFicha('", "").replace("')", "") for link in dirty_links]
    return clean_links


def get_download_html(s, links):
    for link in links:
        res = s.get(link)
        if res.status_code == 200:
            print("fetch succeeded")
            return res.text
        else:
            print("fetch failed with error:", res.reason)

def get_download_links(html):
    soup = BeautifulSoup(html, "html.parser")
    dirty_links = [link["onclick"] for link in soup.select(".lic-block-body a")]
    # clean onclick links
    clean_links = [link.replace("$.Busqueda.verFicha('", "").replace("')", "") for link in dirty_links]
    return clean_links

def main():
    with requests.Session() as s:
        get_headers(s)
        html = search(s)
        popup_links = get_popup_link(html)
        print(popup_links)
        download_html = get_download_html(s, popup_links)
        # print(download_html)

main()