使用request和re爬取豆瓣250排行榜信息

1.1 请求

请求,也就是由客户端发出,可以分成4部分:请求方法、请求的网址、请求头、请求体。
常见的请求方法有两种:GET和POST。
在浏览器里直接输入URL然后回车,这就发起了一个GET请求,请求的参数会直接包含到URL里。比如百度搜索时间,就是一个GET请求,对应链接:https://www.baidu.com/s?wd=时间 , 参数wd就是要搜索的关键字。POST请求多数用在表单的提交,也就是需要登录的时候,输入账号密码,点击“登录”,就会发起一个POST请求。

  • GET和POST的区别:
  • GET请求的参数会包含在URL里,数据可以在URL里看到,但是POST请求的URL不会包含数据,数据都是通过表单形式传输,会包含在请求体中。
  • GET请求提交的数据最多1024字节,POST方式没有限制。
向百度发起get请求,并打印返回结果
import requests 
r = requests.get('https://www.baidu.com')
print(type(r)
print(r.status_code)
print(r.text)
返回结果如下图

get请求返回结果
可以看到返回了状态码是200 以及网页的源码

断开网络再请求

ConnectionError: HTTPSConnectionPool(host='www.baidu.com', port=443): Max retries exceeded with url: /?name=germey&age=22 (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x00000286A1D56A90>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed',))

什么是请求头,如何添加请求头

请求头,用来说明服务器要使用的附加信息,比较重要的信息有Cookie、Referer、User-Agent等。

  • Host:用于指定请求资源的主机IP和端口号
  • Cookie:它的主要功能是维持当前访问会话。例如我们输入用户名和密码成功登陆某个网站,服务器会用会话保存登录状态信息,后面再刷新或请求站点内其他页面时,会发现都是登录状态,这就是Cookie的作用。
  • Referer:用来识别这个请求是从哪里发来的,服务器可以拿到这个信息并做想要的处理,如做来源统计、防盗链处理等。
  • User-Agent:简称UA,它是一个特殊的字符串头,可以使服务器识别客户使用的操作系统及版本、浏览器及版本等信息。通常在写爬虫时要加上这个信息,伪装成浏览器,如果不加可能会被反爬。

所以,请求头是请求的重要组成部分,写爬虫的时候,多数情况下需要设置请求头。
如果要添加请求头信息,只需要传递一个dict就可以了。

>>> data = {
					'name':'Ying'
		}
		r = requests.get('http://httpbin.org/get',parms=data)
		print(r.text)

返回结果

1.2 正则表达式

正则表达式是一个处理字符串非常强大的一个工具,它有自己的语法结构,学好这玩楞,实现字符串的检索、替换、匹配验证那就是分分钟的事情了。

常用的匹配规则
\w匹配字母、数字及下划线
\W匹配不是字母、数字及下划线
\s匹配任意空白字符串,等价于[\t\n\r\f]
\d匹配任意数字,等价于[0-9]
·匹配任意字符,除了换位符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符
*匹配0个或多个表达式
匹配0个或1个前面的正则表达式
[^…]匹配不在[ ]中的字符,比如[^abc]匹配除了a、b、c之外的字符
{n}精确匹配n个前面的表达式
{n,m}匹配n到m次由前面正则表达式定义的片段,贪婪方式

需要注意的两个模式:
贪婪模式:(.)
非贪婪模式: ( .
?)

1.3 爬取豆瓣电影250排行榜信息

使用requests和re爬取https://movie.douban.com/top250里的内容,要求抓取名次、影片名称、年份、导演等字段。

1.3.1 抓取分析

先瞧一瞧目标站点,可以看到一页是给出25个电影信息一共10页。还有就是到第二页是时候网址里的start=25,第三页就是start=50,一共10页,每一页的URL规律也就是:https://movie.douban.com/top250?start=?&filter=
?处是数字,从0开始依次增加25,所以获取排行榜信息,只需要分开访问10次,10次的start参数依次设置成0、25、50…225就可以了,在获取不同页面之后,再用正则表达式提取相关信息,就可以得到需要的信息了。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1.3.2 抓取首页

接下来进行代码实现。第一步,先抓取第一页的内容。emmm 定义一个get_one_page()方法,给它传入url参数。然后返回页面结果。

def get_one_page(url):
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
    }
    response = requests.get(url,headers=headers)
    return response.text
def main():
    url = 'https://movie.douban.com/top250?start=0'
    html = get_one_page(url)
    print(html)
main()

运行之后,就可以成功的获取第一页的源代码了。获取源代码之后开始解析页面,提取目标信息。

1.3.3 正则提取

开始解析网页提取信息

import re
def parse_one_page(html):
    pattern = re.compile('<li>.*?<em class="">(\d+)</em>.*?info">.*?title">(.*?)</span>.*?</div>', re.S)
    items = re.findall(pattern, html)
    for item in items:
        print(item)

我们要写匹配的正则表达式,()内的内容是我们要获取的,然后使用findall方法获取所有匹配的字符串。这里获取的是电影排名和名称。
完整的正则表达式为

<li>.*?<em class="">(\d+)</em>.*?info">.*?title">(.*?)</span>.*?<p class="">.*?导演:(.*?)&nbsp;&nbsp;&nbsp;(.*?)<br>.*?(\d+)&nbsp;/&nbsp;(.*?)&nbsp;/&nbsp;(.*?)\n.*?</p>.*?<span class="rating_num" property="v:average">(.*?)</span>.*?content="10.0"></span>.*?<span>(\d+)人评价</span>.*?</div>

爬取结果

在这里插入图片描述
emm顺便给把这些信息保存到本地

    with open('result.txt', 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, ensure_ascii=False)+'\n')
        f.close()

