我有一个基于 selenium 的网络爬虫应用程序,可以监控100多种不同的医学出版物,还有更多的定期添加。这些出版物中的每一种都有不同的站点结构,所以我试图使网络爬虫尽可能通用和可重用(特别是因为这是供其他同事使用的)。对于每个Crawler,用户指定允许Crawler爬行的正则表达式URL模式的列表。从那里,爬虫程序将抓取找到的任何链接以及HTML的指定部分。这在下载大量内容方面非常有用,下载时间只需手动下载的一小部分。
我现在正在尝试找出一种基于特定页面的HTML生成定制报告的方法。例如,在抓取X站点时,导出一个JSON文件,该文件显示页面上的问题数、每个问题的名称、每个问题下的文章数,然后显示每篇文章的标题和作者姓名。我将使用的页面和测试用例是https://www.paediatrieschweiz.ch/zeitschriften/
我已经创建了一个列表理解,它可以产生我想要的输出。
url = "https://www.paediatrieschweiz.ch/zeitschriften/"
html = requests.get(url).content
soup = BeautifulSoup(html, 'html.parser')
report = [{
'Issue': (unit.find('p', {'class': 'section__spitzmarke'}).text).strip(),
'Articles': [{
'Title': ((article.find('h3', {'class': 'teaser__title'}).text).strip()),
'Author': ((article.find('p', {'class': 'teaser__authors'}).text).strip())
} for article in unit.find_all('article')]}
for unit in soup.find_all('div', {'class': 'section__inner'})]
JSON输出示例:
[
{
"Issue": "Paediatrica Vol. 33-3/2022",
"Articles": [
{
"Title": "Editorial",
"Author": "Daniela Kaiser, Florian Schaub"
},
{
"Title": "Interview mit Dr. med. Germann Clenin",
"Author": "Florian Schaub, Daniela Kaiser"
},
{
"Title": "Ern\u00e4hrung f\u00fcr sportliche Kinder und Jugendliche",
"Author": "Simone Reber"
},
{
"Title": "Diabetes und Sport",
"Author": "Paolo Tonella"
},
{
"Title": "Asthma und Belastung",
"Author": "Isabelle Rochat"
},
{
"Title": "Sport bei Kindern und Jugendlichen mit rheumatischer Erkrankung",
"Author": "Daniela Kaiser"
},
{
"Title": "H\u00e4mophilie und Sport",
"Author": "Denise Etzweiler, Manuela Albisetti"
},
{
"Title": "Apophysen - die Achillesferse junger Sportler",
"Author": "Florian Schaub"
},
{
"Title": "R\u00fcckenschmerzen bei Athleten im Wachstumsalter",
"Author": "Markus Renggli"
},
{
"Title": "COVID-19 bei jugendlichen AthletenInnen: Diagnose und Return to Sports",
"Author": "Susi Kriemler, Jannos Siaplaouras, Holger F\u00f6rster, Christine Joisten"
},
{
"Title": "Schutz von Kindern und Jugendlichen im Sport",
"Author": "Daniela Kaiser"
}
]
},
{
"Issue": "Paediatrica Vol. 33-2/2022",
"Articles": [
{
"Title": "Editorial",
"Author": "Caroline Schnider, Jean-Cristoph Caubet"
},
{
"Title": "Der prim\u00e4re Immundefekt \u2013 Ein praktischer Leitfaden f\u00fcr den Kinderarzt",
"Author": "Tiphaine Arlabosse, Katerina Theodoropoulou, Fabio Candotti"
},
{
"Title": "Arzneimittelallergien bei Kindern: was sollten Kinder\u00e4rzte wissen?",
"Author": "Felicitas Bellutti Enders, Mich\u00e8le Roth, Samuel Roethlisberger"
},
{
"Title": "Orale Immuntherapie bei Nahrungsmittelallergien im Kindesalter",
"Author": "Yannick Perrin, Caroline Roduit"
},
{
"Title": "Autoimmunit\u00e4t in der P\u00e4diatrie: \u00dcberlegungen der p\u00e4diatrischen Rheumatologie",
"Author": "Florence A. Aeschlimann, Raffaella Carlomagno"
但是,如果可能的话,我希望避免为每个单独的爬虫程序使用定制的Python语句或函数,因为每个爬虫程序需要不同的代码。每个爬虫都有自己的JSON配置文件,其中指定了起始URL、允许的URL模式、要下载的内容等。
我最初的想法是创建一个JSON配置来指定要抓取并存储在字典中的Beautiful Soup元素--不编写代码的同事将能够设置这些元素。我的想法是这样的.
{
"name": "Paedriactia",
"unit": {
"selector": {
"name": "div",
"attrs": {"class": "section__inner"},
"find_all": true
},
"items": {
"issue": {
"name": "p", "attrs": {"class": "section__spitzmarke"}, "get_text": true
}
},
"subunits": {
"articles": {
"selector": {
"name": "article",
"find_all": true
},
"items": {
"Title": {
"name": "h3",
"attrs": {"class": "teaser__title"},
"get_text": true
}
}
}
}
}
}
...以及一个能够根据配置解析HTML并生成JSON输出的Python函数。
然而,我完全不知道如何做到这一点,特别是在处理嵌套元素时。每次我试图靠自己来解决这个问题时,我都会把自己搞糊涂,结果又回到了最初的位置。
如果这一切都说得通,有谁会有任何建议或想法来处理这种美丽的汤配置?
我还精通用Beautiful Soup编写代码,因此我愿意为每个爬虫程序编写定制的Beautiful Soup函数和语句(甚至可以培训其他人这样做)。如果我采用这条路线,那么存储所有定制代码并将其导入最佳位置在哪里?我是否可以在每个Crawler文件夹中都有某种“parse.py”文件,并且只在需要时(即,当特定的Crawler运行时)导入它的功能?
如果对您有所帮助,下面是网络爬虫项目当前结构的一个示例:
1条答案
按热度按时间oalqel3c1#
在BeautifulSoup中,与使用
find_all
和find
相比,我更喜欢使用select
和select_one
来抓取嵌套元素。(如果您不习惯使用css选择器,我发现w3schools reference page对他们来说是一个很好的指南。)如果您定义了如下函数
你可以让你的数据结构和你的html结构一样嵌套[因为函数是递归的]……如果你出于某种原因想要这样做;但你也可以设置
maxDepth
来限制它的嵌套方式--如果你不想设置任何限制,你可以同时去掉maxDepth
和curDepth
以及涉及它们的任何部分。然后,您可以使您的配置文件类似于
[这里的
"isList": true
等同于您的"find_all": true
;您的“子单元”在这里也定义为“Items”-该函数可以根据结构/数据类型进行区分。]现在,您[在问题开头]显示的相同数据可以用
对于本例,您可以通过将
{"cssSelector": "a.teaser__inner", "targetAttr": "href"}
添加为...Articles.items.Link
来添加文章链接。还要注意,[因为函数开头设置了缺省值],
"Title": "h3.teaser__title"
与和
会是一样的