当前位置:首页 » 《我的小黑屋》 » 正文

Python →爬虫实践

6 人参与  2024年11月28日 12:01  分类 : 《我的小黑屋》  评论

点击全文阅读


爬取研究中心的书目

现在,想要把如下网站中的书目信息爬取出来。

案例一 耶鲁

Publications | Yale Law School

分析网页,如下图所示,需要爬取的页面,标签信息是“<p>”,所以用 items=soup.find_all("p")

代码如下:

import requestsfrom bs4 import BeautifulSoup as bsfrom openpyxl import Workbookurl="https://law.yale.edu/china-center/publications/recent-staff-publications"webfile=requests.get(url)webfile.encoding="utf-8"data=webfile.textsoup=bs(data,"html.parser")soup.prettify()items=soup.find_all("p")for i in items:    print(i.get_text())

完善代码如下:

import requestsfrom bs4 import BeautifulSoup as bsfrom openpyxl import Workbookimport rewb=Workbook()ws=wb.activewfile=open("bool.txt","w",encoding="utf-8")url="https://law.yale.edu/china-center/publications/recent-staff-publications"webfile=requests.get(url)webfile.encoding="utf-8"data=webfile.textsoup=bs(data,"html.parser")soup.prettify()items=soup.find_all("p")# 正则表达式匹配模式pattern1 = r'([^,\n“]+), “([^”]+),”\s*([^,\n]+)'pattern2 = r'([^,]+(?: and [^,]+)*), “([^”]+),”''''正则表达式匹配模式:([^,]+(?: and [^,]+)*):匹配作者名。这个模式匹配一个或多个名字,由“and”连接。[^,]+匹配一个或多个非逗号字符,(?: and [^,]+)*是一个非捕获组,匹配零个或多个“and”后跟一个或多个非逗号字符的模式。“([^”]+),”:匹配文章名。这个模式匹配引号内的任何字符,直到遇到闭合的引号和逗号。([^,\n“]+):匹配作者名。这个模式匹配一个或多个非逗号、换行符和左引号的字符序列。[^,\n“]是一个字符集,表示匹配除了逗号、换行符和左引号之外的任何字符。+表示匹配一个或多个这样的字符。“([^”]+),”:匹配文章名。这个模式匹配以左引号开始,以右引号结束的任何字符序列,并且确保文章名后面跟着一个逗号。([^,\n]+):匹配期刊名。这个模式匹配一个或多个非逗号和换行符的字符序列。'''for i in items:    info=i.get_text()    # 查找所有匹配项    matches = re.findall(pattern1, info)    if len(matches)>0:        print(matches)        for m in matches:            print(m,sep=",",file=wfile)wfile.close()

将txt文本导入excel即可。原因在于正则表达式中得到的列表中的信息,有的似乎是tuptle类型,导致openpyxl无法输入xlsx表格中。所以采用了txt文本方式。

基于以上出现的情况,再次优化代码,如下:

import requestsfrom bs4 import BeautifulSoup as bsfrom openpyxl import Workbookimport re wb=Workbook()ws=wb.active wfile=open("bool.txt","w",encoding="utf-8") url="https://law.yale.edu/china-center/publications/recent-staff-publications" webfile=requests.get(url)webfile.encoding="utf-8"data=webfile.text soup=bs(data,"html.parser")soup.prettify() items=soup.find_all("p")  # 正则表达式匹配模式pattern1 = r'([^\n“]+), “([^”]+),”\s*([^,\n]+)' #作者和文章名和期刊名,用括号将三者区分pattern2 = r'([^\n“]+), “([^”]+),”\s*([^,\n]+[)])'#parttern1缺少了最后的右括号,在这里补充上。[)]表示可供选择。   for i in items:    info=i.get_text()    # 查找所有匹配项    matches = re.findall(pattern2, info)    if len(matches)>0:        print(matches)         for m in matches:            mlist=[]#将元组的元素放到列表中,这样可以把列表的字符串输出到xlsx中            for k in m:                mlist.append(k)                print(k,sep=",",end=";",file=wfile)                        print("\n",file=wfile)##                print(type(k))            ws.append(mlist)                ##            print(m,sep=",",file=wfile)#注意,m是元组而不是字符串            #print(type(m)) wfile.close()wb.save("book2.xlsx") 

首先是完善了正则表达式:

