什么是网络爬虫

网络爬虫(Web crawler),也称为网络蜘蛛(Web spider)、网络机器人(Web robot)或网络蠕虫(Web worm),是一种自动化程序,用于在互联网上自动抓取和索引网页数据。

网络爬虫的主要功能是浏览互联网,并按照预定的规则自动地从网站上抓取信息。它们通过发送HTTP请求来访问网页,并从响应中提取所需的数据。爬虫可以从一个网页链接到另一个网页,逐级遍历整个网站,或者根据给定的搜索条件和规则,抓取特定的网页数据。

网络爬虫通常用于搜索引擎、数据挖掘、数据分析、内容聚合和监测等应用。搜索引擎使用爬虫来构建搜索引擎索引,以便用户能够通过搜索关键字找到相关的网页。数据挖掘和分析领域可以利用爬虫来收集大量的数据,用于分析和提取有用的信息。

网络爬虫的工作原理一般包括以下步骤:
1. 选择初始URL并进行请求;
2. 获取网页响应并解析HTML或其他标记语言;
3. 提取所需的数据(如链接、文本、图像等);
4. 处理提取的数据,并根据需要进行存储或分析;
5. 根据规则和算法决定如何跟进链接,继续抓取其他网页;
6. 重复上述步骤,直到达到预定的条件或抓取完所有目标网页。

需要注意的是,网络爬虫在使用时应遵守网站的使用政策和法律规定,以确保合法、道德和负责任的使用。一些网站可能会限制爬虫的访问或要求事先获得许可。

解析网页数据

在网络爬虫中,解析网页数据是一个重要的步骤,它使我们能够从网页中提取所需的信息。通常,网页使用HTML、XML或JSON等标记语言来组织和呈现数据。下面介绍几种常见的解析网页数据的方法:

1. 正则表达式:正则表达式是一种强大的文本匹配工具,可以通过定义模式来匹配和提取特定格式的文本。在解析简单的网页时,可以使用正则表达式来提取所需的数据。但是对于复杂的HTML结构,正则表达式可能会变得复杂且难以维护。

2. 使用内置的HTML/XML解析器:Java提供了许多内置的库和解析器,如Jsoup、DOM、SAX和StAX等,用于解析和操作HTML和XML文档。这些解析器可以将网页转换为文档对象模型(DOM)或事件流,从而使我们能够方便地遍历和提取数据。

   - Jsoup是一个流行的Java库,用于解析、清洁、遍历和操作HTML文档。它提供了简单而灵活的API,可以通过选择器语法(类似于CSS选择器)来提取所需的元素和属性。

   - DOM(Document Object Model)解析器将整个网页作为一个树状结构加载到内存中,可以使用DOM API来遍历和操作树中的节点。

   - SAX(Simple API for XML)解析器是一种事件驱动的解析器,它逐行读取文档并触发相应的事件,我们可以实现自己的处理器来处理这些事件。

   - StAX(Streaming API for XML)解析器也是一种事件驱动的解析器,类似于SAX,但提供了更方便的API来处理XML文档。

3. 使用JSON解析器:如果网页返回的数据是JSON格式的,我们可以使用Java中的JSON解析库(如Jackson、Gson等)来解析JSON数据。这些库提供了API来将JSON字符串转换为Java对象,并可以轻松地提取所需的数据。

无论使用哪种方法,解析网页数据时需要了解网页的结构和标记语言的语法,以便正确地定位和提取所需的数据。此外,还需要处理异常情况和错误处理,以确保解析过程的稳定性和可靠性。

例如:使用xpath把markboos.html的非空数据,提取到一个字典里

from lxml import etree
import pandas
 
html = etree.parse('bookmarks.html')
# 获取所有信息并存到一个markbooks里
trs = html.xpath('//tbody/tr')
# print(trs)
markbooks = []  # 初始化书签
for tr in trs:
    # 这里用了“.”,意指在trs路径下的,注意此时tbody外的id=1003的tr不包括在内
    xpath_id = tr.xpath('.//td[1]/text()')[0]
    xpath_name = tr.xpath('.//td[2]/text()')[0]  # 注意,加了[0]表示提取了其第一个字符串:张载
    xpath_mark = tr.xpath('.//td[3]/text()')  # 没加[0]的,则表示提取了列表:['为天地立心,为生民立命,为往圣继绝学,为万世开太平。']
    markbook = {  # 根据没次tr,将信息全部存入单页书签里
        "id": xpath_id,
        "name": xpath_name,
        "mark": xpath_mark
    }
    # print(markbook)
    markbooks.append(markbook)  # 所有书签汇总
 
print(markbooks)
# 整合表头和表格数据构成dataframe表格对象
df = pandas.DataFrame(markbooks, columns=["id", "name", "mark"])
print(df)
df.to_excel('书签.xlsx')

