获取网页源代码
get方式与post方式
- get方式
在GET方法中,数据将作为URL的参数发送,这些参数通常是由&符号分隔的名称和值对的字符串。通常,具有GET数据的URL将如下所示:
http://www.php.cn/action.php?name = john&age = 24
使用GET方法的优点和缺点
1、由于GET方法发送的数据显示在URL中,因此可以使用特定查询字符串值为页面添加书签。
2、GET方法不适合传递用户名和密码等敏感信息,因为这些信息在URL查询字符串中完全可见,并且可能作为访问页存储在客户端浏览器的内存中。
3、由于GET方法将数据分配给服务器环境变量,因此URL的长度是有限的。因此,要发送的总数据存在限制。
- post方式
在POST方法中,数据作为包在与处理脚本的单独通信中发送到服务器;通过POST方法发送的数据在URL中不可见。
POST方法适用于可以传递大量信息的情况。当服务器通过采用POST的表单接收请求时,它在对URL进行请求之后立即传输表单输入的所有相关信息。
如一些页面,只能通过从另一个页面单击某个链接或者某个按钮以后跳过来,不能直接通过在浏览器输入网址访问,这种网页就是使用了POST方式。
使用POST方法的优点和缺点
1、它比GET更安全,因为用户输入的信息在URL查询字符串或服务器日志中永远不可见。
2、可以传递的数据量有一个更大的限制,一个人可以使用POST发送文本数据和二进制数据(上传文件)。
3、由于POST方法发送的数据在URL中不可见,因此无法使用特定查询为页面添加书签。
GET方法主要用于获取信息。而,POST方法主要用于更新数据
使用get方式请求数据
import requests html = requests.get(URL) html_bytes = html.content#获取网页源代码的二进制数据 html_str = html_bytes.decode()#对二进制数据进行解码,常见解码方式有GBK,GB2312,GB18030,默认为UTF-8
使用post方式请求数据
import requests data = {'key1': 'value1', 'key2': 'value2'} html_formdata = requests.post(’网址’, data=data).content.decode() #用formdata提交数据
多线程爬虫
API介绍
from multiprocessing.dummy import Pool
Pool类可创建一个线程池
Pool下的map方法可让线程池的所有线程都支持同一个“函数”
代码实例
from multiprocessing.dummy import Pool def calc_power2(num): return num * num pool = Pool(3)#创建三个线程池 origin_num = [x for x in range(10)] result = pool.map(calc_power2, origin_num)#第一个参数是执行函数名称,第二个参数是给该函数传入的参数列表,必须为可迭代对象 print(f’计算0-9的平方分别为:{result}')
数据解析之Xpath
xpath解析原理
实例化一个etree对象,将源码数据放到etree对象
调用etree对象的xpath方法对元素进行定位和数据捕捉
实例化etree对象
加载本地html文件
from lxml import etree etree.parse(filepath)
加载从网站中响应到的源码数据
etree.HTML(page_text)
Xpath表达式
/
从根节点开始定位,表示单个层级
//
从某标签节点下的任意节点定位,表示多层级
属性定位
//div[@class=’属性值’]
//div[@id=’属性值’]
索引定位
//div[@class=’song’]/p[3]#获取class属性为song的div标签下的第三个p标签
范围定位
//div[position()<n]#获取前n-1个div标签
//div[last()]#获取最后一个div标签
获取标签文本
/text() 获取标签中的直系文本
//text() 获取标签下的所有文本内容
获取标签属性
/@attrNAME
如:/div/@class /a/@href
案例1:抓取豆瓣电影信息
# -*- codeing=utf-8 -*-
# @Author:姜磊
# 人间烟火气,最抚凡人心
import requests
# import lxml.html as lh
from lxml import etree
import chardet
from multiprocessing.dummy import Pool
times=input('输入抓取页面数:')
startUrl='https://movie.douban.com/top250?start='
urls=[]
for page in range(int(times)):
urls.append(startUrl+str(25*page))
#获取网页源代码
def getHtml(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.622"
}
# requests.get(url)获取响应,.content获取网页二进制编码内容
html_b = requests.get(url,headers=headers).content
# chardet.detect(html_b)#检测二进制代码的编码方式
# print(chardet.detect(html_b))
html = html_b.decode()
return html
html=getHtml(startUrl)
# print(html)
# 多线程访问多个页面
pool=Pool(5)
htmls=pool.map(getHtml,urls)
pool.close()
pool.join()
# 抓取页面信息
def XpathGetInfo(html):
html_xpath=etree.HTML(html)#将html页面转换为xpath结构
data=html_xpath.xpath('//ol[@class="grid_view"]/li')
results=[]
# 获取一页的电影信息
for i in range(len(data)):
res = {}
info=data[i].xpath('.//div[@class="hd"]')
# print(blockInfo)
# 获取电影链接
href=info[0].xpath('.//a/@href')[0]
# 获取电影名称
name=info[0].xpath('.//a/span[@class="title"]/text()')[0]
starInfo=data[i].xpath('.//div[@class="bd"]')
star=starInfo[0].xpath('.//span[@class="rating_num" and @property="v:average"]/text()')[0]
res['name']=name
res['href']=href
res['star']=star
results.append(res)
return results
pool=Pool(5)
res=pool.map(XpathGetInfo,htmls)
#抓取times页电影信息
for i in range(int(times)):
print(res[i])
案例2:58二手房信息
# -*- codeing=utf-8 -*-
# @Author:姜磊
# 人间烟火气,最抚凡人心
import requests
from lxml import etree
import re
import pandas as pd
url='https://bj.58.com/ershoufang/'
headers={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.77'
}
# 获取网页源代码
html=requests.get(url,headers=headers).text
# 构造xpath对象
tree=etree.HTML(html)
homes=tree.xpath('//*[@id="esfMain"]/section/section[3]/section[1]/section[2]/div')
res=[]
for home in homes:
house=[]
home_essage=home.xpath('./a/div[2]/div[1]/section')[0]
# 房子结构
structMessage=home_essage.xpath('./div[1]/p[1]/span/text()')
struct=''.join(structMessage)
# print(struct)
# 房子大小
size=home_essage.xpath('./div[1]/p[2]/text()')[0].strip()#strip()函数用于清除换行符
# print(size)
# 方向
direction=home_essage.xpath('./div[1]/p[3]/text()')[0].strip()
# print(direction)
# 所在楼层
floors=home_essage.xpath('./div[1]/p[4]/text()')
if len(floors)>0:
floor=floors[0].strip()
else:
floor=''
# 建造时间
madetimes=home_essage.xpath('./div[1]/p[5]/text()')
if len(madetimes)>0:
madetime=madetimes[0].strip()
else:
madetime=''
# print(madetime)
# 房子名称
name=home_essage.xpath('./div[2]/p[1]/text()')[0]
# print(name)
# 地址
addresMessage=home_essage.xpath('./div[2]/p[2]/span/text()')
# print(addresMessage)
addres='-'.join(addresMessage)
house.extend([name,struct,size,direction,floor,madetime,addres])#构造单个房源信息列表
res.append(house)
data=pd.DataFrame(res,columns=['名称','结构','大小','方向','楼层','建造时间','地理位置'])
print(data)
# data.to_excel('res.xlsx',index=False,encoding='utf_8_sig')