'''
正则表达式匹配模式

[^,]+匹配一个或多个非逗号字符,
(?: and [^,]+)*是一个非捕获组,匹配零个或多个“and”后跟一个或多个非逗号字符的模式。

([^\n“]+):匹配作者名。这个模式匹配一个或多个非换行符和左引号的字符序列。

“([^”]+),”:匹配文章名。这个模式匹配引号内的任何字符,直到遇到闭合的引号和逗号。
[^,\n“]是一个字符集,表示匹配除了逗号、换行符和左引号之外的任何字符。+表示匹配一个或多个这样的字符。
“([^”]+),”:匹配文章名。这个模式匹配以左引号开始,以右引号结束的任何字符序列,并且确保文章名后面跟着一个逗号。
([^,\n]+):匹配期刊名。这个模式匹配一个或多个非逗号和换行符的字符序列。
'''

# 正则表达式匹配模式
pattern1 = r'([^\n“]+), “([^”]+),”\s*([^,\n]+)' #作者和文章名和期刊名,用括号将三者区分
pattern2 = r'([^\n“]+), “([^”]+),”\s*([^,\n]+[)])'
#parttern1缺少了最后的右括号,在这里补充上。[)]表示可供选择。

然后循环输出元组中的元素,放到列表中,从而将元组的元素转化为列表中的字符串。

最后,将不必要的信息清除,简洁代码如下:

import requestsfrom bs4 import BeautifulSoup as bsfrom openpyxl import Workbookimport re wb=Workbook()ws=wb.active wfile=open("bool.txt","w",encoding="utf-8") url="https://law.yale.edu/china-center/publications/recent-staff-publications" webfile=requests.get(url)webfile.encoding="utf-8"data=webfile.text soup=bs(data,"html.parser")soup.prettify() items=soup.find_all("p")  # 正则表达式匹配模式pattern2 = r'([^\n“]+), “([^”]+),”\s*([^,\n]+[)])'#作者和文章名和期刊名,用括号将三者区分for i in items:    info=i.get_text()    # 查找所有匹配项    matches = re.findall(pattern2, info)    if len(matches)>0:        print(matches)         for m in matches:            mlist=[]            for k in m:                mlist.append(k)                print(k,sep=",",end=";",file=wfile)                        ws.append(mlist)                wfile.close()wb.save("book2.xlsx") 

即可完成。

案例二 哈佛

爬取哈佛大学费正清中心出版书籍的信息时候,标签信息是class="article-container entry-content clear",所以用:item1=soup.find_all(attrs={"class":"article-container entry-content clear"})

所以,爬取代码如下:

 '''下面这段代码,爬取哈佛大学费正清中心出版书籍的信息'''import requestsfrom bs4 import BeautifulSoup as bsfrom openpyxl import Workbook wb=Workbook()ws=wb.active for page in range(1,9):    url=f'https://fairbank.fas.harvard.edu/research/publications/page/{page}/'     webFile=requests.get(url)    webFile.eocoding="utf-8"    data=webFile.text     soup=bs(data,'html.parser')    soup.prettify()     ##item1=soup.find_all(attrs={"class":"uagb-post__title"})#提取书本标题信息    ##for i in item1:    ##    print(i.get_text())    ##    ##    ##item2=soup.find_all(attrs={"class":"ast-excerpt-container ast-blog-single-element"})#提取书目介绍信息    ##for k in item2:    ##    print(k.get_text())     item3=soup.find_all(attrs={"class":"article-container entry-content clear"})#在网络页面中,找到的整个的文本    for m in item3:        info=m.get_text()        row1=info.split("\n")        row2=list(filter(lambda x:len(x)>1,row1))#过滤掉空字符串。        ws.append(row2)#worksheet中添加的是列表,然后把列表中的元素挨个放到了xlsx表格中。 wb.save("bool.xlsx") 

即可完成。

案例三 普林斯顿大学

观察该网站,标签信息是class="row search-result-wrapper"

其网站如下:


url="https://catalog.princeton.edu/?f%5Bformat%5D%5B%5D=Book&f%5Blocation%5D%5B%5D=East+Asian+Library&page=1&per_page=100"
 

于是写代码如下:

