」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > Python 中網頁抓取的當前問題和錯誤以及解決它們的技巧!

Python 中網頁抓取的當前問題和錯誤以及解決它們的技巧!

發佈於2024-09-04
瀏覽:274

Introduction

Greetings! I'm Max, a Python developer from Ukraine, a developer with expertise in web scraping, data analysis, and processing.

My journey in web scraping started in 2016 when I was solving lead generation challenges for a small company. Initially, I used off-the-shelf solutions such as Import.io and Kimono Labs. However, I quickly encountered limitations such as blocking, inaccurate data extraction, and performance issues. This led me to learn Python. Those were the glory days when requests and lxml/beautifulsoup were enough to extract data from most websites. And if you knew how to work with threads, you were already a respected expert :)

One of our community members wrote this blog as a contribution to Crawlee Blog. If you want to contribute blogs like these to Crawlee Blog, please reach out to us on our discord channel.

Crawlee & Apify

This is the official developer community of Apify and Crawlee. | 8318 members

Current problems and mistakes of web scraping in Python and tricks to solve them! discord.com

As a freelancer, I've built small solutions and large, complex data mining systems for products over the years.

Today, I want to discuss the realities of web scraping with Python in 2024. We'll look at the mistakes I sometimes see and the problems you'll encounter and offer solutions to some of them.

Let's get started.

Just take requests and beautifulsoup and start making a lot of money...

No, this is not that kind of article.

1. "I got a 200 response from the server, but it's an unreadable character set."

Yes, it can be surprising. But I've seen this message from customers and developers six years ago, four years ago, and in 2024. I read a post on Reddit just a few months ago about this issue.

Let's look at a simple code example. This will work for requests, httpx, and aiohttp with a clean installation and no extensions.

import httpx

url = 'https://www.wayfair.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = httpx.get(url, headers=headers)

print(response.content[:10])

The print result will be similar to:

b'\x83\x0c\x00\x00\xc4\r\x8e4\x82\x8a'

It's not an error - it's a perfectly valid server response. It's encoded somehow.

The answer lies in the Accept-Encoding header. In the example above, I just copied it from my browser, so it lists all the compression methods my browser supports: "gzip, deflate, br, zstd". The Wayfair backend supports compression with "br", which is Brotli, and uses it as the most efficient method.

This can happen if none of the libraries listed above have a Brotli dependency among their standard dependencies. However, they all support decompression from this format if you already have Brotli installed.

Therefore, it's sufficient to install the appropriate library:

pip install Brotli

This will allow you to get the result of the print:

b'

You can obtain the same result for aiohttp and httpx by doing the installation with extensions:

pip install aiohttp[speedups]
pip install httpx[brotli]

By the way, adding the brotli dependency was my first contribution to crawlee-python. They use httpx as the base HTTP client.

You may have also noticed that a new supported data compression format zstd appeared some time ago. I haven't seen any backends that use it yet, but httpx will support decompression in versions above 0.28.0. I already use it to compress server response dumps in my projects; it shows incredible efficiency in asynchronous solutions with aiofiles.

The most common solution to this situation that I've seen is for developers to simply stop using the Accept-Encoding header, thus getting an uncompressed response from the server. Why is that bad? The main page of Wayfair takes about 1 megabyte uncompressed and about 0.165 megabytes compressed.

Therefore, in the absence of this header:

  • You increase the load on your internet bandwidth.
  • If you use a proxy with traffic, you increase the cost of each of your requests.
  • You increase the load on the server's internet bandwidth.
  • You're revealing yourself as a scraper, since any browser uses compression.

But I think the problem is a bit deeper than that. Many web scraping developers simply don't understand what the headers they use do. So if this applies to you, when you're working on your next project, read up on these things; they may surprise you.

2. "I use headers as in an incognito browser, but I get a 403 response". Here's Johnn-... I mean, Cloudflare

Yes, that's right. 2023 brought us not only Large Language Models like ChatGPT but also improved Cloudflare protection.