最后整合一下代码

import json
import requests
import re
import time

#for i in range(10):
    #start = i*25
    #url = 'https://movie.douban.com/top250?start='+str(start)
    #print(url)

def get_one_page(url):
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
    }
    response = requests.get(url,headers=headers)
    if response.status_code == 200:
        return response.text
def parse_one_page(html):
    pattern = re.compile(
        '<li>.*?<em class="">(\d+)</em>.*?info">.*?title">(.*?)</span>.*?<p class="">.*?导演:(.*?)&nbsp;&nbsp;&nbsp;(.*?)<br>.*?(\d+)&nbsp;/&nbsp;(.*?)&nbsp;/&nbsp;(.*?)\n.*?</p>.*?<span class="rating_num" property="v:average">(.*?)</span>.*?content="10.0"></span>.*?<span>(\d+)人评价</span>.*?</div>',re.S
    )
    items = re.findall(pattern,html)
    for item in items:
        yield {
            'index': item[0],
            'title': item[1],
            'director': item[2],
            'actor': item[3],
            'release_time': item[4],
            'location': item[5],
            'label': item[6],
            'score': item[7],
            'users': item[8]
        }
    #print(items)
def write_to_file(content):
    with open('result.txt', 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, ensure_ascii=False)+'\n')
        f.close()
def main(start):
    url = 'https://movie.douban.com/top250?start='+str(start)
    html = get_one_page(url)
    for item in parse_one_page(html):
        print(item)
        write_to_file(item)
    #print(html)
if __name__ == '__main__':
    for i in range(10):
        main(i * 25)

总结

emmm似乎也没什么好总结的,正则表达式还是很好用的。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用urllib、bs4、re、pymysql来爬取豆瓣250的列表页面信息的代码示例: ```python import urllib.request from bs4 import BeautifulSoup import pymysql # 连接数据 db = pymysql.connect(host='localhost', user='root', password='password', db='test', charset='utf8') # 获取页面HTML代码 url = 'https://movie.douban.com/top250' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'} req = urllib.request.Request(url=url, headers=headers) response = urllib.request.urlopen(req) html = response.read().decode('utf-8') # 使用BeautifulSoup解析HTML代码 soup = BeautifulSoup(html, 'html.parser') movie_list = soup.find('ol', class_='grid_view').find_all('li') # 遍历电影列表,获取电影信息并保存到数据 for movie in movie_list: # 获取电影排名、电影名称、电影评分、电影链接 rank = movie.find('em').get_text() title = movie.find('span', class_='title').get_text() rating = movie.find('span', class_='rating_num').get_text() link = movie.find('a')['href'] # 使用正则表达式获取电影年份、电影类型等信息 info = movie.find('p', class_='').get_text() year = re.findall('\d{4}', info)[0] types = re.findall('\s/\s(.*)', info)[0] # 插入数据到数据 cursor = db.cursor() sql = "INSERT INTO movies(rank, title, rating, link, year, types) VALUES('%s', '%s', '%s', '%s', '%s', '%s')" % (rank, title, rating, link, year, types) cursor.execute(sql) db.commit() # 关闭数据连接 db.close() ``` 希望能对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值