使用Python进行网络爬虫

197

我想从一个网站获取每日的日出/日落时间。使用Python可以爬取网页内容吗?需要用到哪些模块?是否有任何可用的教程?

你可以使用Python中的Web Scraping技术来获取网站的日出/日落时间。有很多模块可以用来进行网页解析和抓取,如BeautifulSoup、Scrapy和Requests等。你可以在互联网上找到许多关于这些模块的教程和示例代码。

6
Python有多种用于网络爬虫的选项。我在这里列举了一些选项,以回应一个类似的问题。链接在这里:http://stackoverflow.com/questions/2861/options-for-html-scraping/1970411#1970411 - filippo
为什么不直接使用Python标准库中内置的HTML解析器呢?对于如此简单且不频繁的任务(每天只需一次),我认为没有必要寻找其他工具。https://docs.python.org/2.7/library/htmlparser.html - ArtOfWarfare
希望这篇文章对于某些人来说是有用的。对于初学者来说,这是一个很好的教程。http://samranga.blogspot.com/2015/08/web-scraping-beginner-python.html 它使用了Python中的beautiful soup库进行网络爬虫。 - Samitha Chathuranga
对于未来的读者,你可能也想看看这个答案,它提供了两种不同的网页爬取方法,分别使用(1) Selenium 和 (2) BeautifulSoupRequests - Chris
10个回答

196

使用urllib2与优秀的BeautifulSoup库相结合:

import urllib2
from BeautifulSoup import BeautifulSoup
# or if you're using BeautifulSoup4:
# from bs4 import BeautifulSoup

soup = BeautifulSoup(urllib2.urlopen('http://example.com').read())

for row in soup('table', {'class': 'spad'})[0].tbody('tr'):
    tds = row('td')
    print tds[0].string, tds[1].string
    # will print date and sunrise

8
可以使用requests软件包来稍微简化这段代码,将第6行替换为:soup = BeautifulSoup(requests.get('http://example.com').text)。请注意,这句话的意思是不需要改变,只需用通俗易懂的方式表达出来即可。 - Chiara Coetzee
5
谢谢你的提示。在我写上面的片段时,请求包还不存在;-) - user235064
1
@DerrickCoetzee - 你的简化引发了一个MissingSchema错误(至少在我的安装中是这样)。这个可以工作:soup = BeautifulSoup(requests.get('http://example.com').text) - kmote
希望这篇文章对任何关注此事的人都有所帮助。对于初学者来说,这是一份良好的描述性教程。http://samranga.blogspot.com/2015/08/web-scraping-beginner-python.html它使用Python中的beautiful soup库进行网络爬虫。 - Samitha Chathuranga
1
请注意,urllib2Python3中不存在。另一篇帖子 - themefield
显示剩余3条评论

67

我强烈推荐Scrapy。

以下是删除的回答中的摘录:

  • Scrapy使用异步操作(基于Twisted)比Mechanize更快。
  • Scrapy在libxml2上具有更好和更快的(x)html解析支持。
  • Scrapy是一个成熟的框架,完全支持Unicode,处理重定向、gzip响应、奇怪的编码、集成http缓存等等。
  • 一旦你开始使用Scrapy,你可以在不到5分钟的时间内编写一个爬虫,下载图像、创建缩略图并直接将提取的数据导出为csv或json。

15
我没有注意到这个问题已经两年了,但我认为在这里提到Scrapy还是有必要的,以防其他人有同样的问题。请注意,这句话已经被翻译成中文。 - Sjaak Trekhaak
4
Scrapy是一个框架,因此它很糟糕并认为自己比你的项目更重要。它是一个框架,因为Twisted有可怕(不必要)的限制。 - user1244215
4
“它是一个框架,因为框架很好用。如果你不想将其用作框架,那么你完全可以将所有的代码塞进一个文件中。” - Blender
1
但它不支持Python 3.x。 - user636044

18

我将网页抓取的脚本整合到这个比特桶库中。

以下是适用于您情况的示例脚本:

from webscraping import download, xpath
D = download.Download()

html = D.get('http://example.com')
for row in xpath.search(html, '//table[@class="spad"]/tbody/tr'):
    cols = xpath.search(row, '/td')
    print 'Sunrise: %s, Sunset: %s' % (cols[1], cols[2])

输出:

Sunrise: 08:39, Sunset: 16:08
Sunrise: 08:39, Sunset: 16:09
Sunrise: 08:39, Sunset: 16:10
Sunrise: 08:40, Sunset: 16:10
Sunrise: 08:40, Sunset: 16:11
Sunrise: 08:40, Sunset: 16:12
Sunrise: 08:40, Sunset: 16:13

11

我强烈建议您查看pyquery。它使用类似于jquery(也称为css)的语法,对于那些来自这方面背景的人来说非常容易。

对于您的情况,应该是这样的:

from pyquery import *

html = PyQuery(url='http://www.example.com/')
trs = html('table.spad tbody tr')

for tr in trs:
  tds = tr.getchildren()
  print tds[1].text, tds[2].text

输出:

5:16 AM 9:28 PM
5:15 AM 9:30 PM
5:13 AM 9:31 PM
5:12 AM 9:33 PM
5:11 AM 9:34 PM
5:10 AM 9:35 PM
5:09 AM 9:37 PM

7
你可以使用urllib2来进行HTTP请求,然后你就可以得到网页内容。
你可以按照以下方式获取它:
import urllib2
response = urllib2.urlopen('http://example.com')
html = response.read()

Beautiful Soup 是一个 Python HTML 解析器,适用于屏幕抓取。