Those who have been scraping the web for a long time might say, "Well, we've already dealt with DataDome, PerimeterX, InCapsula, and the like."

But Cloudflare has changed the rules of the game. It is one of the largest CDN providers in the world, serving a huge number of sites. Therefore, its services are available to many sites with a fairly low entry barrier. This makes it radically different from the technologies mentioned earlier, which were implemented purposefully when they wanted to protect the site from scraping.

Cloudflare is the reason why, when you start reading another course on "How to do web scraping using requests and beautifulsoup", you can close it immediately. Because there's a big chance that what you learn will simply not work on any "decent" website.

Let's look at another simple code example:

from httpx import Client

client = Client(http2=True)

url = 'https://www.g2.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = client.get(url, headers=headers)

print(response)

Of course, the response would be 403.

What if we use curl?

curl -XGET -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"' -H 'Accept: text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg xml,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' 'https://www.g2.com/' -s -o /dev/null -w "%{http_code}\n"

Also 403.

Why is this happening?

Because Cloudflare uses TLS fingerprints of many HTTP clients popular among developers, site administrators can also customize how aggressively Cloudflare blocks clients based on these fingerprints.

For curl, we can solve it like this:

curl -XGET -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"' -H 'Accept: text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg xml,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' 'https://www.g2.com/' --tlsv1.3 -s -o /dev/null -w "%{http_code}\n"

You might expect me to write here an equally elegant solution for httpx, but no. About six months ago, you could do the "dirty trick" and change the basic httpcore parameters that it passes to h2, which are responsible for the HTTP2 handshake. But now, as I'm writing this article, that doesn't work anymore.

There are different approaches to getting around this. But let's solve it by manipulating TLS.

The bad news is that all the Python clients I know of use the ssl library to handle TLS. And it doesn't give you the ability to manipulate TLS subtly.

The good news is that the Python community is great and implements solutions that exist in other programming languages.

The first way to solve this problem is to use tls-client

This Python wrapper around the Golang library provides an API similar to requests.

pip install tls-client
from tls_client import Session

client = Session(client_identifier="firefox_120")

url = 'https://www.g2.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = client.get(url, headers=headers)

print(response)

The tls_client supports TLS presets for popular browsers, the relevance of which is maintained by developers. To use this, you must pass the necessary client_identifier. However, the library also allows for subtle manual manipulation of TLS.

The second way to solve this problem is to use curl_cffi

This wrapper around the C library patches curl and provides an API similar to requests.

pip install curl_cffi
from curl_cffi import requests

url = 'https://www.g2.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = requests.get(url, headers=headers, impersonate="chrome124")

print(response)

curl_cffi also provides TLS presets for some browsers, which are specified via the impersonate parameter. It also provides options for subtle manual manipulation of TLS.

I think someone just said, "They're literally doing the same thing." That's right, and they're both still very raw.

Let's do some simple comparisons:

Feature tls_client curl_cffi
TLS preset
TLS manual
async support -
big company support -
number of contributors -

Obviously, curl_cffi wins in this comparison. But as an active user, I have to say that sometimes there are some pretty strange errors that I'm just unsure how to deal with. And let's be honest, so far, they are both pretty raw.

I think we will soon see other libraries that solve this problem.

One might ask, what about Scrapy? I'll be honest: I don't really keep up with their updates. But I haven't heard about Zyte doing anything to bypass TLS fingerprinting. So out of the box Scrapy will also be blocked, but nothing is stopping you from using curl_cffi in your Scrapy Spider.

3. What about headless browsers and Cloudflare Turnstile?

Yes, sometimes we need to use headless browsers. Although I'll be honest, from my point of view, they are used too often even when clearly not necessary.

Even in a headless situation, the folks at Cloudflare have managed to make life difficult for the average web scraper by creating a monster called Cloudflare Turnstile.

To test different tools, you can use this demo page.