爬取动态网页数据

当涉及到爬取动态网页数据时,传统的静态网页解析方法可能无法满足需求,因为动态网页的内容是通过JavaScript等前端技术在客户端生成的。下面介绍几种常见的爬取动态网页数据的方法:

1. 使用Selenium:Selenium是一种自动化测试工具,也可以用于爬取动态网页数据。它模拟浏览器行为,可以加载和执行网页上的JavaScript代码,并提供了API来与页面交互。通过Selenium,我们可以实现自动打开网页、点击按钮、滚动页面等操作,并获取渲染后的网页内容。

2. 使用Headless浏览器:Headless浏览器是没有图形界面的浏览器,可以在后台运行。它可以像普通浏览器一样加载和执行JavaScript代码,同时提供了API来操作页面。常见的Headless浏览器包括PhantomJS、Puppeteer(基于Chromium)、HtmlUnit等。使用Headless浏览器,我们可以模拟用户行为,加载动态内容并获取渲染后的结果。

例如:使用Selenium爬取淘宝网关键词为“红星闪耀中国”的商品信息

import time
 
import pandas
from selenium import webdriver
from selenium.webdriver import ActionChains
 
from info import username, password
 
# 关闭自动化开关
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
# 屏蔽保存密码提示框
prefs = {'credentials_enable_service': False,
        'profile.password_manager_enabled': False}
options.add_experimental_option('prefs', prefs)
# 反爬虫特征处理
options.add_argument('--disable-blink-features=AutomationControlled')
 
# url = 'https://s.taobao.com/search?commend=all&ie=utf8&initiative_id=tbindexz_20170306&q=%E7%BA%A2%E6%98%9F%E7%85%A7%E8%80%80%E4%B8%AD%E5%9B%BD&search_type=item&sourceId=tb.index&spm=a21bo.jianhua.201856-taobao-item.2&ssid=s5-e'
url = 'https://login.taobao.com/member/login.jhtml?spm=a21bo.jianhua.0.0.5af92a89wF3Znx&f=top&redirectURL=http%3A%2F%2Fwww.taobao.com%2F'
# 打开浏览器
driver = webdriver.Chrome(options=options)
driver.maximize_window()
# 打开url网页
driver.get(url)
time.sleep(1)  # 输入完成缓一会儿
# 登录 find_下有很多查找方式,选择自己习惯的方式           send_keys发送关键词到前台网页
driver.find_element_by_xpath('//*[@id="fm-login-id"]').send_keys(username)
driver.find_element_by_xpath('//*[@id="fm-login-password"]').send_keys(password)
time.sleep(3)  # 输入完成又缓一会儿
 
# 滑块验证码
slider = driver.find_element_by_xpath('//*[@id="nc_1_n1z"]')
if slider.is_displayed():
   driver.switch_to.frame(0)
   time.sleep(1)  # 输入完成又缓一会儿
   #                   点击滑块   按住不动
   ActionChains(driver).click_and_hold(on_element=slider).perform()
   #                                  往x轴水平移动  y没移动
   ActionChains(driver).move_by_offset(xoffset=20, yoffset=0).perform()
   time.sleep(1)  # 稍微停顿滑动,应对反扒
   ActionChains(driver).move_by_offset(xoffset=258, yoffset=0).perform()
   #                  暂停1秒后离开鼠标
   ActionChains(driver).pause(1).release().perform()
   driver.switch_to.parent_frame()
 
# 点击登录按钮
driver.find_element_by_xpath('//*[@id="login-form"]/div[4]/button').click()
time.sleep(10)  # 会有验证跳转页面,放缓时间等待回到正常网页
 
# 进入淘宝首页,对查询框输入关键词:红星闪耀中国,并点击搜索按钮
driver.find_element_by_xpath('//*[@id="q"]').send_keys("红星闪耀中国")
driver.find_element_by_xpath('//*[@id="J_TSearchForm"]/div[1]/button').click()
time.sleep(1)
# 取到所有的商品
items = driver.find_elements_by_xpath('//*[@class="Content--contentInner--QVTcU0M"]/*')
 
taobao = []
for item in items:  # 注意,使用了"."从限定范围内查找后续xpath
   title = item.find_element_by_xpath('.//*[@class="Title--title--jCOPvpf"]/span').text  # 商品标题
   price_int = item.find_element_by_xpath('.//*[@class="Price--priceInt--ZlsSi_M"]').text  # 整数价格
   price_float = item.find_element_by_xpath('.//*[@class="Price--priceFloat--h2RR0RK"]').text  # 小数价格
   price = str(price_int) + str(price_float)  # 完整价格
   shopname = item.find_element_by_xpath('.//*[@class="ShopInfo--shopName--rg6mGmy"]').text  # 商家名称
   location = item.find_element_by_xpath('.//*[@class="Price--procity--_7Vt3mX"]').text  # 所在地区
   link = item.find_element_by_xpath('.//*[@class="Card--doubleCardWrapper--L2XFE73"]').get_attribute('href')  # 详情页面链接
   # print(title) # 注意.text和get_attribute()两个方法的使用
   tb = {
       "title": title,
       "price": price,
       "shopname": shopname,
       "location": location,
       "link": link
   }
   taobao.append(tb)
 
