
网页抓取是一种从网站中提取数据的技术。它允许我们从网页上收集信息并将其用于各种目的,例如数据分析、研究或构建应用程序。
在本文中,我们将探讨一个名为“GitHub主题抓取器”的Python项目,它利用网页抓取从GitHub主题页面提取信息,并检索每个主题的存储库名称和详细信息。
介绍
GitHub是一个广泛流行的托管和协作代码存储库的平台。它提供了一个名为“主题”的功能,允许用户根据特定主题或主题对存储库进行分类。GitHub主题抓取器项目自动化了这些主题的抓取过程,并检索相关的存储库信息。
项目概述
GitHub主题抓取器使用Python实现,并利用以下库:
requests:用于发送HTTP请求以检索网页的HTML内容。BeautifulSoup:用于解析HTML和从中提取数据的强大库。pandas:用于数据操作和分析的多功能库,用于将抓取的数据组织成结构化格式。
让我们深入了解代码,并了解项目的每个组件如何工作。
Python脚本
import requestsfrom bs4 import BeautifulSoupimport pandas as pd
上面的代码片段导入了三个库:requests、BeautifulSoup和pandas。
def topic_page_authentication(url): topics_url = url response = requests.get(topics_url) page_content = response.text doc = BeautifulSoup(page_content, 'html.parser') return doc
定义了一个名为topic_page_authentication的函数,它以URL作为参数。
以下是代码的分解:
1. topics_url = url:此行将提供的URL分配给变量topics_url。此URL表示我们要验证和检索其内容的网页。
2. response = requests.get(topics_url):此行使用requests.get()函数发送HTTP GET请求到topics_url并将响应存储在response变量中。此请求用于获取网页的HTML内容。
3. page_content = response.text:此行从响应对象中提取HTML内容,并将其分配给page_content变量。 response.text属性检索响应的文本内容。
- 4.
doc = BeautifulSoup(page_content, 'html.parser') - 此行使用
'html.parser'解析器解析page_content,从而创建一个可导航的对象,代表网页的HTML结构,从而创建一个名为doc的BeautifulSoup对象。
5. return doc:此行从函数返回BeautifulSoup对象doc。这意味着当调用topic_page_authentication函数时,它将返回解析的HTML内容作为BeautifulSoup对象。
此函数的目的是验证和检索由提供的URL指定的网页的HTML内容。它使用requests库发送HTTP GET请求检索响应内容,然后使用BeautifulSoup解析它以创建可导航对象,表示网页的HTML结构。
请注意,提供的代码片段处理网页身份验证和解析的初始步骤,但不执行任何特定的抓取或数据提取任务。
def topicSraper(doc): # Extract title title_class = 'f3 lh-condensed mb-0 mt-1 Link--primary' topic_title_tags = doc.find_all('p', {'class':title_class}) # Extract description description_class = 'f5 color-fg-muted mb-0 mt-1' topic_desc_tags = doc.find_all('p', {'class':description_class}) # Extract link link_class = 'no-underline flex-1 d-flex flex-column' topic_link_tags = doc.find_all('a',{'class':link_class}) #Extract all the topic names topic_titles = [] for tag in topic_title_tags: topic_titles.append(tag.text) #Extract the descrition text of the particular topic topic_description = [] for tag in topic_desc_tags: topic_description.append(tag.text.strip()) #Extract the urls of the particular topics topic_urls = [] base_url = "https://github.com" for tags in topic_link_tags: topic_urls.append(base_url + tags['href']) topics_dict = { 'Title':topic_titles, 'Description':topic_description, 'URL':topic_urls } topics_df = pd.DataFrame(topics_dict) return topics_df
定义了一个名为 topicScraper 的函数,该函数以一个 BeautifulSoup 对象 (doc) 作为参数。