To quickly test whether a library works with the browser, you should start by checking the usual non-headless mode. You don't even need to use automation; just open the site using the desired library and act manually.

What libraries are worth checking out for this?

Candidate #1 Playwright playwright-stealth

It'll be blocked and won't let you solve the captcha.

Playwright is a great library for browser automation. However the developers explicitly state that they don't plan to develop it as a web scraping tool.

And I haven't heard of any Python projects that effectively solve this problem.

Candidate #2 undetected_chromedriver

It'll be blocked and won't let you solve the captcha.

This is a fairly common library for working with headless browsers in Python, and in some cases, it allows bypassing Cloudflare Turnstile. But on the target website, it is blocked. Also, in my projects, I've encountered at least two other cases where Cloudflare blocked undetected_chromedriver.

In general, undetected_chromedriver is a good library for your projects, especially since it uses good old Selenium under the hood.

Candidate #3 botasaurus-driver

It allows you to go past the captcha after clicking.

I don't know how its developers pulled this off, but it works. Its main feature is that it was developed specifically for web scraping. It also has a higher-level library to work with - botasaurus.

On the downside, so far, it's pretty raw, and botasaurus-driver has no documentation and has a rather challenging API to work with.

To summarize, most likely, your main library for headless browsing will be undetected_chromedriver. But in some particularly challenging cases, you might need to use botasaurus.

4. What about frameworks?

High-level frameworks are designed to speed up and ease development by allowing us to focus on business logic, although we often pay the price in flexibility and control.

So, what are the frameworks for web scraping in 2024?

Scrapy

It's impossible to talk about Python web scraping frameworks without mentioning Scrapy. Scrapinghub (now Zyte) first released it in 2008. For 16 years, it has been developed as an open-source library upon which development companies built their business solutions.

Talking about the advantages of Scrapy, you could write a separate article. But I will emphasize the two of them:

  • The huge amount of tutorials that have been released over the years
  • Middleware libraries are written by the community and are extending their functionality. For example, scrapy-playwright.

But what are the downsides?

In recent years, Zyte has been focusing more on developing its own platform. Scrapy mostly gets fixes only.

  • Lack of development towards bypassing anti-scraping systems. You have to implement them yourself, but then, why do you need a framework?
  • Scrapy was originally developed with the asynchronous framework Twisted. Partial support for asyncio was added only in version 2.0. Looking through the source code, you may notice some workarounds that were added for this purpose.

Thus, Scrapy is a good and proven solution for sites that are not protected against web scraping. You will need to develop and add the necessary solutions to the framework in order to bypass anti-scraping measures.

Botasaurus

A new framework for web scraping using browser automation, built on botasaurus-driver. The initial commit was made on May 9, 2023.

Let's start with its advantages:

  • Allows you to bypass any Claudflare protection as well as many others using botasaurus-driver.
  • Good documentation for a quick start

Downsides include:

  • Browser automation only, not intended for HTTP clients.
  • Tight coupling with botasaurus-driver; you can't easily replace it with something better if it comes out in the future.
  • No asynchrony, only multithreading.
  • At the moment, it's quite raw and still requires fixes for stable operation.
  • There are very few training materials available at the moment.

This is a good framework for quickly building a web scraper based on browser automation. It lacks flexibility and support for HTTP clients, which is crutias for users like me.

Crawlee for Python

A new framework for web scraping in the Python ecosystem. The initial commit was made on Jan 10, 2024, with a release in the media space on July 5, 2024.

Current problems and mistakes of web scraping in Python and tricks to solve them! apify / crawlee-python

Crawlee—A web scraping and browser automation library for Python to build reliable crawlers. Extract data for AI, LLMs, RAG, or GPTs. Download HTML, PDF, JPG, PNG, and other files from websites. Works with BeautifulSoup, Playwright, and raw HTTP. Both headful and headless mode. With proxy rotation.

Current problems and mistakes of web scraping in Python and tricks to solve them!
A web scraping and browser automation library

