在这个示例中,我们将演示如何爬取湖北武汉东湖的旅行轨迹数据。请注意,这只是一个示例,您可以根据自己的需求来修改爬虫设置。
首先,打开浏览器并访问两步路官网。然后,使用开发者工具,切换到 “网络” 或 “Network” 选项卡,并选择 “XHR”。在这里,我们发现网页只有4条数据。逐条查找这些请求,以确定预览的网页中的内容包含了我们所需的旅行轨迹数据。从中确定目标网页名称。
在开发者工具的 “标头” 栏中,查找网页正式访问的URL链接,这将是我们在爬虫中使用的链接。
在开发者工具的 “负载” 栏中,查找网页爬取的设定参数,这些参数在后续爬虫代码中需要使用。
根据上述确定的正式URL链接和设定参数,创建Python代码来访问网页内容。示例代码如下:
def send_http_post_request(url, page_number):
"""
发送HTTP POST请求并获取数据。
:param url: 目标URL
:param page_number: 页码
:return: 请求响应的文本内容,如果请求失败则返回None
"""
# 设置请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.43'
}
# 构建请求参数
data = {
'pageNumber': page_number,
'sortType': 0,
'areaId': '15728',
'parentId': '15727',
}
# 设置请求的cookie信息
cookies = {}
co_data = '你的cookies '
for i in co_data.split('; '):
cookies[i.split('=')[0]] = i.split('=')[1]
try:
# 发送POST请求
response = requests.post(url=url, headers=headers, cookies=cookies, data=data, timeout=10)
# 检查响应状态码
if response.status_code == 200:
return response.text
else:
print(f"Failed to fetch data for page {page_number}. Status code: {response.status_code}")
return None
except requests.exceptions.RequestException as e:
print(f"Error while fetching data for page {page_number}: {e}")
return None
代码中使用了Beautiful Soup的各种方法来定位、提取和处理HTML中的特定元素和文本内容,以构建包含所需数据的列表。以下是一个示例,提取的信息包括目标链接、轨迹名称、出行方式、里程、用户名称、上传时间、行程安排、点赞、下载和收藏。
def parse_html_data(page, data):
"""
解析HTML数据,提取所需信息并存储到列表中。
:param data: HTML文本数据
:return: 存储解析数据的列表
"""
page_counter = 1
parsed_data = []
soup = BeautifulSoup(data, "html.parser")
target_divs = soup.find_all('div', class_='guiji_discription')
for target_div in target_divs:
# 构建轨迹id
trajectory_id = (page - 1) * 10 + page_counter
# 构建轨迹URL
url_link_1 = 'https://www.2bulu.com'
url_link_2 = target_div.find('a')['href']
target_url = url_link_1 + url_link_2
# 查找轨迹名称
target_p = target_div.find('p', class_='guiji_name').get_text()
text_list = [item.strip() for item in target_p.split('\n') if item.strip()]
trajectory_name = text_list[-1]
# 查找骑行方式
original_travel_mode = target_div.find('p', class_='guiji_name').span.get_text().strip()
travel_mode = re.sub(r'[^\u4e00-\u9fa5]+', '', original_travel_mode)
# 查找里程数
original_mileage = target_div.find('span', class_='s1').get_text(strip=True)
mileage = [item.strip() for item in original_mileage.split('\n')][0]
# 查找作者
user_name = target_div.find('span', class_='s7').a.get_text(strip=True)
# 查找上传时间
original_upload_time = target_div.find('span', class_='s7').get_text()
upload_time = [item.strip() for item in original_upload_time.split('\n') if item.strip()][-1]
# 查找行程
original_itinerary = target_div.find_all('li')[1].get_text(strip=True)
itinerary = re.sub(r'\s+', '', original_itinerary)
# 查找点赞数
original_like = target_div.find('span', class_='s3').get_text(strip=True)
like = re.findall(r'\d+\.\d+|\d+', original_like)[0]
# 查找下载数
original_download = target_div.find('span', class_='s4').get_text(strip=True)
download = re.findall(r'\d+\.\d+|\d+', original_download)[0]
# 查找收藏数
original_bookmark = target_div.find('span', class_='s5').get_text(strip=True)
bookmark = re.findall(r'\d+\.\d+|\d+', original_bookmark)[0]
# 构建临时列表,存储每条轨迹的数据
temporary_list = [trajectory_id, target_url, trajectory
_name, travel_mode, mileage, user_name, upload_time,
itinerary,
like, download, bookmark]
parsed_data.append(temporary_list)
page_counter += 1
print(temporary_list)
return parsed_data
如果您需要爬取多个页面或需要登录后的Cookie来继续爬取,在已经登录的网站中找到网页的cookie通常需要使用浏览器的开发者工具。您可以按照下面步骤来获取所需的Cookie信息。
使用浏览器登录:
首先,使用您的浏览器登录到目标网站。确保您已经登录成功并可以访问需要的页面。
打开开发者工具:
打开浏览器的开发者工具。不同浏览器的打开方式略有不同,通常可以通过按下F12
键或Ctrl + Shift + I
(在Windows/Linux系统下)或Cmd + Option + I
(在Mac系统下)来打开开发者工具。
选择选项卡:
在开发者工具中,通常有一个名为"XHR"的选项卡(具体名称可能会因浏览器而异),请点击它。
查看Cookie:
在选项卡目标网页的“表头”中,可以找到"Cookie"或"Cookies"。
整体代码如下所示:
import re
import csv
import time
import random
import requests
from bs4 import BeautifulSoup
def send_http_post_request(url, page_number):
"""
发送HTTP POST请求并获取数据。
:param url: 目标URL
:param page_number: 页码
:return: 请求响应的文本内容,如果请求失败则返回None
"""
# 设置请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.43'
}
# 构建请求参数
data = {
'pageNumber': page_number,
'sortType': 2,
'trackType': 8, # 步行
# 'trackType': 2, # 骑行
'areaId': '15728',
'parentId': '15727',
}
# 设置请求的cookie信息
cookies = {}
co_data = 'JSESSIONID=5F93F98CB090214EA8B1E93BA41E4DB6-n1; Hm_lvt_bed4e06c9c336e6fec0b7611aeefdc73=1695689237,1695747748,1695780063,1695800227; token=0B2v0TDzBHhqSk1PUbZKhA%3D%3D; utoken=GQOyz6peAECco5JhVMIdXKmFdvFKOs%2Bs; Hm_lpvt_bed4e06c9c336e6fec0b7611aeefdc73=1695800273'
for i in co_data.split('; '):
cookies[i.split('=')[0]] = i.split('=')[1]
try:
# 发送POST请求
response = requests.post(url=url, headers=headers, cookies=cookies, data=data, timeout=10)
# 检查响应状态码
if response.status_code == 200:
return response.text
else:
print(f"Failed to fetch data for page {page_number}. Status code: {response.status_code}")
return None
except Exception as e:
print(f"Error while fetching data for page {page_number}: {e}")
return None
def parse_html_data(page, data):
"""
解析HTML数据,提取所需信息并存储到列表中。
:param data: HTML文本数据
:return: 存储解析数据的列表
"""
page_counter = 1
parsed_data = []
soup = BeautifulSoup(data, "html.parser")
target_divs = soup.find_all('div', class_='guiji_discription')
for target_div in target_divs:
# 构建轨迹id
trajectory_id = (page - 1) * 10 + page_counter
# 构建轨迹URL
url_link_1 = 'https://www.2bulu.com'
url_link_2 = target_div.find('a')['href']
target_url = url_link_1 + url_link_2
# 查找轨迹名称
target_p = target_div.find('p', class_='guiji_name').get_text()
text_list = [item.strip() for item in target_p.split('\n') if item.strip()]
trajectory_name = text_list[-1]
# 查找骑行方式
original_travel_mode = target_div.find('p', class_='guiji_name').span.get_text().strip()
travel_mode = re.sub(r'[^\u4e00-\u9fa5]+', '', original_travel_mode)
# 查找里程数
original_mileage = target_div.find('span', class_='s1').get_text(strip=True)
mileage = [item.strip() for item in original_mileage.split('\n')][0]
# 查找作者
user_name = target_div.find('span', class_='s7').a.get_text(strip=True)
# 查找上传时间
original_upload_time = target_div.find('span', class_='s7').get_text()
upload_time = [item.strip() for item in original_upload_time.split('\n') if item.strip()][-1]
# 查找行程
original_itinerary = target_div.find_all('li')[1].get_text(strip=True)
itinerary = re.sub(r'\s+', '', original_itinerary)
# 查找点赞数
original_like = target_div.find('span', class_='s3').get_text(strip=True)
like = re.findall(r'\d+\.\d+|\d+', original_like)[0]
# 查找下载数
original_download = target_div.find('span', class_='s4').get_text(strip=True)
download = re.findall(r'\d+\.\d+|\d+', original_download)[0]
# 查找收藏数
original_bookmark = target_div.find('span', class_='s5').get_text(strip=True)
bookmark = re.findall(r'\d+\.\d+|\d+', original_bookmark)[0]
# 构建临时列表,存储每条轨迹的数据
temporary_list = [trajectory_id, target_url, trajectory_name, travel_mode, mileage, user_name, upload_time,
itinerary,
like, download, bookmark]
parsed_data.append(temporary_list)
page_counter += 1
print(temporary_list)
return parsed_data
def write_data_to_csv(csv_path, header, data):
"""
将数据列表写入CSV文件。
:param csv_path: CSV文件路径
:param header: CSV文件的列标题
:param data: 要写入CSV的数据列表
"""
with open(csv_path, 'w', encoding='utf-8-sig', newline='') as f:
writer = csv.writer(f)
writer.writerow(header)
writer.writerows(data)
def random_delay(min_delay, max_delay):
"""
随机延时函数,生成指定范围内的随机延时时间。
:param min_delay: 最小延时(秒)
:param max_delay: 最大延时(秒)
"""
delay = random.uniform(min_delay, max_delay)
time.sleep(delay)
def main():
url = 'https://www.2bulu.com/track/track_search_result.htm'
csv_header = ['trajectory_id', 'target_url', 'trajectory_name',
'travel_mode', 'mileage', 'user_name', 'upload_time', 'itinerary',
'like', 'download', 'bookmark']
parsed_data = []
start_page = 1
end_page = 5 # 增加了一个示例值,可以根据需求更改
for page_number in range(start_page, end_page + 1):
data = send_http_post_request(url=url, page_number=page_number)
if len(data) <= 150:
time.sleep(120)
parsed_data.extend(parse_html_data(page=page_number, data=data))
# 随机访问时间,反爬
random_delay(min_delay=5, max_delay=10)
csv_file_path = str(start_page) + '_' + str(int(parsed_data[-1][0] / 10)) + "_output.csv"
write_data_to_csv(csv_path=csv_file_path, header=csv_header, data=parsed_data)
print('CSV导出完成。')
if __name__ == "__main__":
main()
这是一个完整的示例,演示了如何爬取湖北武汉东湖的旅行轨迹数据。请根据您的实际需求和网站结构进行适当的修改和扩展。
术语/函数 | 解释 |
---|---|
HTTP POST请求 | 发送HTTP POST请求并获取数据。 |
BeautifulSoup | 用于解析HTML数据,提取所需信息的Python库。 |
requests | 用于发送HTTP请求的Python库。 |
cookies | 存储在浏览器中的网站数据,通常用于身份验证和状态跟踪。 |
User-Agent | HTTP请求头中的字段,标识客户端应用程序的类型和版本。 |
re | Python的正则表达式库,用于文本匹配和处理。 |
page_number | 页码,用于指示要爬取的页面编号。 |
URL链接 | 统一资源定位符,用于标识互联网上的资源位置。 |
如果这对您有所帮助,希望点赞支持一下作者!
点击查看原文