如何使用单个脚本从具有不同源代码的不同站点中获取数据?

问题描述 投票:1回答:2

我在python中编写了一个脚本来解析不同网站中可用的不同配置文件名称。每个链接都连接到其个人资料信息可用的每个人。在这一刻,我只想刮掉他们的个人资料名称。我在剧本中为三个不同的人提供了三个不同的链接。下面的脚本做得很好。我使用css选择器来从三个站点中删除配置文件信息。由于数量有限,我已经处理好了。但是,它可能有数百个链接。

现在,我的问题是:由于每个站点包含彼此非常不同的源代码,我如何通过包含单独的selectors,因为这些站点选择器已知,我可以使用单个脚本从这些站点获取所有配置文件名称对我来说?如果链接数百个怎么办?

以下是我为了获取配置文件名称所写的内容(这里做得很好):

import requests 
from bs4 import BeautifulSoup

links = {
"https://www.paulweiss.com/professionals/associates/robert-j-agar",
"http://www.cadwalader.com/index.php?/professionals/matthew-lefkowitz",
"https://www.kirkland.com/sitecontent.cfm?contentID=220&itemID=12061"
}
for link in links:
    res = requests.get(link)
    soup = BeautifulSoup(res.text,"lxml")
    for item in soup.select("#leftnav,.article,.main-content-container"):
        pro_name = item.select(".page-hdr h1,b.hidepf,.bioBreadcrumb span")[0].text
        print(pro_name)

输出:

Robert J Agar
Matthew Lefkowitz 
Mark Adler
python python-3.x web-scraping
2个回答
2
投票

一般而言,如果可能的话,在任意站点上可靠地覆盖概要文件名称的所有可能的任意位置将是非常困难的。主要问题是您无法预测目标网站上的HTML布局。

解决问题的一种可能的替代方法是从HTML解析切换到自然语言处理和Named Entity Recognition in particular

几乎没有工具可供选择 - 来自StanfordNERTaggernltk等的spacy

以下是使用nltk的示例(this answer应该有助于设置):

import nltk
import requests
from bs4 import BeautifulSoup

from nltk.tag.stanford import StanfordNERTagger


st = StanfordNERTagger('stanford-ner/english.all.3class.distsim.crf.ser.gz', 'stanford-ner/stanford-ner.jar')


links = {
    "https://www.paulweiss.com/professionals/associates/robert-j-agar",
    "http://www.cadwalader.com/index.php?/professionals/matthew-lefkowitz",
    "https://www.kirkland.com/sitecontent.cfm?contentID=220&itemID=12061"
}
for link in links:
    res = requests.get(link)
    soup = BeautifulSoup(res.text,"lxml")
    text = soup.body.get_text()

    for sent in nltk.sent_tokenize(text):
        tokens = nltk.tokenize.word_tokenize(sent)
        tags = st.tag(tokens)
        for tag in tags:
            if tag[1] == 'PERSON':
                print(tag)
    print("----------")

现在,这将提取人名,但也会有很多噪音:

('Mark', 'PERSON')
('Adler', 'PERSON')
('Ellis', 'PERSON')
('Mark', 'PERSON')
('Adler', 'PERSON')
('J.D.', 'PERSON')
('Mark', 'PERSON')
('Adler', 'PERSON')
('Kirkland', 'PERSON')
('Mark', 'PERSON')
----------
('PAUL', 'PERSON')
('Agar', 'PERSON')
('Robert', 'PERSON')
...
('Paul', 'PERSON')
('Weiss', 'PERSON')
('Rifkind', 'PERSON')
----------
('Bono', 'PERSON')
('Bono', 'PERSON')
('ProjectsPro', 'PERSON')
...
('Jason', 'PERSON')
('Schwartz', 'PERSON')
('Jodi', 'PERSON')
('Avergun', 'PERSON')
('Top', 'PERSON')
----------

造成这种噪音的原因之一是我们正在解析网页的body文本,当然,这些文本包含许多不相关的信息。

整个命名实体识别问题非常有趣,还有很多其他技术,比如使用word2vec进行进一步分析:

深入学习的想法也在那里,仅举几例:


1
投票

您正在询问如何扩展以抓取具有不同HTML布局的大量网站。

您已经有三个(link,pro_name)元组,以及三个相关CSS选择器的分离,以及从文本中提取pro_name的普通r'。*'正则表达式访问器。识别相关的选择器和正则表达式是缩放问题。您希望远离硬编码选择器,将它们放在某种数据存储区中。

所以你拥有的代码非常适合N = 3。这是您要编写的代码,用于处理任意N:“给定包含pro_name的HTML文档,选择器+访问器的哪个组合将可靠地提取该pro_name?”。要验证此类输出,您需要使用其他已知的pro_names来测试来自同一站点的一个或多个链接。就此而言,您需要验证重复访问相同链接会产生相同的结果,因为某些网站会在浏览器刷新时更改文档详细信息。

让selector_list成为CSS选择器bs4将用于将DOM从根节点导航到叶节点。在你的问题中,你基本上发布了selector_list [-1],这是三个这样的列表的最终条目。

在培训时,首先输出selector_list,char_offset,word_offset和样板文件,其中样板文本可以从多个站点页面中挖掘出来并将合并到正则表达式中。在发布的代码中,字符和单词的偏移量为“0”,表示空站点样板“”。然后,对于接受文本加上这四个参数的一些访问函数族,输出候选访问器(您的代码采用从字符偏移零开始的“接受r'。*'”),观察它们发出正确的pro_name。根据其他(document,pro_name)输入验证访问者。

在推理时,映射到访问器的链接,并使用它从生产中的HTML文档中提取pro_name。

© www.soinside.com 2019 - 2024. All rights reserved.