Current problems and mistakes of web scraping in Python and tricks to solve them!Current problems and mistakes of web scraping in Python and tricks to solve them!Current problems and mistakes of web scraping in Python and tricks to solve them!Current problems and mistakes of web scraping in Python and tricks to solve them!

Crawlee covers your crawling and scraping end-to-end and helps you build reliable scrapers. Fast.

? Crawlee for Python is open to early adopters!

Your crawlers will appear almost human-like and fly under the radar of modern bot protections even with the default configuration. Crawlee gives you the tools to crawl the web for links, scrape data and persistently store it in machine-readable formats, without having to worry about the technical details. And thanks to rich configuration options, you can tweak almost any aspect of Crawlee to suit your project's needs if the default settings don't cut it.

? View full documentation, guides and examples on the Crawlee project website ?

We also have a TypeScript implementation of the Crawlee, which you can explore and utilize for your projects. Visit our GitHub repository for more information Crawlee for JS/TS on GitHub.

Installation

We…


View on GitHub


Developed by Apify, it is a Python adaptation of their famous JS framework crawlee, first released on Jul 9, 2019.

As this is a completely new solution on the market, it is now in an active design and development stage. The community is also actively involved in its development. So,we can see that the use of curl_cffi is already being discussed. The possibility of creating their own Rust-based client was previously discussed. I hope the company doesn't abandon the idea.

From Crawlee team:
"Yeah, for sure we will keep improving Crawlee for Python for years to come."

As I personally would like to see an HTTP client for Python developed and maintained by a major company. And Rust shows itself very well as a library language for Python. Let's remember at least Ruff and Pydantic v2.

Advantages:

The framework was developed by an established company in the web scraping market, which has well-developed expertise in this sphere.

  • Support for both browser automation and HTTP clients.
  • Fully asynchronous, based on asyncio.
  • Active development phase and media activity. As developers listen to the community, it is quite important in this phase.

On a separate note, it has a pretty good modular architecture. If developers introduce the ability to switch between several HTTP clients, we will get a rather flexible framework that allows us to easily change the technologies used, with a simple implementation from the development team.

Deficiencies:

  • The framework is new. There are very few training materials available at the moment.
  • At the moment, it's quite raw and still requires fixes for stable operation, as well as convenient interfaces for configuration. -There is no implementation of any means of bypassing anti-scraping systems for now other than changing sessions and proxies. But they are being discussed.

I believe that how successful crawlee-python turns out to depends primarily on the community. Due to the small number of tutorials, it is not suitable for beginners. However, experienced developers may decide to try it instead of Scrapy.

In the long run, it may turn out to be a better solution than Scrapy and Botasaurus. It already provides flexible tools for working with HTTP clients, automating browsers out of the box, and quickly switching between them. However, it lacks tools to bypass scraping protections, and their implementation in the future may be the deciding factor in choosing a framework for you.

Conclusion

If you have read all the way to here, I assume you found it interesting and maybe even helpful :)

The industry is changing and offering new challenges, and if you are professionally involved in web scraping, you will have to keep a close eye on the situation. In some other field, you would remain a developer who makes products using outdated technologies. But in modern web scraping, you become a developer who makes web scrapers that simply don't work.

Also, don't forget that you are part of the larger Python community, and your knowledge can be useful in developing tools that make things happen for all of us. As you can see, many of the tools you need are being built literally right now.

I'll be glad to read your comments. Also, if you need a web scraping expert or do you just want to discuss the article, you can find me on the following platforms: Github, Linkedin, Apify, Upwork, Contra.

Thank you for your attention :)