以下是代码的详细说明:
1. title_class = 'f3 lh-condensed mb-0 mt-1 Link--primary': 此行定义了包含网页上主题标题的 HTML 元素的 CSS 类名称 (title_class)。
2. topic_title_tags = doc.find_all('p', {'class':title_class}): 此行使用 BeautifulSoup 对象的 find_all() 方法查找所有具有指定 CSS 类 (title_class) 的 HTML 元素 (<p>)。 它检索一个表示主题标题标签的 BeautifulSoup 标记对象列表。
3. description_class = 'f5 color-fg-muted mb-0 mt-1': 此行定义了包含网页上主题描述的 HTML 元素的 CSS 类名称 (description_class)。
4. topic_desc_tags = doc.find_all('p', {'class':description_class}): 此行使用 find_all() 方法查找所有具有指定 CSS 类 (description_class) 的 HTML 元素 (<p>)。 它检索一个表示主题描述标记的 BeautifulSoup 标记对象列表。
5. link_class = 'no-underline flex-1 d-flex flex-column': 此行定义了包含网页上主题链接的 HTML 元素的 CSS 类名称 (link_class)。
6. topic_link_tags = doc.find_all('a',{'class':link_class}): 此行使用 find_all() 方法查找所有具有指定 CSS 类 (link_class) 的 HTML 元素 (<a>)。 它检索一个表示主题链接标记的 BeautifulSoup 标记对象列表。
7. topic_titles = []: 此行初始化一个空列表,以存储提取的主题标题。
8. for tag in topic_title_tags: ...: 此循环遍历 topic_title_tags 列表,并将每个标记的文本内容附加到 topic_titles 列表中。
9. topic_description = []: 此行初始化一个空列表,以存储提取的主题描述。
10. for tag in topic_desc_tags: ...: 此循环遍历 topic_desc_tags 列表,并将每个标记的去除空格的文本内容附加到 topic_description 列表中。
11. topic_urls = []: 此行初始化一个空列表,以存储提取的主题 URL。
12. base_url = "https://github.com": 此行定义了网站的基本 URL。
13. for tags in topic_link_tags: ...: 此循环遍历 topic_link_tags 列表,并将每个标记的 URL (基本 URL + href 属性) 连接到 topic_urls 列表中。
14. topics_dict = {...}: 此块创建了一个包含提取数据的字典 (topics_dict): 主题标题、描述和 URL。
15. topics_df = pd.DataFrame(topics_dict): 此行将 topics_dict 字典转换为 pandas DataFrame,其中每个键都成为 DataFrame 中的一列。
16. return topics_df: 此行返回包含提取数据的 pandas DataFrame。
该函数的目的是从提供的BeautifulSoup对象(doc)中抓取和提取信息。它从网页上特定的HTML元素中检索主题标题、描述和URL,并将它们存储在一个pandas数据框中,以便进行进一步的分析或处理。
def topic_url_extractor(dataframe): url_lst = [] for i in range(len(dataframe)): topic_url = dataframe['URL'][i] url_lst.append(topic_url) return url_lst
定义了一个名为topic_url_extractor的函数,该函数将panda DataFrame(dataframe)作为参数。
以下是代码的详细说明:
1. url_lst = []:该行初始化一个空列表(url_lst),用于存储提取的URL。
2. for i in range(len(dataframe)): ...:该循环遍历DataFrame行的索引。
3. topic_url = dataframe['URL'][i]:此行检索数据框中当前行索引(i)的“URL”列的值。
4. url_lst.append(topic_url):此行将检索到的URL添加到url_lst列表中。
5. return url_lst:此行返回包含提取的URL的url_lst列表。
该函数的目的是从提供的DataFrame的“URL”列中提取URL。
它遍历DataFrame的每一行,检索每一行的URL值,并将其添加到一个列表中。最后,该函数返回提取的URL列表。
当您想要从DataFrame中提取URL进行进一步的处理或分析(如访问每个URL或对各个网页执行其他Web抓取)时,此函数可能非常有用。
def parse_star_count(stars_str): stars_str = stars_str.strip()[6:] if stars_str[-1] == 'k': stars_str = float(stars_str[:-1]) * 1000 return int(stars_str)
定义了一个名为parse_star_count的函数,该函数将字符串(stars_str)作为参数。
以下是代码的详细说明:
1. stars_str = stars_str.strip()[6:]:此行使用strip()方法从stars_str字符串中删除前导和尾随空格。然后从第6个字符开始切片该字符串,并将结果分配回stars_str。此行的目的是删除字符串中的任何不需要的字符或空格。
2. if stars_str[-1] == 'k': ...:此行检查stars_str的最后一个字符是否为“k”,表示星级计数以千为单位。
3. stars_str = float(stars_str[:-1]) * 1000:此行将字符串的数字部分(不包括“k”)转换为浮点数,然后乘以1000将其转换为实际的星级计数。
4. return int(stars_str):此行将stars_str转换为整数并返回它。
该函数的目的是将星级计数从字符串表示形式解析并转换为整数值。它处理星级计数以千为单位(“k”)的情况,通过将字符串的数字部分乘以1000来处理。该函数将解析的星级计数作为整数返回。
当您有以字符串表示的星级计数(例如“1.2k”表示1200颗星),并且需要将它们转换为数字值以进行进一步的分析或处理时,此函数可能非常有用。
def get_repo_info(h3_tags, star_tag): base_url = 'https://github.com' a_tags = h3_tags.find_all('a') username = a_tags[0].text.strip() repo_name = a_tags[1].text.strip() repo_url = base_url + a_tags[1]['href'] stars = parse_star_count(star_tag.text.strip()) return username, repo_name, stars, repo_url
定义了一个名为get_repo_info的函数,该函数接受两个参数:h3_tags和star_tag。
以下是代码的详细说明:
1. base_url = 'https://github.com':该行定义了GitHub网站的基本URL。
2. a_tags = h3_tags.find_all('a'):该行使用h3_tags对象的find_all()方法查找其中的所有HTML元素(<a>),并检索代表锚链接的BeautifulSoup标记对象的列表。
3. username = a_tags[0].text.strip():该行提取第一个锚链接标记(a_tags[0])的文本内容并将其分配给username变量。它还使用strip()方法删除任何前导或尾随空格。
4. repo_name = a_tags[1].text.strip():该行提取第二个锚链接标记(a_tags[1])的文本内容并将其分配给repo_name变量。它还使用strip()方法删除任何前导或尾随空格。
5. repo_url = base_url + a_tags[1]['href']:该行从第二个锚链接标记(a_tags[1])检索“href”属性的值,并将其与base_url连接起来形成存储库的完整URL。生成的URL分配给repo_url变量。
- 6.
stars = parse_star_count(star_tag.text.strip()) - 该行提取
star_tag对象的文本内容,删除任何前导或尾随空格,并将其作为参数传递给parse_star_count函数。该函数返回解析后的星级数量作为整数,分配给stars变量。
7. return username, repo_name, stars, repo_url:该行返回一个包含提取信息的元组:username、repo_name、stars和repo_url。
该函数的目的是从提供的h3_tags和star_tag对象中提取有关GitHub存储库的信息。它通过浏览和提取HTML结构中的特定元素来检索用户名、存储库名称、星级计数和存储库URL。然后,该函数将此信息作为元组返回。
当您想要从包含存储库列表的网页中提取存储库信息时,该函数可能会很有用,例如在爬取GitHub主题时。
def topic_information_scraper(topic_url): #页面身份验证 topic_doc = topic_page_authentication(topic_url) #提取名称 h3_class = 'f3 color-fg-muted text-normal lh-condensed' repo_tags = topic_doc.find_all('h3', {'class':h3_class}) #获取星标签 star_class = 'tooltipped tooltipped-s btn-sm btn BtnGroup-item color-bg-default' star_tags = topic_doc.find_all('a',{'class':star_class}) #获取主题信息 topic_repos_dict = { 'username': [], 'repo_name': [], 'stars': [], 'repo_url': [] } for i in range(len(repo_tags)): repo_info = get_repo_info(repo_tags[i], star_tags[i]) topic_repos_dict['username'].append(repo_info[0]) topic_repos_dict['repo_name'].append(repo_info[1]) topic_repos_dict['stars'].append(repo_info[2]) topic_repos_dict['repo_url'].append(repo_info[3]) return pd.DataFrame(topic_repos_dict)
定义了一个名为topic_information_scraper的函数,该函数以topic_url作为参数。
以下是代码的详细说明:
- 1.
topic_doc = topic_page_authentication(topic_url) - 该行调用
topic_page_authentication函数以验证并检索topic_url的HTML内容。解析的HTML内容分配给topic_doc变量。
2. h3_class = 'f3 color-fg-muted text-normal lh-condensed' :这行定义了 CSS 类名(h3_class),用于包含主题页面中存储库名称的 HTML 元素。
3. repo_tags = topic_doc.find_all('h3', {'class':h3_class}):这一行使用 topic_doc 对象的 find_all() 方法查找具有指定 CSS 类(h3_class)的所有 HTML 元素(<h3>),并检索代表存储库名称标记的 BeautifulSoup 标记对象列表。
4. star_class = 'tooltipped tooltipped-s btn-sm btn BtnGroup-item color-bg-default' :这行定义了 CSS 类名(star_class),用于包含主题页面中的星标计数的 HTML 元素。
5. star_tags = topic_doc.find_all('a',{'class':star_class}):这一行使用 find_all() 方法查找具有指定 CSS 类(star_class)的所有 HTML 元素(<a>),并检索代表星标计数标记的 BeautifulSoup 标记对象列表。
6. topic_repos_dict = {...} :此块创建了一个字典(topic_repos_dict),用于存储提取的存储库信息:用户名、存储库名称、星标计数和存储库 URL。
7. for i in range(len(repo_tags)): ... :此循环遍历 repo_tags 列表的索引,假设它与 star_tags 列表具有相同的长度。
8. repo_info = get_repo_info(repo_tags[i], star_tags[i]) :此行调用 get_repo_info 函数,以提取有关特定存储库的信息。它将当前的存储库名称标记(repo_tags[i])和星标计数标记(star_tags[i])作为参数。返回的信息分配给 repo_info 变量。
9. topic_repos_dict['username'].append(repo_info[0]) :此行将从 repo_info 中提取的用户名附加到 topic_repos_dict 中的“用户名”列表中。
10. topic_repos_dict['repo_name'].append(repo_info[1]) :此行将从 repo_info 中提取的存储库名称 repo_info 附加到 topic_repos_dict 中的“repo_name”列表中。
- 11.
topic_repos_dict['stars'].append(repo_info[2]) - 此行将从
repo_info中提取的星标计数repo_info附加到topic_repos_dict中的“stars”列表中。
12. topic_repos_dict['repo_url'].append(repo_info[3]) :此行将从 repo_info 中提取的存储库 URL 附加到 topic_repos_dict 中的“repo_url”列表中。
13. return pd.DataFrame(topic_repos_dict) :此行将 topic_repos_dict 字典转换为 pandas DataFrame,其中每个键成为 DataFrame 中的一列。生成的数据框包含提取的存储库信息。
此函数的目的是在 GitHub 上特定主题内抓取和提取存储库信息。它验证并检索主题页面的 HTML 内容,然后使用特定的 CSS 类名称提取存储库名称和星标计数。
它为每个存储库调用 get_repo_info 函数,以检索用户名、存储库名称、星标计数和存储库 URL。
提取的信息存储在字典中,然后转换为 pandas DataFrame,并由该函数返回。
if __name__ == "__main__": url = 'https://github.com/topics' topic_dataframe = topicSraper(topic_page_authentication(url)) topic_dataframe.to_csv('GitHubtopics.csv', index=None) # 根据主题创建其他 CSV 文件 url = topic_url_extractor(topic_dataframe) name = topic_dataframe['Title'] for i in range(len(topic_dataframe)): new_df = topic_information_scraper(url[i]) new_df.to_csv(f'GitHubTopic_CSV-Files/{name[i]}.csv', index=None)
代码段展示了脚本的主要执行流程。
以下是代码的详细说明:
1. if __name__ == "__main__": :这个条件语句检查脚本是否直接运行(而不是作为模块导入)。
2. url = 'https://github.com/topics' :这一行定义了GitHub主题页面的URL。
3. topic_dataframe = topicSraper(topic_page_authentication(url)) :这一行使用 topic_page_authentication 检索主题页面的HTML内容,然后将解析的HTML(doc)传递给topicSraper 函数。它将结果数据帧(topic_dataframe)分配给一个变量。
4. topic_dataframe.to_csv('GitHubtopics.csv', index=None) :这一行将topic_dataframe数据帧导出到名为“GitHubtopics.csv”的CSV文件中。参数index=None确保不包括行索引。
5. url = topic_url_extractor(topic_dataframe) :这一行调用topic_url_extractor函数,将topic_dataframe作为参数传递。它检索从数据帧中提取的URL列表(url)。
6. name = topic_dataframe['Title'] :这一行从topic_dataframe中检索“Title”列,并将其分配给变量name。
7. for i in range(len(topic_dataframe)): ... :此循环遍历topic_dataframe数据帧的索引。
8. new_df = topic_information_scraper(url[i]) :这一行调用topic_information_scraper函数,将URL(url[i])作为参数传递。它检索特定主题URL的存储库信息,并将其分配给new_df数据帧。
9. new_df.to_csv(f'GitHubTopic_CSV-Files/{name[i]}.csv', index=None) :这一行将new_df数据帧导出到CSV文件中。文件名使用f-string动态生成,包含主题名称(name[i])。参数index=None确保不包括行索引。
该脚本的目的是从GitHub主题页面中抓取和提取信息,并创建包含提取数据的CSV文件。它首先抓取主题页面,将提取的信息保存在“GitHubtopics.csv”中,然后继续使用提取的URL抓取单个主题页面。
对于每个主题,它创建一个名为该主题的新CSV文件,并在其中保存存储库信息。
可以直接执行此脚本以执行抓取并生成所需的CSV文件。
最终输出
url = 'https://github.com/topics'topic_dataframe = topicSraper(topic_page_authentication(url))topic_dataframe.to_csv('GitHubtopics.csv', index=None)
一旦运行此代码,它将生成一个名为“GitHubtopics.csv”的CSV文件,该文件看起来像这样,并且该CSV文件涵盖所有主题名称,其描述和URL。

url = topic_url_extractor(topic_dataframe) name = topic_dataframe['Title']for i in range(len(topic_dataframe)): new_df = topic_information_scraper(url[i]) new_df.to_csv(f'GitHubTopic_CSV-Files/{name[i]}.csv', index=None)
然后,此代码将执行,基于我们在之前的“GitHubtopics.csv”文件中保存的主题创建特定的csv文件。然后将这些CSV文件保存在名为“GitHubTopic_CSV-Files”的目录中,每个文件都有自己特定的主题名称。这些CSV文件看起来像这样。

这些主题csv文件存储了有关主题的一些信息,例如他们的用户名、仓库名称、仓库的星级和仓库的URL。

注意:网站的标签可能会更改,因此在运行此Python脚本之前,请根据网站检查标签。
完整脚本访问 >> https://github.com/PrajjwalSule21/GitHub-Topic-Scraper/blob/main/RepoScraper.py
