作业1
爬取前37条大学排名实验
- 首先点击链接进入网页,分析网页存储有排名、学校名称、省市、学校类型和总分的元素。分析得使用该网页使用自定义属性data-v-4645600d=""的tr元素进行作为包装。
- 观察该html文档树,发现tr元素下共有6个td子节点,其中,第一个td子节点中的div元素存放排名数据,第二个td子节点下的class="name-cn"的a元素中存放学校名称,第三、四、五节点分别存放省市、学校类型和总分。
- 根据分析结果编写findElement函数,用于寻找网页中所需的信息,尽可能实现精确定位,主要代码如下:
def findElement(html):
soup = BeautifulSoup(html, 'html.parser')
rows=[]
try:
#尽量精确查找
tr_elements=soup.select("table tbody[data-v-4645600d] tr[data-v-4645600d]")
for tr_element in tr_elements:
td_elements = tr_element.select("td[data-v-4645600d]")
No = td_elements[0].select_one("div.ranking").text.strip()
UnName=td_elements[1].select_one("a.name-cn").text.strip()
Province=td_elements[2].text.strip()
Type=td_elements[3].text.strip()
Score=td_elements[4].text.strip()
row=No+'-'+UnName+'-'+Province+'-'+Type+'-'+Score
rows.append(row)
except Exception as err:
print(err)
return rows
- 然后将读取到的数据存储到数据库中并提交保存
for row in rows:
row=row.split('-')
if(len(row)==5):
#实现插入数据
sql='insert into rankings (No,UnName,Province,Type,Score) values(?,?,?,?,?)'
try:
No=row[0]
UnName=row[1]
Province=row[2]
Type=row[3]
Score=row[4]
cursor.execute(sql,(No,UnName,Province,Type,Score))
except Exception as err:
print(err)
# 数据库提交保存
con.commit()
con.close()
- 但发现由于该网页一页仅显示30条数据,数据库中也仅存储了30条数据,根据要求爬取37条数据,因此需要实现翻页功能。使用selenium模拟点击翻页按钮进行爬取,代码如下:
url='http://www.shanghairanking.cn/rankings/bcur/2020'
# 创建浏览器实例
driver = webdriver.Edge()
driver.get(url) #打开网页
button_xpath = '//li[@title="下一页"]'
button = driver.find_element(By.XPATH, button_xpath)
button.click()
# 获取新页面的 HTML 内容
new_html = driver.page_source
# 解析新页面的数据
new_rows = findElement(new_html)
- 即可成功输出获取前37条的大学排名数据(长度寿险仅展示部分)

心得体会
- 爬取网页的时候一定要仔细分析页面html结构,如果元素选择器写错就无法实现对应功能
- 实现翻页功能的时候使用selenium,创建webdriver进行模拟用户点击翻页按钮
- 做实验的时候不能心急,要细心仔细防止代码出bug
作业2
爬取商城数据实验
- 准备爬取京东商城前60条书包的名称、价格、店铺数据,首先分析网页html结构,发现相关数据是被存放在class=”gl-warp clearfix”的ul中,其中有许多li元素,每个li元素中有一个商品的许多信息。分析所需信息,发现商品名称是被存放在class="p-name p-name-type-2"的div元素下target=”_blank”的a元素下的em元素中,价格被存放在class=”p-price”的div下的i元素中,店铺名被存放在class=”p-shop”的div元素下class="J_im_icon"的span元素中的target="_blank"的a元素中。分析完毕,编写程序核心代码如下:
#尽量精确查找
li_elements=soup.select('div[id="J_goodsList"] ul li')
for li_element in li_elements:
Name=li_element.select_one('div[class="p-name p-name-type-2"] a[target="_blank"] em')
if Name:
Name=Name.text.strip()
Name=Name.replace('\n', '')
Price=li_element.select_one("div[class='p-price'] i")
if Price:
Price=Price.text.strip()
Shop=li_element.select_one("div[class='p-shop'] span[class='J_im_icon'] a[target='_blank']")
if Shop:
Shop=Shop.text.strip()
if Name and Price and Shop:
row = Name + '-' + Price + '-' + Shop
rows.append(row)
- 但在实际运行时发现一个问题,如果直接复制输入搜索词“书包”后的网址进行爬取,获取到的html并不是实际有书包的那个页面,分析是因为京东网页内容是通过ajax动态渲染的,因此难以直接爬取静态数据,为解决此问题,使用webdriver模拟人输入“书包”并点击搜索按钮,然后爬取跳转后的网页,实现代码如下:
# 找到输入框并输入内容
input_element = driver.find_element(By.ID, "key") # 使用 id 属性定位输入框
input_element.send_keys(item) # 输入要搜索的文本
#点击按钮
button = driver.find_element(By.CSS_SELECTOR, '.button[aria-label="搜索"]')
button.click()
#动态等待页面成功加载
wait = WebDriverWait(driver, 10) # 最大等待时间为10秒
wait.until(EC.text_to_be_present_in_element((By.XPATH,
"//div[@class='crumbs-nav-item']/strong"), item))
html = driver.page_source
-
存储数据到数据库和展示数据库的代码与上面类似,在此就不再展示,运行代码后即可爬取书包的商品列表:

-
由于在程序中增加了input输入框,所有可以根据输入的需求爬取任意商品
心得体会
- 京东这类大型网站的反爬措施都会做的很好,合法爬取数据时要注意找到合适的方法绕过反爬措施,本人采用的方法是webdriver驱动后使用手机进行扫码登录,这样的做法有些取巧,但很好用。
作业3
爬取并下载给定页面的图片实验
- 创建findImg函数进行获取图像,由于是爬取页面中所有网页,因此无需分析类选择器,爬取页面所有的img元素并存储src即可,但需要分析图片存储的src,经过分析,img元素存储的src并不完整,如果要下载图像,需要在前面补上'https://xcb.fzu.edu.cn',寻找图片元素代码如下:
def findImg(html):
soup = BeautifulSoup(html, 'html.parser')
global rows
try:
img_elements=soup.select('img')
for img_element in img_elements:
#确保src存在
if img_element is not None and 'src' in img_element.attrs:
imgurl='https://xcb.fzu.edu.cn'+img_element['src']
rows.append(imgurl)
except Exception as err:
print(err)
return rows
- 存储所有元素的src后,调用自行创建的downloadImg函数把图片下载到本地
def downloadImg():
global rows
try:
folder_path = 'downloadImages'
if not os.path.exists(folder_path):
os.makedirs(folder_path)
# 本地保存文件
for index, img_url in enumerate(rows):
# 生成文件名
filename = f"image_{index}.jpg"
# 拼接完整的文件路径
file_path = os.path.join(folder_path, filename)
urllib.request.urlretrieve(img_url, file_path)
except Exception as err:
print(err)
- 最后执行findImg和downloadImg函数,即可成功下载指定网页中的所有图像,结果如下:

心得体会
- 在爬取图片时,一定要注意img元素的src属性,观察它的src是否完整,如果不完整要自己补充url链接才能正确下载。