版本聲明 本文轉載於:https://dev.to/crawlee/current-problems-and-mistakes-of-web-scraping-in-python-and-tricks-to-solve-them-1ogf?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 掌握 React Native 中的深度連結和通用連結:OpenGraph Share 和 Node.js 集成
    掌握 React Native 中的深度連結和通用連結:OpenGraph Share 和 Node.js 集成
    设想 假设您有一个名为 ShopEasy 的电子商务应用程序,并且您希望点击电子邮件、消息或社交媒体中的产品链接的用户被直接重定向到应用程序中的相关产品页面,而不是网站。 第1步:在nodejs服务器中进行Opengraph配置以进行链接预览: Open Graph...
    程式設計 發佈於2024-11-07
  • 如何在不使用“eval”的情況下安全地解析“寬鬆”JSON?
    如何在不使用“eval”的情況下安全地解析“寬鬆”JSON?
    在沒有風險評估的情況下解析「輕鬆」的JSONJSON 是廣泛使用的資料交換格式,需要帶引號的鍵的嚴格語法。但是,某些應用程式可能會遇到帶有不帶引號的鍵的“寬鬆”JSON。由於安全風險,不鼓勵使用 eval 解析此類資料。 避免邪惡的 Evaleval 的替代方法是基於正則表達式的方法,該方法在解析之...
    程式設計 發佈於2024-11-07
  • 透過sponge+dtm快速輕鬆實現高性能的電商系統
    透過sponge+dtm快速輕鬆實現高性能的電商系統
    This article demonstrates how to use the Sponge framework to quickly build a simplified high-performance e-commerce system, implementing flash sale an...
    程式設計 發佈於2024-11-07
  • 什麼是 Java 中的關閉鉤子以及如何有效地使用它?
    什麼是 Java 中的關閉鉤子以及如何有效地使用它?
    1. 了解關閉鉤子 關閉鉤子是 Java 中的一種特殊構造,允許您註冊一個線程,該線程將在 Java 虛擬機 (JVM) 關閉時執行。這可以由各種事件觸發,例如使用者中斷 (Ctrl C)、系統關閉或編程終止。 1.1 關閉鉤子如何運作 當 JVM 啟動時,它會建...
    程式設計 發佈於2024-11-07
  • 在 Web 工具中使用 JavaScript 進行安全加密
    在 Web 工具中使用 JavaScript 進行安全加密
    這是開發人員用來幫助保護程式中的敏感資訊免受潛在攻擊者攻擊的方法。加密將可讀資料轉變為編碼格式,只有使用正確的金鑰才能解碼;因此,它對於保護密碼、財務詳細資料和個人資料等資訊的安全性至關重要。 在資料外洩和網路攻擊非常猖獗的時候,這一點變得非常重要。透過加密數據,開發人員將確保沒有未經授權的一方在...
    程式設計 發佈於2024-11-07
  • 使用 STMMCU 實現靜電除塵器控制器的 SPWM ase/ase 逆變器
    使用 STMMCU 實現靜電除塵器控制器的 SPWM ase/ase 逆變器
    前段時間提到中頻電除塵器控制器,我仔細分析了單相和三相SPWM驅動時間,完成了STM32F103處理器上SPWM程式碼的編寫,並用示波器測試了訊號和波形,邏輯分析儀。 STM32F103的TIMER1和TIMER2支援互補的PWM輸出,我選擇TIMER1的CH1、CH2、CH3用於A、B、C三相驅...
    程式設計 發佈於2024-11-07
  • 如何將 java.util.Date 轉換為 java.time 類型?
    如何將 java.util.Date 轉換為 java.time 類型?
    將java.util.Date 轉換為java.time 類型遺留的java.util.Date 和Calendar 類別以其複雜性而聞名和麻煩。雖然建議使用 java.time 框架進行日期時間管理,但在使用現有程式碼時,必須在這些新舊類型之間進行轉換。 對應到 java.time 類型將 jav...
    程式設計 發佈於2024-11-07
  • #daysofMiva 編碼挑戰日:JS 中的值和變數
    #daysofMiva 編碼挑戰日:JS 中的值和變數
    嗨,大家好。最近太忙了,都沒有時間記錄我的旅程是怎麼樣的?無論如何,我會繼續關注❤️。 對於我的第 5 天文檔,我只是做了一些非常簡單和簡短的事情。 正如您從上面看到的,一旦您理解了值和變量,這就是一個非常簡單的任務。 那麼什麼是值和變數? JavaScript 中的值 將值...
    程式設計 發佈於2024-11-07
  • 您需要了解的 Python 4 關鍵特性
    您需要了解的 Python 4 關鍵特性
    Spotify、Google、NASA 和摩根大通有什么共同点?他们每天都使用Python。 Python 是一种令人印象深刻且全面的编程语言,在各种技术方法中发挥着至关重要的作用。从搜索引擎、网络应用程序、游戏到动画和其他编程语言,Python 都是发明的核心。 多年来,Python 经历了流行...
    程式設計 發佈於2024-11-07
  • MySQL如何實現樂觀鎖?
    MySQL如何實現樂觀鎖?
    MySQL 中的樂觀鎖:全面解釋樂觀鎖是資料庫管理系統中採用的技術,用於防止以下情況下可能出現的資料衝突:多個使用者嘗試同時更新相同的資料。雖然 MySQL 本身不支援樂觀鎖定,但可以使用標準 SQL 指令來實現。 理解概念樂觀鎖定的操作假設資料不可能被多個使用者頻繁修改。該技術不是獲取資料鎖,而是...
    程式設計 發佈於2024-11-07
  • 如何使用Golang高效取得Windows中的可用磁碟機清單?
    如何使用Golang高效取得Windows中的可用磁碟機清單?
    使用Golang 獲取Windows 上的驅動器清單尋求一種更有效的方法來在Windows 系統上的所有驅動器中搜尋特定的磁碟機檔案類型,Go 程式設計師可能想知道是否可以在沒有使用者指定輸入的情況下自動取得可用磁碟機清單。 使用 GetLogicalDrives 和位元操作的解決方案:To列出 W...
    程式設計 發佈於2024-11-07
  • 如何從 C++ 中的函數安全地傳回數組?
    如何從 C++ 中的函數安全地傳回數組?
    從C 中的函數傳回陣列嘗試從C 中的函數傳回陣列可能會導致意外行為,如以下程式碼所示片段:int* uni(int *a,int *b) { int c[10]; ... return c; }此函數嘗試從函數傳回本機陣列 c。但是,當函數返回時,數組佔用的記憶體將被釋放,從...
    程式設計 發佈於2024-11-07
  • HTML5中如何將表格屬性遷移到CSS?
    HTML5中如何將表格屬性遷移到CSS?
    HTML5 表格屬性轉換Visual Studio 的HTML5 驗證功能將單元格填充、單元格間距、valign 和對齊屬性標識為對表格元素無效。為了解決這個問題,HTML5 引入了 CSS 替代方案來控製表格的外觀和間距。 單元格填充:將 cellpadding 替換為應用於表格單元格的 CSS ...
    程式設計 發佈於2024-11-07
  • 為什麼不能在 C++ 中使用非常量變數來定義數組大小?
    為什麼不能在 C++ 中使用非常量變數來定義數組大小?
    了解使用 Const Int 作為數組大小的限制在 C 中,使用 const int 作為數組大小受到以下限制某些限制。讓我們深入研究為什麼會有這些限制。 考慮以下場景:允許:const int size = 2; int array[size] = {0}; // Compilation succ...
    程式設計 發佈於2024-11-07
  • 如何在 MySQL WHERE 子句中指定不明確的「user_id」欄位?
    如何在 MySQL WHERE 子句中指定不明確的「user_id」欄位?
    解決MySQL 'user_id' WHERE 子句中的歧義當處理共享列名的多個表時,MySQL 在使用時可能會遇到歧義WHERE 子句中的該列。這在錯誤訊息“user_id”中很明顯,其中 where 子句不明確。 考慮範例查詢:SELECT user.*, user_info.*...
    程式設計 發佈於2024-11-07

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3