IT评测·应用市场-qidao123.com技术社区

标题: Python 爬虫基础教程 [打印本页]

作者: 冬雨财经    时间: 2025-2-13 01:22
标题: Python 爬虫基础教程
爬虫的背景与应用

诞生

爬虫(Web Crawling)是自动化程序,用于从互联网上获取信息。爬虫的根本任务是自动访问网站,通过抓取网页内容并提取有用数据来构建数据库、索引或者举行进一步的数据分析。爬虫通常会模拟欣赏器的行为,以避免被服务器辨认为机器人,而且可以或许在大规模范围内高效地抓取信息。
爬虫技术最早由搜刮引擎开发者提出,目标是自动网络网页信息并将其索引,便于用户搜刮时快速检索干系内容。随着互联网的快速发展,网页内容的增长也越来越迅速,手动网络和分析数据的难度增加,爬虫技术逐渐成为获取网络数据的标准方法。
技术原理

爬虫通常通过以下几个步调实现数据抓取:
例如,有如下网页:
  1. <!doctype html>
  2. <html lang="en-US">
  3. <head>
  4.     <meta charset="utf-8" />
  5.     <title>Simple DOM example</title>
  6. </head>
  7. <body>
  8. <section>
  9.     <img src="/icon.jpg" alt="Logo" width=30%>
  10.     <p>
  11.         Here we will add a link to the
  12.         <a href="https://www.mozilla.org/">Mozilla homepage</a>
  13.     </p>
  14. </section>
  15. </body>
复制代码
通过 Python 脚本发送请求获取到 HTML 代码后,通过筛选元素,例如如果必要爬取图片,就对代码中的 img 元素举行筛选,同理段落元素则筛选出 p 元素,这是 BeautifulSoup 的爬取规则。固然原始的方法还有通过正则表达式举行匹配。
其次,爬虫除了下载指定页面内容外,还可以通过访问本页指向的其他地址举行爬取,例如筛选出上文的 a 元素并将 href 属性存入程序中以供接下来爬取,这样就实现了爬虫的自动化。使用者提供的最初的网页被称为根,而爬虫不断爬取页面其他链接的数量称为深度。
详细操纵

需求分析

这里以爬取新浪新闻为例,新浪新闻的滚动新闻页面直接可以展示出许多新闻链接,雷同于导航,可以作为比较好的根网站。起首通过滚动页面解析出全部的新闻链接,然后对全部链接的新闻举行爬取,并存入本地数据库中。
数据库接纳 SQLite,一个小型本地数据库。数据库以一个 db 文件形式存在本地。
请求内容

requests

  1. import requests
  2. url = "https://finance.sina.com.cn/roll/#pageid=384&lid=2519&k=&num=50&page=1"
  3. response = requests.get(url)
  4. print(response.status_code) # 200,表示成功
  5. if response.status_code == 200:
  6.     content = response.text
  7.     print(content)
复制代码
可以看到有一部分内容如下,这些链接就是必要爬取的内容网站:
  1. <li><a href="https://cj.sina.cn/article/norm_detail?url=https%3A%2F%2Ffinance.sina.com.cn%2Fstock%2Fusstock%2Fc%2F2025-02-08%2Fdoc-ineiumza6406789.shtml" target="_blank">
  2.         沃尔沃汽车将几乎零成本收购Northvolt电池合资企业股份
  3. </a></li>
  4.                                                
  5. <li><a href="https://cj.sina.cn/article/norm_detail?url=https%3A%2F%2Ffinance.sina.com.cn%2Fstock%2Fbxjj%2F2025-02-08%2Fdoc-ineiumza6402728.shtml" target="_blank">
  6.         小心“李鬼”!你炒的DeepSeek概念股可能是假的
  7. </a></li>
  8.                                                
  9. <li><a href="https://cj.sina.cn/article/norm_detail?url=https%3A%2F%2Ffinance.sina.com.cn%2Froll%2F2025-02-08%2Fdoc-ineiumyy8907788.shtml" target="_blank">
  10.         马斯克战胜美国最大工会!美法官拒绝阻止DOGE访问劳工部系统
  11. </a></li>
  12. <li><a href="https://cj.sina.cn/article/norm_detail?url=https%3A%2F%2Ffinance.sina.com.cn%2Fjryx%2Fbank%2F2025-02-08%2Fdoc-ineiumyx2131162.shtml" target="_blank">
  13.         建设银行上海市金山石化支行被罚40万元:因贷款业务严重违反审慎经营规则
  14. </a></li>
  15. <li><a href="https://cj.sina.cn/article/norm_detail?url=https%3A%2F%2Ffinance.sina.com.cn%2Fstock%2Fobserve%2F2025-02-08%2Fdoc-ineiumyy8905576.shtml" target="_blank">
  16.         多氟多业绩大额预亏 早年埋下逆势扩产的雷终究还是炸了
  17. </a></li>
  18.                                                
复制代码
selenium