# 整合表头和表格数据构成dataframe表格对象
df = pandas.DataFrame(taobao, columns=["title", "price", "shopname", "location", "link"])
print(df)
df.to_excel('淘宝.xlsx')
 

3. 分析网络请求:有些动态网页通过Ajax或其他异步请求获取数据。我们可以通过分析网页的网络请求,直接发送相应的请求并获取数据。这需要我们了解网页使用的API接口、请求参数和响应格式。我们可以使用Java中的HTTP库(如HttpClient、OkHttp等)来发送网络请求,并解析响应数据。

无论使用哪种方法,爬取动态网页数据时需要注意以下事项:

- 网站的使用政策:确保你的爬虫遵守网站的使用政策和法律规定。一些网站可能会禁止爬虫访问或对频繁的请求进行限制。

- 休眠和限速:为了避免给服务器带来过大的负担,建议在请求之间添加适当的休眠时间,并限制爬虫的请求速率。

- 数据提取:动态网页通常会加载更多的内容,我们需要通过观察网页的行为和分析网页源代码来确定如何提取所需的数据。

- 异常处理:由于动态网页的复杂性,可能会出现各种异常情况,如页面加载失败、JavaScript错误等。在编写爬虫时,需要考虑这些异常情况,并进行适当的错误处理。

以上是一些常见的爬取动态网页数据的方法和注意事项。选择适合你需求的方法,并根据具体情况进行实施。

例如:百度翻译

import requests
 
# 获取百度翻译页面部分内容:动态加载的翻译结果
# url处理
url = 'https://fanyi.baidu.com/sug'
headers = {"User-Agent": "Chrome/117.0.0.0"}
data = {'kw': 'hello'}
 
# 请求url并获取响应内容  unicode_escape编码
response = requests.post(url, json=data, headers=headers)
 
response.encoding = "unicode_escape"
print(response.text)

储存数据

在网络爬虫中,存储数据是一个重要的环节,它使我们能够将从网页中提取的数据进行保存和管理。下面介绍几种常见的储存数据的方法:

1. 数据库:使用数据库是一种常见和有效的方式来存储爬取的数据。常用的数据库包括关系型数据库(如MySQL、PostgreSQL)和NoSQL数据库(如MongoDB、Redis)。通过将数据存储在数据库中,我们可以方便地进行查询、更新和管理数据。

2. 文件存储:如果数据量较小或者简单,可以选择将数据保存到文件中。常见的文件格式包括CSV、JSON、XML等。这种方式简单直接,适用于小规模的数据存储需求。

3. 分布式存储系统:对于大规模的数据存储需求,可以考虑使用分布式存储系统,如Hadoop、HBase、Cassandra等。这些系统可以处理大量的数据,并提供高可靠性和可伸缩性。

4. 内存数据库:如果对读写速度有较高要求,可以选择使用内存数据库,如Redis、Memcached等。内存数据库将数据存储在内存中,读写速度较快,适用于需要实时访问和处理数据的场景。

无论使用哪种方法,储存数据时需要考虑以下事项:

- 数据结构和模式:根据数据的特点和需求,设计合适的数据结构和数据库模式,以便有效地存储和检索数据。

- 数据清洗和处理:在存储数据之前,可能需要对数据进行清洗、转换和处理,以确保数据的质量和一致性。

- 数据安全性:对于敏感或重要的数据,需要考虑数据的安全性和保护措施,如加密、权限控制等。

- 数据备份和恢复:定期进行数据备份,并建立相应的恢复机制,以防止数据丢失或损坏。

选择适合你需求的数据存储方法,并根据具体情况进行实施。

测试连接:

from pymongo import MongoClient
 
try:
    # 准备前工作:连接-数据库-数据表
    client = MongoClient("localhost", 27017)  # 连接mongodb
    database = client["db_student"]  # 数据库存在,则直接访问db_student;否则创建db_student
    collection = database["user"]  # 集合存在,则直接访问user;否则创建user
 
    # 具体操作
    insertont = collection.insert_one({"name": "小明",
                                       "age": "19"})  # 创建时候一定要有数据,否则创建不成功
    insertont = collection.insert_one({"name": "小明", "age": "20"})  # 创建时候一定要有数据,否则创建不成功
    insertont = collection.insert_one({"name": "小红", "age": "19"})  # 创建时候一定要有数据,否则创建不成功
except Exception as error:
    print(error)

更多推荐