特别地,这里 是他们关于解析 HTML 文档的教程。

祝好运!


也许设置一个最大字节数限制是个好主意。response.read(100000000)或者其他什么方式,这样ISO的URL就不会把你的内存填满了。祝挖矿愉快。 - andrew pate

4
我会使用Scrapemark(用于查找URL - py2)和httlib2(下载图像 - py2+3)的组合。 scrapemark.py有500行代码,但使用正则表达式,所以可能不太快,未经过测试。
爬取您网站的示例:
import sys
from pprint import pprint
from scrapemark import scrape

pprint(scrape("""
    <table class="spad">
        <tbody>
            {*
                <tr>
                    <td>{{[].day}}</td>
                    <td>{{[].sunrise}}</td>
                    <td>{{[].sunset}}</td>
                    {# ... #}
                </tr>
            *}
        </tbody>
    </table>
""", url=sys.argv[1] ))

使用方法:

python2 sunscraper.py http://www.example.com/

结果:

[{'day': u'1. Dez 2012', 'sunrise': u'08:18', 'sunset': u'16:10'},
 {'day': u'2. Dez 2012', 'sunrise': u'08:19', 'sunset': u'16:10'},
 {'day': u'3. Dez 2012', 'sunrise': u'08:21', 'sunset': u'16:09'},
 {'day': u'4. Dez 2012', 'sunrise': u'08:22', 'sunset': u'16:09'},
 {'day': u'5. Dez 2012', 'sunrise': u'08:23', 'sunset': u'16:08'},
 {'day': u'6. Dez 2012', 'sunrise': u'08:25', 'sunset': u'16:08'},
 {'day': u'7. Dez 2012', 'sunrise': u'08:26', 'sunset': u'16:07'}]

1
使用CSS选择器使您的生活更轻松
我知道我来晚了,但我有一个不错的建议。
虽然已经建议使用BeautifulSoup,但我更喜欢使用CSS选择器来抓取HTML中的数据。
import urllib2
from bs4 import BeautifulSoup

main_url = "http://www.example.com"

main_page_html  = tryAgain(main_url)
main_page_soup = BeautifulSoup(main_page_html)

# Scrape all TDs from TRs inside Table
for tr in main_page_soup.select("table.class_of_table"):
   for td in tr.select("td#id"):
       print(td.text)
       # For acnhors inside TD
       print(td.select("a")[0].text)
       # Value of Href attribute
       print(td.select("a")[0]["href"])

# This is method that scrape URL and if it doesnt get scraped, waits for 20 seconds and then tries again. (I use it because my internet connection sometimes get disconnects)
def tryAgain(passed_url):
    try:
        page  = requests.get(passed_url,headers = random.choice(header), timeout = timeout_time).text
        return page
    except Exception:
        while 1:
            print("Trying again the URL:")
            print(passed_url)
            try:
                page  = requests.get(passed_url,headers = random.choice(header), timeout = timeout_time).text
                print("-------------------------------------")
                print("---- URL was successfully scraped ---")
                print("-------------------------------------")
                return page
            except Exception:
                time.sleep(20)
                continue 

1
如果我们想从任何特定类别中获取项目名称,则可以通过使用CSS选择器指定该类别的类名来实现:
import requests ; from bs4 import BeautifulSoup

soup = BeautifulSoup(requests.get('https://www.flipkart.com/').text, "lxml")
for link in soup.select('div._2kSfQ4'):
    print(link.text)

这是部分搜索结果:

Puma, USPA, Adidas & moreUp to 70% OffMen's Shoes
Shirts, T-Shirts...Under ₹599For Men
Nike, UCB, Adidas & moreUnder ₹999Men's Sandals, Slippers
Philips & moreStarting ₹99LED Bulbs & Emergency Lights

0

Python有很好的选项来爬取网页。最好的框架是scrapy。对于初学者来说可能会有一些棘手,因此在这里提供一些帮助。
1. 安装Python 3.5以上(低版本到2.7也可以)。
2. 在conda中创建环境(我已经完成了这个步骤)。
3. 在一个位置安装Scrapy并从那里运行。
4. Scrapy shell 将为您提供测试代码的交互界面。
5. Scrapy startproject projectname 将创建一个框架。
6. Scrapy genspider spidername 将创建一个蜘蛛。您可以创建任意数量的蜘蛛。在执行此操作时,请确保您位于项目目录内。


更简单的方法是使用requestsbeautiful soup。在开始之前,花一个小时的时间阅读文档,它将解决大部分疑问。BS4提供了广泛的解析器供您选择。使用user-agentsleep可以使爬取更容易。BS4返回一个bs.tag,因此请使用variable[0]。如果有js运行,则无法直接使用requests和bs4进行爬取。您可以获取API链接,然后解析JSON以获取所需信息,或尝试selenium


无论您是否使用Anaconda,在这里都完全不相关。创建虚拟环境基本上总是一个好主意,但您不需要conda来完成这个任务。 - tripleee

0
这是一个简单的网络爬虫,我使用了BeautifulSoup,并且我们将搜索所有类名为_3NFO0d的链接(锚点)。我使用了Flipkar.com,它是一个在线零售商店。
import requests
from bs4 import BeautifulSoup
def crawl_flipkart():
    url = 'https://www.flipkart.com/'
    source_code = requests.get(url)
    plain_text = source_code.text
    soup = BeautifulSoup(plain_text, "lxml")
    for link in soup.findAll('a', {'class': '_3NFO0d'}):
        href = link.get('href')
        print(href)

crawl_flipkart()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接