如果只用 Python 的 requests 库举行请求,可能得到原始页面会发现没有任何内容,原因在于网站是通过网页的 JavaScript 脚本举行即时渲染的,只有通过欣赏器访问实行了 JS 脚本后才会显示出全部链接,而 request 库直接请求的页面原内容并没有实行 JS 脚本。因此,必要利用 selenium 模拟欣赏器访问这个页面来爬取。
  1. from selenium import webdriver
  2. from selenium.webdriver.chrome.service import Service
  3. DRIVER_PATH = "./chromedriver"
  4. def get_driver():
  5.     if not os.path.exists(DRIVER_PATH):
  6.         driver_path = ChromeDriverManager().install()
  7.         shutil.copy(driver_path, DRIVER_PATH)
  8.     options = webdriver.ChromeOptions()
  9.     options.add_argument("--headless")
  10.     options.add_argument("--disable-blink-features=AutomationControlled")
  11.     return webdriver.Chrome(service=Service(DRIVER_PATH), options=options)
  12. driver = get_driver()
复制代码
得到 driver 对象后即可举行爬取:
  1. root_url = "https://news.sina.com.cn/roll/"
  2. driver.get(root_url)
  3. driver.implicitly_wait(5)
  4. content = driver.page_source
复制代码
筛选内容

正则表达式

观察爬取到的网页的一部分:
  1. https://finance.sina.com.cn/stock/marketresearch/2025-02-09/doc-ineivyah8211991.shtml
复制代码
也就是说,要将内容中全部形如这个的链接,通过正则表达式将全部像这样的链接筛选出来
  1. # Get news list by regex
  2. pattern = r"https://finance\.sina\.com\.cn/[a-zA-Z0-9/_-]+/doc-[a-zA-Z0-9]+\.shtml"
  3. news_list = re.findall(pattern, content)
复制代码
BeautifulSoup 筛选

可以看到,全部的链接,都是包罗在列表元素 li 下的超链接 a 元素,而且指向的链接是 a 元素的 href 属性,那么就通过 BS 筛选出全部 li下的 a 并获取其属性即可:
  1. from bs4 import BeautifulSoup
  2. soup = BeautifulSoup(content, 'html.parser')
  3. links = soup.select('li>a')
  4. news_list = []
  5. for link in links:
  6.     news_list.append(link.get('href'))
  7.    
  8. # news_list = [link.get('href') for link in soup.select('li > a') if link.get('href')]
复制代码
进一步操纵

通过上面请求页面并获取网页原内容,并筛选出所必要的信息,根本上已经完成了爬虫的根本功能,接下来的操纵思路根本一样。
解析新闻页面

获取了新闻链接后,再逐一访问单独的新闻页面以获取所必要的内容,存入一个字典中,如果必要可以将其存入本地数据库中。
  1. def get_news_content_from_url(url):
  2.     """
  3.     Get news content from html content
  4.     Record url, title, time and article
  5.     :param url
  6.     :return: news content_dict
  7.     """
  8.     news_dict = {'url': url}
  9.     driver.get(url)
  10.     content = driver.page_source
  11.     soup = BeautifulSoup(content, 'lxml')
  12.     news_title = soup.select('h1.main-title')[0].text.strip()
  13.     news_dict['title'] = news_title
  14.     news_time_temp = datetime.datetime.strptime(
  15.         soup.select('span.date')[0].text.strip(),
  16.         '%Y年%m月%d日 %H:%M'
  17.     )
  18.     news_time = (news_time_temp
  19.                  .strftime('%Y-%m-%d %H:%M:%S'))
  20.     news_dict['time'] = news_time
  21.     news_article = soup.select('div#artibody p')
  22.     news_article_text = ''
  23.     for paragraph in news_article:
  24.         news_article_text += paragraph.text.strip()
  25.     news_dict['article_text'] = news_article_text
  26.     return news_dict
复制代码
存入数据库

这里使用 SQLite 作为数据库,在存入之前,起主要创建数据库和数据表:
  1. def create_table():
  2.     """
  3.     Create a news database while initializing
  4.     :return:
  5.     """
  6.     conn = sqlite3.connect('news_data.db')
  7.     cursor = conn.cursor()
  8.     cursor.execute('''
  9.     CREATE TABLE IF NOT EXISTS news (
  10.         id INTEGER PRIMARY KEY AUTOINCREMENT,
  11.         title TEXT NOT NULL,
  12.         content TEXT,
  13.         published_time TEXT,
  14.         url TEXT UNIQUE,
  15.         created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  16.     )
  17.     ''')
  18.     conn.commit()
  19.     conn.close()
  20.     print("Database and table created successfully!")
复制代码
然后可以将获取的新闻的字典存入数据库中,其中字典的 url 作为键值,检查并避免重复。
  1. def save_news_to_db(news_dict):
  2.     """
  3.     Check for duplicate URLs before inserting into the database
  4.     """
  5.     conn = sqlite3.connect('news_data.db')
  6.     cursor = conn.cursor()
  7.     cursor.execute('SELECT COUNT(*) FROM news WHERE url = ?', (news_dict['url'],))
  8.     exists = cursor.fetchone()[0]
  9.     if exists:
  10.         print(f"Duplicate URL, skipped: {news_dict['title']}")
  11.     else:
  12.         cursor.execute('''
  13.         INSERT INTO news (title, content, published_time, url)
  14.         VALUES (?, ?, ?, ?)
  15.         ''', (
  16.             news_dict['title'],
  17.             news_dict['article_text'],
  18.             news_dict['time'],
  19.             news_dict['url']
  20.         ))
  21.         conn.commit()
  22.         print(f"Saved to DB: {news_dict['title']}")
  23.     conn.close()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4