import requestsfrom bs4 import BeautifulSoup as bsfrom openpyxl import Workbookimport re wb=Workbook()ws=wb.activefor pageNum in  range(1,100):#提取一百页,共10000条书目的信息    url=f"https://catalog.princeton.edu/?f%5Bformat%5D%5B%5D=Book&f%5Blocation%5D%5B%5D=East+Asian+Library&page={pageNum}&per_page=100"         webfile=requests.get(url)    webfile.encoding="utf-8"    data=webfile.text         soup=bs(data,"html.parser")    soup.prettify()    item=soup.find_all(attrs={"class":"row search-result-wrapper"})    for m in item:        info=m.get_text()        row1=info.split("\n")        row2=list(filter(lambda x: len(x)>1,row1))        ws.append(row2)    print(pageNum,pageNum/100)wb.save("book3.xlsx") 

即可完成。

爬取公众号讲座图片信息

要下载网页中的图片,你可以使用Python的几个库来实现,比如`requests`来获取网页内容,以及`BeautifulSoup`来解析HTML并提取图片链接。以下是一个简单的示例代码,用于下载指定链接中的所有图片:

```python

案例一 讲座海報

图片对应的链接如下图所示:

网络链接如下:

<img data-imgfileid="512667600" data-ratio="1.413888888888889" data-s="300,640"

data-src="https://mmbiz.qpic.cn/mmbiz_png/sDanpDlI6ddB2YzJ9xdYcjOgl9ibvAlXPB0I3pTFpr20l3ewPROl850AXd8GoiaOtogzSglOMbKmhib0nxEtKbCMA/640?wx_fmt=png&amp;from=appmsg"

data-type="png"

data-w="1080"

style="vertical-align: middle; width: 479.6px !important; height: auto !important; visibility: visible !important;" data-original-style="vertical-align: middle;width: 100%;"

data-index="4" src="https://mmbiz.qpic.cn/mmbiz_png/sDanpDlI6ddB2YzJ9xdYcjOgl9ibvAlXPB0I3pTFpr20l3ewPROl850AXd8GoiaOtogzSglOMbKmhib0nxEtKbCMA/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" class="" _width="100%" crossorigin="anonymous" alt="图片" data-fail="0">

代码如下,

import osimport urllib.requestimport requestsfrom bs4 import BeautifulSoupimport re# 目标URLurl = 'https://mp.weixin.qq.com/s/A4Q1tVK6LnDa4vpJmMSIvQ'# 发送HTTP请求获取网页内容response = requests.get(url)response.encoding = 'utf-8'  # 根据网页编码设置,可能需要调整# 解析网页内容soup = BeautifulSoup(response.text, 'html.parser')# 找到所有图片标签img_tags = soup.find_all('img')# 创建一个目录来保存图片if not os.path.exists('lecture_images'):    os.makedirs('lecture_images')# 遍历所有图片标签并下载图片zhang=1for img in img_tags:    # 获取图片的URL,优先使用data-src属性    imageUrl = img.get('data-src', '') or img.get('src', '')    print(imageUrl)        imageName= os.path.join('lecture_images',str(zhang)+"-"+".png")#將图片存在了文件夹中。    urllib.request.urlretrieve(imageUrl,filename=imageName)    zhang+=1    

即可完成,在文件夹中爬取了相关的讲座图片。不过爬取的图片有些非讲座信息,需要进一步清除。


### 注意事项:

如果图片链接是动态加载的,那么使用requestsBeautifulSoup可能无法直接获取到图片链接,因为这些库只能处理静态内容。动态加载的内容通常是通过JavaScript在客户端执行后生成的。在这种情况下,你可以使用以下几种方法之一来处理:

1. 使用Selenium

Selenium是一个自动化测试工具,可以模拟浏览器行为,包括执行JavaScript。你可以使用Selenium来加载页面,然后提取动态加载的图片链接。

from selenium import webdriverimport timeimport requestsfrom bs4 import BeautifulSoupimport os# 设置Selenium驱动driver = webdriver.Chrome()  # 确保你已经安装了ChromeDriver# 访问网页driver.get('https://mp.weixin.qq.com/s/A4Q1tVK6LnDa4vpJmMSIvQ')# 等待页面加载完成time.sleep(5)  # 根据网络情况调整等待时间# 获取页面源码html = driver.page_source# 解析网页内容soup = BeautifulSoup(html, 'html.parser')# 找到所有图片标签img_tags = soup.find_all('img')# 创建一个目录来保存图片if not os.path.exists('lecture_images'):    os.makedirs('lecture_images')# 遍历所有图片标签并下载图片for img in img_tags:    # 获取图片的URL    img_url = img.get('src')    if img_url:        # 发送请求下载图片        img_response = requests.get(img_url)        if img_response.status_code == 200:            # 构造图片的保存路径            img_name = os.path.join('lecture_images', img_url.split('/')[-1])            # 保存图片            with open(img_name, 'wb') as f:                f.write(img_response.content)            print(f"图片已保存:{img_name}")        else:            print(f"图片下载失败:{img_url}")# 关闭浏览器driver.quit()

2. 使用Pyppeteer

Pyppeteer是一个Python库,它提供了一个高级的接口来控制无头版Chrome。它也是基于Chromium的,可以执行JavaScript。

import asynciofrom pyppeteer import launchfrom bs4 import BeautifulSoupimport requestsimport osasync def main():    browser = await launch(headless=True)    page = await browser.newPage()    await page.goto('https://mp.weixin.qq.com/s/A4Q1tVK6LnDa4vpJmMSIvQ')    await page.waitForSelector('img')  # 等待图片加载    html = await page.content()    soup = BeautifulSoup(html, 'html.parser')    img_tags = soup.find_all('img')    if not os.path.exists('lecture_images'):        os.makedirs('lecture_images')    for img in img_tags:        img_url = img.get('src')        if img_url:            img_response = requests.get(img_url)            if img_response.status_code == 200:                img_name = os.path.join('lecture_images', img_url.split('/')[-1])                with open(img_name, 'wb') as f:                    f.write(img_response.content)                print(f"图片已保存:{img_name}")            else:                print(f"图片下载失败:{img_url}")    await browser.close()asyncio.get_event_loop().run_until_complete(main())

即可完成。

一日一图

代码如下:

"""使用Python中的turtle模块绘制一个壮观的太阳系图是一个有趣且具有挑战性的任务"""import turtleimport math# 设置屏幕screen = turtle.Screen()screen.bgcolor("black")screen.title("Solar System")# 创建太阳sun = turtle.Turtle()sun.hideturtle()sun.penup()sun.goto(0, -200)sun.pendown()sun.color("yellow")sun.begin_fill()sun.circle(50)sun.end_fill()# 行星数据(名称,距离太阳的距离(单位:像素),大小(单位:像素))planets = [    ("Mercury", 35, 5),    ("Venus", 72, 10),    ("Earth", 98, 10),    ("Mars", 152, 7),    ("Jupiter", 279, 30),  # 简化大小,实际应更大    ("Saturn", 449, 25),   # 简化大小,实际应更大    # "Uranus" 和 "Neptune" 由于距离太远,在这个比例下可能无法很好地显示]# 绘制行星和轨道orbit_color = "gray"planet_color = ["gray", "yellow", "blue", "red", "orange", "gold", "lightblue"]  # 对应行星的颜色,实际应根据行星选择for i, (name, distance, size) in enumerate(planets):    # 绘制轨道    orbit_turtle = turtle.Turtle()    orbit_turtle.hideturtle()    orbit_turtle.speed(0)    orbit_turtle.penup()    orbit_turtle.goto(0, 0)    orbit_turtle.pendown()    orbit_turtle.color(orbit_color)    orbit_turtle.width(2)    orbit_turtle.circle(distance)    orbit_turtle.hideturtle()    # 绘制行星    planet_turtle = turtle.Turtle()    planet_turtle.hideturtle()    planet_turtle.speed(0)    planet_turtle.penup()    # 计算行星在轨道上的位置    angle = 360 * i / len(planets)  # 均匀分布行星    x = distance * math.cos(math.radians(angle))    y = distance * math.sin(math.radians(angle)) - 200  # 减去太阳的高度    planet_turtle.goto(x, y)    planet_turtle.pendown()    planet_turtle.color(planet_color[i % len(planet_color)])  # 循环使用颜色    planet_turtle.begin_fill()    planet_turtle.circle(size)    planet_turtle.end_fill()    planet_turtle.write(name, align="center", font=("Arial", 8, "normal"))    planet_turtle.hideturtle()# 隐藏turtle光标turtle.done()turtle.tracer(False)

图片如下:

即可完成。


点击全文阅读


本文链接:http://zhangshiyu.com/post/193301.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1